fix(orders): copy order lines into invoice on creation
POST /invoices with only fk_commande+socid creates an empty invoice. Lines must be included in the request body explicitly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
312829e5f4
commit
c02e771f0a
|
|
@ -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
|
||||
* <p>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.</p>
|
||||
*
|
||||
* @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<String, Object> body = Map.of("fk_commande", orderId, "socid", socid);
|
||||
public DolibarrInvoiceDto createInvoiceFromOrder(DolibarrOrderDto order) {
|
||||
log.debug("Creating Dolibarr invoice from orderId={}", order.id());
|
||||
|
||||
List<DolibarrInvoiceDto.InvoiceLine> 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<InvoiceLine> 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
|
||||
) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue