Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
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 | |
| 8 | declare(strict_types=1); |
| 9 | |
| 10 | require_once __DIR__.'/InvoiceMail.php'; |
| 11 | require_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 | */ |
| 28 | return 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 | }; |