feat: add DTOs, Dolibarr response types and mappers for Contacts, Clients, Setup and invoice lines

- New command DTOs: CreateClientDto, UpdateClientDto, CreateContactDto,
  UpdateContactDto, UpdateInvoiceLineDto
- New query DTOs: ClientDetailDto, ContactDetailDto, Setup dictionaries
  (PaymentTypeDto, CountryDto, CivilityDto, ContactTypeDto,
  PaymentTermDto, CompanyDto)
- New Dolibarr response types for setup endpoints
- SetupMapper for all dictionary transforms
- Extended ClientResponse and ContactResponse with additional fields
  (address, town, zip, country_code, note_public, note_private, etc.)
- ClientMapper: added MapToClientDetailDto for GET /Clients/{id}
- ContactMapper: added MapToContactDetailDto for GET /Contacts/{id}
This commit is contained in:
JavMB 2026-05-15 18:58:26 +02:00
parent e58b6c0679
commit 32028e21e1
25 changed files with 484 additions and 21 deletions

View File

@ -3,21 +3,19 @@ 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; }
// Tipo de entidad
public string? typent_code { get; set; }
// Estado
public string? status { get; set; }
// Contacto
public string? email { get; set; }
public string? phone { get; set; }
public string? address { get; set; }
public string? zip { get; set; }
public string? town { get; set; }
public string? country_code { get; set; }
public string? tva_intra { get; set; }
public string? url { get; set; }
public string? note_public { get; set; }
public string? note_private { get; set; }
public string? client { get; set; }
}

View File

