Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
74.12% covered (warning)
74.12%
63 / 85
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3/**
4 * @file
5 * Ticket action: email invoice PDF (and optional Factura-e) to a recipient.
6 */
7
8declare(strict_types=1);
9
10require_once __DIR__.'/InvoiceMail.php';
11require_once __DIR__.'/../legacy/taxes/factura-e.php';
12
13/**
14 * Action callable: authorize session and send invoice email with PDF attachment.
15 *
16 * When query ticket is set and PLACEOPT optionFacturaE is on, attaches signed Factura-e XML.
17 * Generation failure logs a warning and the PDF is still sent (v3 dosend parity).
18 *
19 * @param string $body JSON payload: { pdfdata: string } (base64).
20 * @param array<string, mixed> $query device, session, lang, recipient, invoice, ticket?, place?.
21 * @param \ConxHelper $conx Connection helper.
22 * @param \Psr\Log\LoggerInterface $logger Logger.
23 * @param \UppServices\SessionService $sessionService Session service.
24 * @param callable $emailSend Mail sender seam.
25 * @param string $authMode 'staff' (checkSession) or 'guest' (checkAccess).
26 * @return array{output: string, contentType: string}
27 */
28return function (
29    string $body,
30    array $query,
31    \ConxHelper $conx,
32    \Psr\Log\LoggerInterface $logger,
33    \UppServices\SessionService $sessionService,
34    callable $emailSend,
35    string $authMode = 'staff'
36): array {
37    $retval = \ApplicationError::Success;
38    $pdffile = '';
39    $facturaeXml = null;
40
41    $device = $query['device'] ?? null;
42    if (!$device) {
43        $logger->error("No device provided on URL. Operation cancelled.");
44        $retval = \ApplicationError::Parameters;
45    }
46
47    if (\success($retval)) {
48        $session = $query['session'] ?? null;
49        if (!$session) {
50            $logger->error("No session provided on URL. Operation cancelled.");
51            $retval = \ApplicationError::Parameters;
52        }
53        else {
54            if ($authMode === 'guest') {
55                $qrscanid = null;
56                $retval = $sessionService->checkAccess($conx, (string) $session, (string) $device, $qrscanid);
57            }
58            else {
59                $userid = null;
60                $retval = $sessionService->checkSession($conx, (string) $session, (string) $device, $userid);
61            }
62        }
63    }
64
65    $lang = null;
66    $recipient = null;
67    $invoice = null;
68    if (\success($retval)) {
69        $lang = isset($query['lang']) ? trim((string) $query['lang']) : '';
70        if ($lang === '') {
71            $logger->error("Mandatory parameter 'lang' not provided on URL. Operation cancelled.");
72            $retval = \ApplicationError::Parameters;
73        }
74    }
75    if (\success($retval)) {
76        $recipient = isset($query['recipient']) ? trim((string) $query['recipient']) : '';
77        if ($recipient === '' || !filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
78            $logger->error("Mandatory parameter 'recipient' missing or invalid. Operation cancelled.");
79            $retval = \ApplicationError::Parameters;
80        }
81    }
82    if (\success($retval)) {
83        $invoice = isset($query['invoice']) ? trim((string) $query['invoice']) : '';
84        if ($invoice === '') {
85            $logger->error("Mandatory parameter 'invoice' not provided on URL. Operation cancelled.");
86            $retval = \ApplicationError::Parameters;
87        }
88    }
89
90    if (\success($retval)) {
91        $payload = json_decode($body, true);
92        if (!\is_array($payload) || !isset($payload['pdfdata']) || !\is_string($payload['pdfdata'])) {
93            $logger->error("Invalid JSON payload for ticket invoicesend endpoint.");
94            $retval = \ApplicationError::Parameters;
95        }
96        else {
97            $decoded = base64_decode($payload['pdfdata'], true);
98            if ($decoded === false || $decoded === '') {
99                $logger->error("Empty or invalid pdfdata for ticket invoicesend endpoint.");
100                $retval = \ApplicationError::Parameters;
101            }
102            else {
103                $pdffile = $decoded;
104            }
105        }
106    }
107
108    if (\success($retval)) {
109        $ticket = isset($query['ticket']) ? trim((string) $query['ticket']) : '';
110        if ($ticket !== '') {
111            $place = isset($query['place']) ? trim((string) $query['place']) : '';
112            if ($place === '') {
113                $logger->warning("Ticket provided for invoicesend without place; Factura-e skipped.");
114            }
115            else {
116                $conx->tenant = $place;
117                $ddbb = $conx->tenant;
118                if ($ddbb === null) {
119                    $logger->warning("Tenant connection unavailable for Factura-e; sending PDF only.");
120                }
121                else {
122                    $enabled = false;
123                    $check = _check_facturae_enabled($ddbb, $ticket, $enabled);
124                    if (!\success($check)) {
125                        // Missing ticket / DB while attaching Factura-e must not abort PDF mail.
126                        $logger->warning("Factura-e enabled check failed (errorcode=".$check."); sending PDF only.");
127                    }
128                    elseif ($enabled) {
129                        $logger->info("Ticket provided: attaching Factura-e document.");
130                        $xml = null;
131                        if (!\success(generate_facturae($conx, $ticket, $xml)) || !\is_string($xml) || $xml === '') {
132                            $logger->warning("Factura-E data not available; sending PDF only.");
133                        }
134                        else {
135                            $facturaeXml = $xml;
136                        }
137                    }
138                }
139            }
140        }
141    }
142
143    if (\success($retval)) {
144        if (!ticket_invoice_mail((string) $lang, (string) $recipient, (string) $invoice, $pdffile, $facturaeXml, $emailSend)) {
145            $logger->error("Invoice email send failed for recipient '".$recipient."'.");
146            $retval = \ApplicationError::Generic;
147        }
148    }
149
150    $result = [
151        'errorcode' => $retval,
152    ];
153    return ['output' => json_encode($result), 'contentType' => 'application/json; charset=utf-8'];
154};