diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java
index 1d55fc4..a450009 100644
--- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java
+++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/DolibarrClient.java
@@ -9,7 +9,6 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import java.util.List;
-import java.util.Map;
/**
* Typed HTTP client for the Dolibarr REST API.
@@ -182,17 +181,38 @@ public class DolibarrClient {
// ── Invoices ─────────────────────────────────────────────────────────
/**
- * Creates an invoice linked to an existing order.
+ * Creates an invoice linked to an existing Dolibarr order, copying its lines.
*
- * @param orderId Dolibarr internal order ID
- * @param socid customer (thirdparty) internal ID — required by Dolibarr even with fk_commande
+ *
Dolibarr's {@code POST /invoices} does not copy order lines automatically when
+ * only {@code fk_commande + socid} are sent — lines must be included in the body.
+ *
+ * @param order the created order (must have {@code id}, {@code socid}, and {@code lines})
*/
- public DolibarrInvoiceDto createInvoiceFromOrder(Integer orderId, Integer socid) {
- log.debug("Creating Dolibarr invoice from orderId={}", orderId);
- Map body = Map.of("fk_commande", orderId, "socid", socid);
+ public DolibarrInvoiceDto createInvoiceFromOrder(DolibarrOrderDto order) {
+ log.debug("Creating Dolibarr invoice from orderId={}", order.id());
+
+ List invoiceLines = order.lines() == null
+ ? List.of()
+ : order.lines().stream()
+ .map(l -> DolibarrInvoiceDto.InvoiceLine.builder()
+ .fkProduct(l.fkProduct())
+ .productRef(l.productRef())
+ .desc(l.desc())
+ .subprice(l.subprice())
+ .qty(l.qty())
+ .tvaTx(l.tvaTx())
+ .build())
+ .toList();
+
+ DolibarrInvoiceDto invoiceBody = DolibarrInvoiceDto.builder()
+ .fkCommande(order.id())
+ .socid(order.socid())
+ .lines(invoiceLines)
+ .build();
+
Integer newId = restClient.post()
.uri("/invoices")
- .body(body)
+ .body(invoiceBody)
.retrieve()
.body(Integer.class);
diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/dto/DolibarrInvoiceDto.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/dto/DolibarrInvoiceDto.java
index c37b3b1..9a04475 100644
--- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/dto/DolibarrInvoiceDto.java
+++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/dolibarr/dto/DolibarrInvoiceDto.java
@@ -3,18 +3,41 @@ package com.teterialosjuanjos.tfg.sync_service.integration.dolibarr.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+
+import java.util.List;
/**
- * Minimal representation of a Dolibarr invoice.
- * Used for {@code GET /invoices/{id}} responses after creation via {@code POST /invoices}.
+ * Represents a Dolibarr invoice.
+ * Used for {@code POST /invoices} request bodies (with lines) and {@code GET /invoices/{id}} responses.
*/
+@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record DolibarrInvoiceDto(
Integer id,
String ref,
+ Integer socid,
/** Linked order internal ID */
@JsonProperty("fk_commande") Integer fkCommande,
/** 0 = draft, 1 = validated, 2 = paid, 3 = abandoned */
- Integer statut
-) {}
+ Integer statut,
+ List lines
+) {
+
+ /**
+ * One line of an invoice. Mirrors {@link DolibarrOrderDto.OrderLine} fields
+ * so order lines can be copied directly into the invoice on creation.
+ */
+ @Builder
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public record InvoiceLine(
+ @JsonProperty("fk_product") Integer fkProduct,
+ @JsonProperty("product_ref") String productRef,
+ String desc,
+ Double subprice,
+ Double qty,
+ @JsonProperty("tva_tx") Double tvaTx
+ ) {}
+}
diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/sync/OrderSyncService.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/sync/OrderSyncService.java
index b5128ff..6496503 100644
--- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/sync/OrderSyncService.java
+++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/sync/OrderSyncService.java
@@ -130,9 +130,8 @@ public class OrderSyncService {
DolibarrOrderDto createdOrder = dolibarrClient.createOrder(orderDto);
- // 3. Create linked invoice
- DolibarrInvoiceDto invoice = dolibarrClient.createInvoiceFromOrder(
- createdOrder.id(), customer.id());
+ // 3. Create linked invoice with lines copied from the order
+ DolibarrInvoiceDto invoice = dolibarrClient.createInvoiceFromOrder(createdOrder);
// 4. Persist mapping to prevent re-import
orderMappingRepository.save(OrderMapping.builder()