@ -3,18 +3,16 @@ 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; }
public string? address { get; set; }
public string? zip { get; set; }
public string? town { get; set; }
public string? civility_code { get; set; }
public string? statut { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class CivilityResponse
{
public string? id { get; set; }
public string? code { get; set; }
public string? label { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class CompanyResponse
{
public string? name { get; set; }
public string? address { get; set; }
public string? town { get; set; }
public string? zip { get; set; }
public string? country { get; set; }
public string? phone { get; set; }
public string? email { get; set; }
public string? idprof1 { get; set; }
public string? tva_intra { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class ContactTypeResponse
{
public string? id { get; set; }
public string? code { get; set; }
public string? label { get; set; }
public string? module { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class CountryResponse
{
public string? id { get; set; }
public string? code { get; set; }
public string? label { get; set; }
public string? code_iso { get; set; }
public string? numeric_code { get; set; }
public string? active { get; set; }
public string? eec { get; set; }
public string? favorite { get; set; }
}

View File

@ -0,0 +1,12 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class PaymentTermResponse
{
public string? id { get; set; }
public string? code { get; set; }
public string? label { get; set; }
public string? descr { get; set; }
public string? nbjour { get; set; }
public string? type_cdr { get; set; }
public string? module { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace DoliMiddlewareApi.Dtos.Dolibarr.Setup;
public class PaymentTypeResponse
{
public string? id { get; set; }
public string? code { get; set; }
public string? type { get; set; }
public string? label { get; set; }
public string? module { get; set; }
}

View File

@ -0,0 +1,42 @@
using System.ComponentModel.DataAnnotations;
namespace DoliMiddlewareApi.Dtos.command;
public class CreateClientDto
{
[Required]
[StringLength(200)]
public string Name { get; set; } = "";
[StringLength(50)]
public string? Address { get; set; }
[StringLength(50)]
public string? Zip { get; set; }
[StringLength(50)]
public string? Town { get; set; }
[StringLength(20)]
public string? Phone { get; set; }
[EmailAddress]
[StringLength(200)]
public string? Email { get; set; }
[StringLength(50)]
public string? CountryCode { get; set; }
[StringLength(50)]
public string? VatNumber { get; set; }
[Url]
[StringLength(255)]
public string? Url { get; set; }
[StringLength(500)]
public string? NotePublic { get; set; }
[StringLength(500)]
public string? NotePrivate { get; set; }
}

View File

@ -0,0 +1,38 @@
using System.ComponentModel.DataAnnotations;
namespace DoliMiddlewareApi.Dtos.command;
public class CreateContactDto
{
[Required]
[StringLength(100)]
public string Lastname { get; set; } = "";
[StringLength(100)]
public string? Firstname { get; set; }
[Range(1, int.MaxValue)]
public int ClientId { get; set; }
[EmailAddress]
[StringLength(200)]
public string? Email { get; set; }
[StringLength(50)]
public string? PhonePro { get; set; }
[StringLength(50)]
public string? PhonePerso { get; set; }
[StringLength(50)]
public string? PhoneMobile { get; set; }
[StringLength(255)]
public string? Address { get; set; }
[StringLength(50)]
public string? Zip { get; set; }
[StringLength(50)]
public string? Town { get; set; }
}

View File

@ -0,0 +1,41 @@
using System.ComponentModel.DataAnnotations;
namespace DoliMiddlewareApi.Dtos.command;
public class UpdateClientDto
{
[StringLength(200)]
public string? Name { get; set; }
[StringLength(50)]
public string? Address { get; set; }
[StringLength(50)]
public string? Zip { get; set; }
[StringLength(50)]
public string? Town { get; set; }
[StringLength(20)]
public string? Phone { get; set; }
[EmailAddress]
[StringLength(200)]
public string? Email { get; set; }
[StringLength(50)]
public string? CountryCode { get; set; }
[StringLength(50)]
public string? VatNumber { get; set; }
[Url]
[StringLength(255)]
public string? Url { get; set; }
[StringLength(500)]
public string? NotePublic { get; set; }
[StringLength(500)]
public string? NotePrivate { get; set; }
}

View File

@ -0,0 +1,34 @@
using System.ComponentModel.DataAnnotations;
namespace DoliMiddlewareApi.Dtos.command;
public class UpdateContactDto
{
[StringLength(100)]
public string? Lastname { get; set; }
[StringLength(100)]
public string? Firstname { get; set; }
[EmailAddress]
[StringLength(200)]
public string? Email { get; set; }
[StringLength(50)]
public string? PhonePro { get; set; }
[StringLength(50)]
public string? PhonePerso { get; set; }
[StringLength(50)]
public string? PhoneMobile { get; set; }
[StringLength(255)]
public string? Address { get; set; }
[StringLength(50)]
public string? Zip { get; set; }
[StringLength(50)]
public string? Town { get; set; }
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
using System.Globalization;
namespace DoliMiddlewareApi.Dtos.command;
public class UpdateInvoiceLineDto
{
[StringLength(500)]
public string? Description { get; set; }
[Range(0.01, double.MaxValue)]
public decimal? Quantity { get; set; }
[Range(0, double.MaxValue)]
public decimal? UnitPrice { get; set; }
[Range(0, 100)]
public decimal? TaxRate { get; set; }
}

View File

@ -0,0 +1,21 @@
namespace DoliMiddlewareApi.Dtos.query;
public class ClientDetailDto
{
public int Id { get; set; }
public required string Name { get; set; }
public string? CodeClient { get; set; }
public string? TypentCode { get; set; }
public string? Status { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string? Address { get; set; }
public string? Town { get; set; }
public string? Zip { get; set; }
public string? CountryCode { get; set; }
public string? VatNumber { get; set; }
public string? Url { get; set; }
public string? NotePublic { get; set; }
public string? NotePrivate { get; set; }
public List<ContactDto> Contacts { get; set; } = new();
}

View File

@ -0,0 +1,18 @@
namespace DoliMiddlewareApi.Dtos.query;
public class ContactDetailDto
{
public int Id { get; set; }
public string? Lastname { get; set; }
public string? Firstname { get; set; }
public string? Email { set; get; }
public string? PhonePro { get; set; }
public string? PhonePerso { get; set; }
public string? PhoneMobile { get; set; }
public int ClientId { get; set; }
public string? Address { get; set; }
public string? Town { get; set; }
public string? Zip { get; set; }
public string? CivilityCode { get; set; }
public string? Status { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class CivilityDto
{
public string? Id { get; set; }
public string? Code { get; set; }
public string? Label { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class CompanyDto
{
public string? Name { get; set; }
public string? Address { get; set; }
public string? Town { get; set; }
public string? Zip { get; set; }
public string? Country { get; set; }
public string? Phone { get; set; }
public string? Email { get; set; }
public string? VatNumber { get; set; }
public string? Siren { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class ContactTypeDto
{
public string? Id { get; set; }
public string? Code { get; set; }
public string? Label { get; set; }
}

View File

@ -0,0 +1,11 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class CountryDto
{
public string? Id { get; set; }
public string? Code { get; set; }
public string? Label { get; set; }
public string? CodeIso { get; set; }
public string? NumericCode { get; set; }
public bool Active { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class PaymentTermDto
{
public string? Id { get; set; }
public string? Code { get; set; }
public string? Label { get; set; }
public string? Description { get; set; }
public string? Nbjour { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace DoliMiddlewareApi.Dtos.query.Setup;
public class PaymentTypeDto
{
public string? Id { get; set; }
public string? Code { get; set; }
public string? Label { get; set; }
public string? Type { get; set; }
}

View File

@ -3,9 +3,8 @@ using DoliMiddlewareApi.Dtos.query;
namespace DoliMiddlewareApi.Mappers;
public class ClientMapper
public static class ClientMapper
{
public static ClientDto MapToClientDto(ClientResponse clientResponse, List<ContactDto> contacts)
{
var clientId = int.TryParse(clientResponse.id, out int id) ? id : 0;
@ -37,4 +36,28 @@ public class ClientMapper
};
}
public static ClientDetailDto MapToClientDetailDto(ClientResponse r, List<ContactDto> contacts)
{
var clientId = int.TryParse(r.id, out int id) ? id : 0;
return new ClientDetailDto
{
Id = clientId,
Name = r.name ?? "",
CodeClient = r.code_client,
TypentCode = r.typent_code,
Status = r.status,
Email = r.email,
Phone = r.phone,
Address = r.address,
Town = r.town,
Zip = r.zip,
CountryCode = r.country_code,
VatNumber = r.tva_intra,
Url = r.url,
NotePublic = r.note_public,
NotePrivate = r.note_private,
Contacts = contacts.Where(c => c.ClientId == clientId).ToList()
};
}
}

View File

@ -3,7 +3,7 @@ using DoliMiddlewareApi.Dtos.query;
namespace DoliMiddlewareApi.Mappers;
public class ContactMapper
public static class ContactMapper
{
public static ContactDto MapToContactDto(ContactResponse contactResponse)
{
@ -19,4 +19,29 @@ public class ContactMapper
ClientId = int.TryParse(contactResponse.fk_soc, out int clientId) ? clientId : 0
};
}
public static ContactDetailDto MapToContactDetailDto(ContactResponse r)
{
return new ContactDetailDto
{
Id = int.TryParse(r.id, out int id) ? id : 0,
Lastname = r.lastname,
Firstname = r.firstname,
Email = r.email,
PhonePro = r.phone_pro,
PhonePerso = r.phone_perso,
PhoneMobile = r.phone_mobile,
ClientId = int.TryParse(r.fk_soc, out int clientId) ? clientId : 0,
Address = r.address,
Town = r.town,
Zip = r.zip,
CivilityCode = r.civility_code,
Status = r.statut switch
{
"0" => "inactive",
"1" => "active",
_ => r.statut
}
};
}
}

View File

@ -96,6 +96,7 @@ public static class InvoiceMapper
"0" => "draft",
"1" => "unpaid",
"2" => "paid",
"3" => "cancelled",
_ => "unknown"
};
}

View File

@ -0,0 +1,79 @@
using DoliMiddlewareApi.Dtos.Dolibarr.Setup;
using DoliMiddlewareApi.Dtos.query.Setup;
namespace DoliMiddlewareApi.Mappers;
public static class SetupMapper
{
public static PaymentTypeDto MapToPaymentTypeDto(PaymentTypeResponse r)
{
return new PaymentTypeDto
{
Id = r.id,
Code = r.code,
Label = r.label,
Type = r.type
};
}
public static CountryDto MapToCountryDto(CountryResponse r)
{
return new CountryDto
{
Id = r.id,
Code = r.code,
Label = r.label,
CodeIso = r.code_iso,
NumericCode = r.numeric_code,
Active = r.active == "1"
};
}
public static CivilityDto MapToCivilityDto(CivilityResponse r)
{
return new CivilityDto
{
Id = r.id,
Code = r.code,
Label = r.label
};
}
public static ContactTypeDto MapToContactTypeDto(ContactTypeResponse r)
{
return new ContactTypeDto
{
Id = r.id,
Code = r.code,
Label = r.label
};
}
public static PaymentTermDto MapToPaymentTermDto(PaymentTermResponse r)
{
return new PaymentTermDto
{
Id = r.id,
Code = r.code,
Label = r.label,
Description = r.descr,
Nbjour = r.nbjour
};
}
public static CompanyDto MapToCompanyDto(CompanyResponse r)
{
return new CompanyDto
{
Name = r.name,
Address = r.address,
Town = r.town,
Zip = r.zip,
Country = r.country,
Phone = r.phone,
Email = r.email,
VatNumber = r.tva_intra,
Siren = r.idprof1
};
}
}