diff --git a/DoliMiddlewareApi/Controllers/ClientsController.cs b/DoliMiddlewareApi/Controllers/ClientsController.cs new file mode 100644 index 0000000..9cf2987 --- /dev/null +++ b/DoliMiddlewareApi/Controllers/ClientsController.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; +using DoliMiddlewareApi.Dtos.query; +using DoliMiddlewareApi.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace DoliMiddlewareApi.Controllers; + +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class ClientsController(ClientService clientService) : ControllerBase +{ + + [HttpGet] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task>> GetClientes( + [FromQuery] int limit = 50, + [FromQuery] [Range(1, int.MaxValue)] int page = 1) + { + var clients = await clientService.GetClientsAsync(limit, page); + return Ok(clients); + } + + + +} diff --git a/DoliMiddlewareApi/Controllers/InvoicesController.cs b/DoliMiddlewareApi/Controllers/InvoicesController.cs index 7de5683..1623be6 100644 --- a/DoliMiddlewareApi/Controllers/InvoicesController.cs +++ b/DoliMiddlewareApi/Controllers/InvoicesController.cs @@ -10,15 +10,8 @@ namespace DoliMiddlewareApi.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] -public class InvoicesController : ControllerBase +public class InvoicesController(InvoiceService invoiceService) : ControllerBase { - private readonly InvoiceService _invoiceService; - - public InvoicesController(InvoiceService invoiceService) - { - _invoiceService = invoiceService; - } - [HttpGet] [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] @@ -29,7 +22,7 @@ public class InvoicesController : ControllerBase [FromQuery] string? status = null, [FromQuery] [StringLength(100)] string? search = null) { - var invoices = await _invoiceService.GetInvoicesAsync(limit, page, status, search); + var invoices = await invoiceService.GetInvoicesAsync(limit, page, status, search); return Ok(invoices); } @@ -40,7 +33,7 @@ public class InvoicesController : ControllerBase [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task> GetInvoice([Range(1, int.MaxValue)] int id) { - var invoice = await _invoiceService.GetInvoiceAsync(id); + var invoice = await invoiceService.GetInvoiceAsync(id); return Ok(invoice); } @@ -50,7 +43,7 @@ public class InvoicesController : ControllerBase [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task> CreateInvoice([FromBody] CreateInvoiceDto createInvoiceDto) { - var invoiceId= await _invoiceService.CreateInvoiceAsync(createInvoiceDto); + var invoiceId= await invoiceService.CreateInvoiceAsync(createInvoiceDto); return CreatedAtAction(nameof(GetInvoice), new { id = invoiceId }, invoiceId); } @@ -62,7 +55,7 @@ public class InvoicesController : ControllerBase [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task UpdateInvoice([Range(1, int.MaxValue)] int id, [FromBody] UpdateInvoiceDto updateInvoiceDto) { - await _invoiceService.UpdateInvoiceAsync(id, updateInvoiceDto); + await invoiceService.UpdateInvoiceAsync(id, updateInvoiceDto); return NoContent(); } @@ -74,7 +67,7 @@ public class InvoicesController : ControllerBase [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] public async Task> AddInvoiceLine([Range(1, int.MaxValue)] int id, [FromBody] CreateInvoiceLineDto lineDto) { - var result = await _invoiceService.AddInvoiceLineAsync(id, lineDto); + var result = await invoiceService.AddInvoiceLineAsync(id, lineDto); return CreatedAtAction(nameof(GetInvoice), new { id }, result); } } diff --git a/DoliMiddlewareApi/DoliMiddlewareApi.csproj b/DoliMiddlewareApi/DoliMiddlewareApi.csproj index d112c61..08593a2 100644 --- a/DoliMiddlewareApi/DoliMiddlewareApi.csproj +++ b/DoliMiddlewareApi/DoliMiddlewareApi.csproj @@ -23,7 +23,6 @@ - diff --git a/DoliMiddlewareApi/Dtos/Dolibarr/ClientResponse.cs b/DoliMiddlewareApi/Dtos/Dolibarr/ClientResponse.cs new file mode 100644 index 0000000..2eba2e9 --- /dev/null +++ b/DoliMiddlewareApi/Dtos/Dolibarr/ClientResponse.cs @@ -0,0 +1,17 @@ +namespace DoliMiddlewareApi.Dtos.Dolibarr; + +public class ClientResponse +{ + public string? id { get; set; } + + // Nombre comercial / razón social + public string? name { get; set; } + + // Código cliente (CUxxxx) + public string? code_client { get; set; } + + // Contacto + public string? email { get; set; } + public string? phone { get; set; } + +} \ No newline at end of file diff --git a/DoliMiddlewareApi/Dtos/Dolibarr/ContactResponse.cs b/DoliMiddlewareApi/Dtos/Dolibarr/ContactResponse.cs new file mode 100644 index 0000000..851de43 --- /dev/null +++ b/DoliMiddlewareApi/Dtos/Dolibarr/ContactResponse.cs @@ -0,0 +1,20 @@ +namespace DoliMiddlewareApi.Dtos.Dolibarr; + +public class ContactResponse +{ + public string? id { get; set; } + + public string? lastname { get; set; } + + public string? firstname { get; set; } + + public string? email { get; set; } + + public string? phone_pro { get; set; } + + public string? phone_perso { get; set; } + + public string? phone_mobile { get; set; } + + public string? fk_soc { get; set; } +} diff --git a/DoliMiddlewareApi/Dtos/query/ClientDto.cs b/DoliMiddlewareApi/Dtos/query/ClientDto.cs new file mode 100644 index 0000000..5407208 --- /dev/null +++ b/DoliMiddlewareApi/Dtos/query/ClientDto.cs @@ -0,0 +1,10 @@ +namespace DoliMiddlewareApi.Dtos.query; + +public class ClientDto +{ + public int Id { get; set; } + public required string? Name { get; set; } + public required string? CodeClient { get; set; } + + public List Contacts { get; set; } = new(); +} \ No newline at end of file diff --git a/DoliMiddlewareApi/Dtos/query/ContactDto.cs b/DoliMiddlewareApi/Dtos/query/ContactDto.cs new file mode 100644 index 0000000..7e2e390 --- /dev/null +++ b/DoliMiddlewareApi/Dtos/query/ContactDto.cs @@ -0,0 +1,20 @@ +namespace DoliMiddlewareApi.Dtos.query; + +public class ContactDto +{ + public int Id { get; set; } + + public required string? Lastname { get; set; } + + public required string? Firstname { get; set; } + + public required string? Email { get; set; } + + public required string? PhonePro { get; set; } + + public required string? PhonePerso { get; set; } + + public required string? PhoneMobile { get; set; } + + public int ClientId { get; set; } +} diff --git a/DoliMiddlewareApi/Mappers/ClientMapper.cs b/DoliMiddlewareApi/Mappers/ClientMapper.cs new file mode 100644 index 0000000..5ca0cea --- /dev/null +++ b/DoliMiddlewareApi/Mappers/ClientMapper.cs @@ -0,0 +1,32 @@ +using DoliMiddlewareApi.Dtos.Dolibarr; +using DoliMiddlewareApi.Dtos.query; + +namespace DoliMiddlewareApi.Mappers; + +public class ClientMapper +{ + + public static ClientDto MapToClientDto(ClientResponse clientResponse, List contacts) + { + var clientId = int.TryParse(clientResponse.id, out int id) ? id : 0; + + return new ClientDto + { + Id = clientId, + Name = clientResponse.name, + CodeClient = clientResponse.code_client, + Contacts = contacts.Where(c => c.ClientId == clientId).ToList() + }; + } + + public static ClientDto MapToClientDtoWithoutContacts(ClientResponse clientResponse) + { + return new ClientDto + { + Id = int.TryParse(clientResponse.id, out int id) ? id : 0, + Name = clientResponse.name, + CodeClient = clientResponse.code_client + }; + } + +} \ No newline at end of file diff --git a/DoliMiddlewareApi/Mappers/ContactMapper.cs b/DoliMiddlewareApi/Mappers/ContactMapper.cs new file mode 100644 index 0000000..896b364 --- /dev/null +++ b/DoliMiddlewareApi/Mappers/ContactMapper.cs @@ -0,0 +1,22 @@ +using DoliMiddlewareApi.Dtos.Dolibarr; +using DoliMiddlewareApi.Dtos.query; + +namespace DoliMiddlewareApi.Mappers; + +public class ContactMapper +{ + public static ContactDto MapToContactDto(ContactResponse contactResponse) + { + return new ContactDto + { + Id = int.TryParse(contactResponse.id, out int id) ? id : 0, + Lastname = contactResponse.lastname, + Firstname = contactResponse.firstname, + Email = contactResponse.email, + PhonePro = contactResponse.phone_pro, + PhonePerso = contactResponse.phone_perso, + PhoneMobile = contactResponse.phone_mobile, + ClientId = int.TryParse(contactResponse.fk_soc, out int clientId) ? clientId : 0 + }; + } +} diff --git a/DoliMiddlewareApi/Program.cs b/DoliMiddlewareApi/Program.cs index b54beb9..8e99b5c 100644 --- a/DoliMiddlewareApi/Program.cs +++ b/DoliMiddlewareApi/Program.cs @@ -100,6 +100,9 @@ builder.Services.AddScoped(sp => // Servicio de negocio (facturas) builder.Services.AddScoped(); +// Servicio de negocio (clientes) +builder.Services.AddScoped(); + // Servicio de aplicación (orquesta login + cache) builder.Services.AddScoped(); diff --git a/DoliMiddlewareApi/Services/ClientService.cs b/DoliMiddlewareApi/Services/ClientService.cs new file mode 100644 index 0000000..40285db --- /dev/null +++ b/DoliMiddlewareApi/Services/ClientService.cs @@ -0,0 +1,29 @@ +using DoliMiddlewareApi.Dtos.Dolibarr; +using DoliMiddlewareApi.Dtos.query; +using DoliMiddlewareApi.Mappers; +using DoliMiddlewareApi.Services.Clients; + +namespace DoliMiddlewareApi.Services; + +public class ClientService(IDolibarrApiClient dolibarrApiClient) +{ + public async Task> GetClientsAsync( + int limit = 50, + int page = 1) + { + var endpoint = $"thirdparties?limit={limit}&page={page - 1}"; + + var clients = await dolibarrApiClient.GetCollectionAsync(endpoint); + + if (clients.Count == 0) + return clients.Select(ClientMapper.MapToClientDtoWithoutContacts).ToList(); + + var clientIds = string.Join(",", clients.Select(c => c.id).Where(id => !string.IsNullOrEmpty(id))); + + var contactsEndpoint = $"contacts?thirdparty_ids={clientIds}"; + var contacts = await dolibarrApiClient.GetCollectionAsync(contactsEndpoint); + var contactDtos = contacts.Select(ContactMapper.MapToContactDto).ToList(); + + return clients.Select(c => ClientMapper.MapToClientDto(c, contactDtos)).ToList(); + } +} \ No newline at end of file