From 076103ee3662341b30e0d0ddb04206386e0315f7 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Mon, 26 Jan 2026 14:59:49 +0100 Subject: [PATCH] wip #7957 @0.5 --- app/Fluidbook/Compiler/Cart.php | 20 ++ .../Services/NewHeidiOperation.php | 228 ++++++++++++++++++ app/Models/Traits/PublicationSettings.php | 1 + 3 files changed, 249 insertions(+) create mode 100644 app/Http/Controllers/Admin/Operations/FluidbookPublication/Services/NewHeidiOperation.php diff --git a/app/Fluidbook/Compiler/Cart.php b/app/Fluidbook/Compiler/Cart.php index 354016b05..1ce59eb1d 100644 --- a/app/Fluidbook/Compiler/Cart.php +++ b/app/Fluidbook/Compiler/Cart.php @@ -798,6 +798,9 @@ trait Cart case 'Kimplay': $this->writeKimplayCart(); break; + case 'NewHeidi': + $this->writeNewHeidiCart(); + break; default: break; } @@ -904,4 +907,21 @@ trait Cart $this->config->basketReferences = $references; } + + public function writeNewHeidiCart() + { + + $this->addFontKit('InstrumentSans'); + $this->lessVariables['import-cart-styles'] = 'newheidi'; + $this->addJsLib('newheidi', 'js/libs/fluidbook/cart/fluidbook.cart.newheidi.js'); + + $refs = ExcelToArray::excelToArrayKeyVars($this->wdir . 'commerce/' . $this->config->basketReferences); + + $references = []; + foreach ($refs as $ref => $data) { + $references[$ref] = ['reference' => $ref, 'name' => $data['DESIGNATION'], 'batch' => $data['LOT'], 'price' => (float)$data['PRIX']]; + } + + $this->config->basketReferences = $references; + } } diff --git a/app/Http/Controllers/Admin/Operations/FluidbookPublication/Services/NewHeidiOperation.php b/app/Http/Controllers/Admin/Operations/FluidbookPublication/Services/NewHeidiOperation.php new file mode 100644 index 000000000..1e07445fa --- /dev/null +++ b/app/Http/Controllers/Admin/Operations/FluidbookPublication/Services/NewHeidiOperation.php @@ -0,0 +1,228 @@ +middleware([CORSMiddleware::class])->withoutMiddleware([CheckIfAdmin::class, Authenticate::class, VerifyCsrfToken::class]); + } + } + + public function newheidi(Request $request) + { + + $validator = Validator::make($request->all(), [ + 'company' => 'required|max:255', + 'name' => 'required|string|max:255', + 'mail' => 'required|email', + 'phone' => 'required', + ], [ + 'required' => 'Ce champ est obligatoire', + 'email' => 'Adresse email incorrecte' + ]); + + $validated = $validator->validated(); + + $formData = [ + 'Nom de l\'entreprise' => request('company'), + 'Nom' => request('name'), + 'Prénom' => request('firstname'), + 'Email' => request('mail'), + 'Téléphone' => request('phone'), + 'Adresse' => request('address'), + 'Message' => request('message'), + ]; + + if (empty(request('cart_items'))) { + die('Error: invalid data received'); + } + + $cart_items = json_decode(request('cart_items'), true); + $file = $this->getCsv($cart_items, $formData); + $this->sendMail($file, request('mail')); + } + + public function getCsv($cart_items, $user_details) + { + $column_headings = [ + 'ref' => 'Réference', + 'name' => 'Désignation', + 'quantity' => 'Quantité', + 'comment' => 'Commentaire' + ]; + + $excel = new Spreadsheet(); + $excel->setActiveSheetIndex(0); + $defaultStyle = $excel->getDefaultStyle(); + $defaultStyle->getAlignment()->setVertical(Alignment::VERTICAL_CENTER); + $defaultStyle->getAlignment()->setWrapText(true); + $defaultStyle->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_TEXT); + $sheet = $excel->getActiveSheet(); + $sheet->setTitle('Récapitulatif de demande'); + $sheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); + $sheet->getPageSetup()->setFitToPage(true); + + // Setup column headings + $current_column_index = 1; + $current_row = 1; + $sheet->getRowDimension(1)->setRowHeight(22); // Larger row height for headings + foreach ($column_headings as $column_heading) { + $sheet->setCellValueByColumnAndRow($current_column_index, $current_row, $column_heading); + $cell_style = $sheet->getStyleByColumnAndRow($current_column_index, $current_row); + $cell_style->getFont()->setBold(true); + $cell_style->getBorders()->getBottom()->setBorderStyle(Border::BORDER_MEDIUM); + $current_column_index++; + } + + // Output cart data + foreach ($cart_items as $key => $cart_item) { + $current_row++; + + // Set a slightly larger row height to give better vertical spacing + $sheet->getRowDimension($current_row)->setRowHeight(22); + + // Look up the value by the column keys to ensure the correct order of values + foreach (array_keys($column_headings) as $column_index => $column_key) { + + $current_cell_style = $sheet->getStyleByColumnAndRow($column_index + 1, $current_row); + + switch ($column_key) { + case 'ref': + $sheet->setCellValueByColumnAndRow($column_index + 1, $current_row, $key); + break; + case 'quantity': + $sheet->setCellValueByColumnAndRow($column_index + 1, $current_row, $cart_item[$column_key]); + $current_cell_style->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_NUMBER); + break; + default: + $sheet->setCellValueByColumnAndRow($column_index + 1, $current_row, $cart_item[$column_key]); + } + + } + } + + // Autosize columns once the data has been added + for ($i = 1; $i <= count($column_headings); $i++) { + $sheet->getColumnDimensionByColumn($i)->setAutoSize(true); + } + + $details_sheet = $excel->addSheet(new Worksheet($excel, 'Coordonnées'), 0); // Setting index to zero will put this sheet first in the workbook + + $current_row = 1; + foreach ($user_details as $key => $value) { + // User details are displayed as Label: Value in the A & B columns + $details_label_style = $details_sheet->getStyleByColumnAndRow(1, $current_row); + $details_label_style->getFont()->setBold(true); + $details_label_style->getAlignment()->setWrapText(false); + $details_label_style->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT); + $details_label_style->getAlignment()->setVertical(Alignment::VERTICAL_TOP); + + // Top align the values because we'll be using a slightly larger row height + $details_value_style = $details_sheet->getStyleByColumnAndRow(2, $current_row); + $details_value_style->getAlignment()->setVertical(Alignment::VERTICAL_TOP); + + // Set values + $details_sheet->setCellValueByColumnAndRow(1, $current_row, $key . ' :'); + $details_sheet->setCellValueByColumnAndRow(2, $current_row, $value); + + // $details_sheet->getStyleByColumnAndRow(1, $current_row)->getAlignment()->setWrapText(true); + // $details_sheet->getRowDimension($current_row)->setRowHeight(-1); // Auto row height from content + + // Unfortunately, LibreOffice has a long-standing bug where auto row height doesn't work :( + // Ref: https://github.com/PHPOffice/PHPExcel/issues/588#issuecomment-249544915 + // Since we may have multi-line text for the address and message, we need to figure out how high + // the row should be, based on the number of lines. The default row height is 12.75pt + // Ref: https://github.com/PHPOffice/PHPExcel/blob/1.8/Documentation/markdown/Overview/08-Recipes.md#setting-a-rows-height + $single_row_height = 12.75; // Basis for a single line of text + $line_count = count(explode("\n", $value)); + // Add a slight extra buffer to row height (+3) so it isn't tight against the next one + $details_sheet->getRowDimension($current_row)->setRowHeight($line_count * $single_row_height + 3); + + $current_row++; + } + + // Auto-size both columns + $details_sheet->getColumnDimensionByColumn(1)->setAutoSize(true); + $details_sheet->getColumnDimensionByColumn(2)->setAutoSize(true); + + $xls_writer = new Xlsx($excel); + $xls_file = Files::tempnam(); + $xls_writer->save($xls_file); + + return $xls_file; + } + + public function sendMail($xls_file, $user_email) + { + + $admin = 'test@fluidbook.com'; + + $email_for_newheidi = $admin; + $return_address = 'toolbox@fluidbook.com'; + $email_from_name = "Kim'Play"; + $email_reply_to = $admin; + $email_newheidi_subject = 'Demande catalogue Kim\'Play'; + $email_user_subject = 'Récapitulatif de votre demande Kim\'Play'; + $email_to_user_body = "Bonjour,

