fix: PDF via JSON-RPC render, full-width table with nowrap columns

PDF download:
- Drop HTTP Basic Auth approach (Odoo's /report/pdf/ endpoint rejects it)
- Call ir.actions.report.render_qweb_pdf() via the already-working
  authenticated JSON-RPC connection; returns base64-encoded PDF bytes
- Validate base64_decode result starts with %PDF before serving
- Descriptive Spanish error messages for each failure point

Table layout:
- Remove table-layout:fixed which was squashing columns into WC's
  ~650px content column
- Add min-width:820px so table never compresses below readable width
  (scrolls horizontally on small screens instead)
- .woodoo-invoices breaks out 100px into page margins on desktop
  (margin: 0 -100px; width: calc(100% + 200px)) for full-width feel
- Reverts to 100% width below 960px
- All key columns use white-space:nowrap + min-width so invoice
  reference, dates and amounts never wrap to multiple lines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Malin
2026-04-01 17:34:34 +02:00
parent 02c8fee174
commit 84e6195f3a
2 changed files with 50 additions and 35 deletions

View File

@@ -131,33 +131,30 @@ class WooDoo_Invoices {
wp_die( esc_html__( 'Invoice not found.', 'woodoo' ) );
}
// Fetch the PDF via HTTP Basic Auth (API key as password supported in Odoo 17+).
// This avoids the fragile session-cookie approach entirely.
$odoo_url = rtrim( get_option( 'woodoo_odoo_url', '' ), '/' );
$pdf_url = $odoo_url . '/report/pdf/account.report_invoice/' . $invoice_id;
$basic_auth = 'Basic ' . base64_encode(
get_option( 'woodoo_odoo_username', '' ) . ':' . get_option( 'woodoo_odoo_api_key', '' )
// Use the authenticated JSON-RPC connection to render the PDF.
// Odoo's /report/pdf/ HTTP endpoint only accepts session cookies, not API keys.
// Calling ir.actions.report.render_qweb_pdf() via execute_kw works with any
// valid authenticated user and returns the PDF content base64-encoded.
$result = $api->execute_kw(
'ir.actions.report',
'render_qweb_pdf',
[ 'account.report_invoice', [ $invoice_id ] ]
);
$pdf_response = wp_remote_get(
$pdf_url,
[
'headers' => [ 'Authorization' => $basic_auth ],
'timeout' => 90,
'sslverify' => apply_filters( 'woodoo_ssl_verify', true ),
]
);
if ( is_wp_error( $pdf_response ) ) {
wp_die( 'No se pudo obtener el PDF de la factura: ' . esc_html( $pdf_response->get_error_message() ) );
if ( is_wp_error( $result ) ) {
wp_die( 'Error de Odoo al generar el PDF: ' . esc_html( $result->get_error_message() ) );
}
$http_code = wp_remote_retrieve_response_code( $pdf_response );
$pdf_body = wp_remote_retrieve_body( $pdf_response );
// Result is [base64_pdf_string, 'pdf']
$b64 = is_array( $result ) ? ( $result[0] ?? '' ) : $result;
if ( empty( $b64 ) ) {
wp_die( 'Odoo devolvió una respuesta vacía al generar el PDF.' );
}
// Guard: Odoo may return a JSON error or HTML login page instead of a PDF
if ( $http_code !== 200 || substr( $pdf_body, 0, 4 ) !== '%PDF' ) {
wp_die( 'No se pudo generar el PDF. Código HTTP: ' . esc_html( $http_code ) . '. Comprueba los permisos del usuario de la API en Odoo.' );
$pdf_body = base64_decode( $b64, true );
if ( $pdf_body === false || substr( $pdf_body, 0, 4 ) !== '%PDF' ) {
wp_die( 'El contenido recibido de Odoo no es un PDF válido. Comprueba que el usuario de la API tenga permisos de impresión en Odoo.' );
}
header( 'Content-Type: application/pdf' );