Votre demande est en cours de traitement (récapitulatif en pièce jointe). Nous vous recontacterons dans les meilleurs délais. D’ici là nous restons joignables pour toute question à l’adresse : info@cofalu.com

Cordialement,

L'équipe commerciale"; + $email_to_newheidi_body = "Bonjour,

Une commande a été passée (récapitulatif en pièce jointe).

Cordialement

"; + + // Filename for attachment (without extension) + $orderId = date('YmdHis'); + $attachment_basename = "Kim'Play" . $orderId; + + //=== Send the email + // There are two almost identical e-mails sent: + // - E-mail to Bastide, containing the request details in XLS format + // - E-mail to the user, containing the same information but converted to PDF format + $mail_to_newheidi = new Base(); + $mail_to_newheidi->from($return_address, $email_from_name); + $mail_to_newheidi->replyTo($email_reply_to, $email_from_name); + $mail_to_newheidi->subject($email_newheidi_subject); + $mail_to_newheidi->html($email_to_newheidi_body); + $mail_to_newheidi->attach($xls_file, ['as' => $attachment_basename . '.xlsx', 'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + + // Duplicate the common e-mail settings and apply them to the user e-mail + $mail_to_user = clone $mail_to_newheidi; + $mail_to_user->to($user_email); + $mail_to_user->subject($email_user_subject); + $mail_to_user->html($email_to_user_body); + + // Back to setting up the mail for NewHeidi + $mail_to_newheidi->to($email_for_newheidi); + + //=== Send the e-mails + try { + Mail::send($mail_to_newheidi); + Mail::send($mail_to_user); + return true; + } catch (Exception $e) { + Log::warn('#### NewHeidi: Failed sending message via Mailjet ####'); + Log::warn('ERROR: ' . $e->getMessage()); + return false; + } + + } +} diff --git a/app/Models/Traits/PublicationSettings.php b/app/Models/Traits/PublicationSettings.php index fee462446..86896cb46 100644 --- a/app/Models/Traits/PublicationSettings.php +++ b/app/Models/Traits/PublicationSettings.php @@ -1490,6 +1490,7 @@ trait PublicationSettings 'BastideResah' => 'Bastide Resah', 'BastideResahGuest' => 'Bastide Resah (invité)', 'Kimplay' => 'Kim\'Play', + 'NewHeidi'=>'New Heidi', ], 'default' => 'com.fluidbook.player.basket.BasketManager', ]); -- 2.39.5