custom/plugins/scha1AdditionalProductBasketFields/src/scha1AdditionalProductBasketFields.php line 25

Open in your IDE?
  1. <?php
  2.   declare(strict_types=1);
  3.   namespace scha1\scha1AdditionalProductBasketFields;
  4.   use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  5.   use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  6.   use Shopware\Core\Framework\Plugin;
  7.   use Shopware\Core\Framework\Plugin\Context\InstallContext;
  8.   use Shopware\Core\Framework\Plugin\Context\UninstallContext;
  9.   use Shopware\Core\Framework\Plugin\Context\UpdateContext;
  10.   use Shopware\Core\System\CustomField\CustomFieldTypes;
  11.   
  12.   /**
  13.    * email template
  14.    */
  15.   use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
  16.   use Shopware\Core\Content\MailTemplate\Aggregate\MailTemplateType\MailTemplateTypeEntity;
  17.   use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  18.   use Shopware\Core\Framework\Uuid\Uuid;
  19.   use Shopware\Core\Defaults;
  20.   
  21.   /**
  22.    * 
  23.    */
  24.   class scha1AdditionalProductBasketFields extends Plugin {
  25.     
  26.     const MAX_FIELD 8;
  27.     
  28.     /**
  29.      * email template
  30.      */
  31.     const TEMPLATE_TYPE_NAME 'AdditionalOrderConfirmationMail';
  32.     const TEMPLATE_TYPE_TECHNICAL_NAME 'additional_order_confirmation_mail';
  33.     const MAIL_TEMPLATE_NAME 'AdditionalOrderConfirmationTemplate';
  34.     
  35.     
  36.     /**
  37.      * 
  38.      * @param UpdateContext $updateContext
  39.      */
  40.     public function update(UpdateContext $updateContext): void {
  41. //      parent::activate($updateContext); 
  42.     }
  43.     
  44.     /**
  45.      * 
  46.      * @param UninstallContext $uninstallContext
  47.      * @return void
  48.      */
  49.     public function uninstall(UninstallContext $uninstallContext): void {
  50.       if ($uninstallContext->keepUserData()) {
  51.         parent::uninstall($uninstallContext);
  52.         return;
  53.       }
  54.       $this->deleteCustomFields$uninstallContext->getContext() );
  55.       $this->deleteCustomTemplate$uninstallContext );
  56.       parent::uninstall($uninstallContext);
  57.     }
  58.     
  59.     
  60.     /**
  61.      * 
  62.      * @param type $uninstallContext
  63.      */
  64.     private function deleteCustomTemplate($uninstallContext) {
  65.       /** 
  66.        * @var EntityRepositoryInterface $mailTemplateTypeRepository 
  67.        */
  68.       $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  69.       /** 
  70.        * @var EntityRepositoryInterface $mailTemplateRepository 
  71.        */
  72.       $mailTemplateRepository $this->container->get('mail_template.repository');
  73.       /** 
  74.        * @var MailTemplateTypeEntity $myCustomMailTemplateType 
  75.        */
  76.       $myCustomMailTemplateType $mailTemplateTypeRepository->search( (new Criteria())->addFilter(new EqualsFilter('technicalName'self::TEMPLATE_TYPE_TECHNICAL_NAME)), $uninstallContext->getContext() )->first();
  77.       $mailTemplateIds $mailTemplateRepository->searchIds( (new Criteria())->addFilter(new EqualsFilter('mailTemplateTypeId'$myCustomMailTemplateType->getId())), $uninstallContext->getContext() )->getIds();
  78.       $ids array_map(static function ($id) {
  79.         return ['id' => $id]; 
  80.       }, $mailTemplateIds);
  81.       $mailTemplateRepository->delete($ids$uninstallContext->getContext());
  82.       /**
  83.        * Delete the TemplateType which were added by this Plugin
  84.        */
  85.       $mailTemplateTypeRepository->delete([['id' => $myCustomMailTemplateType->getId()]], $uninstallContext->getContext());
  86.     }
  87.     
  88.     
  89.     /**
  90.      * 
  91.      * @param type $uninstallContext
  92.      */
  93.     private function deleteCustomFields($uninstallContext){
  94.       $customFieldSetRepository $this->container->get('custom_field_set.repository');
  95.       for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  96.         $criteria = new Criteria();
  97.         $criteria->addFilter(new EqualsFilter('name''scha1additionalproductbasketfields' $i));
  98.         $result $customFieldSetRepository->searchIds($criteria$uninstallContext);
  99.         if ($result->getTotal() > 0) {
  100.           $data $result->getDataOfId($result->firstId());
  101.           $customFieldSetRepository->delete([$data], $uninstallContext);
  102.         }
  103.       } 
  104.     }
  105.     
  106.     /**
  107.      * 
  108.      * @param InstallContext $installContext
  109.      */
  110.     public function install(InstallContext $installContext): void{
  111.       $this->addCustomFields$installContext->getContext() );
  112.       $this->addCustomTemplate$installContext );
  113.       parent::install($installContext);
  114.     }
  115.     
  116.     /**
  117.      * 
  118.      * @param type $installContext
  119.      */
  120.     private function addCustomTemplate($installContext) {
  121.       /** @var EntityRepositoryInterface $mailTemplateTypeRepository 
  122.        */
  123.       $mailTemplateTypeRepository $this->container->get('mail_template_type.repository');
  124.       /** 
  125.        * @var EntityRepositoryInterface $mailTemplateRepository */
  126.       $mailTemplateRepository $this->container->get('mail_template.repository');
  127.       $mailTemplateTypeId Uuid::randomHex();
  128.       $mailTemplateType = [[
  129.        'id' => $mailTemplateTypeId,
  130.        'name' => self::TEMPLATE_TYPE_NAME,
  131.        'technicalName' => self::TEMPLATE_TYPE_TECHNICAL_NAME,
  132.        'availableEntities' => [
  133.         'product' => 'product',
  134.         'salesChannel' => 'sales_channel']]
  135.       ];
  136.       $mailTemplate = [[
  137.        'id' => Uuid::randomHex(),
  138.        'mailTemplateTypeId' => $mailTemplateTypeId,
  139.        'sender' => '{{salesChannel.name}}',
  140.        'subject' => 'Zusatzdokument für Ihre Bestellung',
  141.        'contentPlain' => $this->plainText(),
  142.        'contentHtml' => $this->htmlText(),
  143.       ]];
  144.       try {
  145.         $mailTemplateTypeRepository->create($mailTemplateType$installContext->getContext());
  146.         $mailTemplateRepository->create($mailTemplate$installContext->getContext());
  147.       } catch (UniqueConstraintViolationException $exception) { }
  148.     } 
  149.  
  150.     
  151.     /**
  152.      * 
  153.      * @param type $installContext
  154.      */
  155.     private function addCustomFields($installContext){
  156.       $customFieldSetRepository $this->container->get('custom_field_set.repository');
  157.       for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  158.         $criteria = new Criteria();
  159.         $criteria->addFilter(new EqualsFilter('name''scha1additionalproductbasketfields' $i));
  160.         $result $customFieldSetRepository->searchIds($criteria$installContext);
  161.         if (!($result->getTotal() > 0)) {
  162.           $customFieldSetRepository->create([[
  163.             'name' => 'scha1additionalproductbasketfields' $i,
  164.             'config' => [
  165.               'label' => [
  166.                 'de-DE' => 'Zusatzfeld ' $i,
  167.                 'en-GB' => 'additional field ' $i,
  168.               ],
  169.             ],
  170.             'position' => $i,
  171.             'customFields' => [
  172.             [
  173.               'name' => 'scha1additionalproductbasketfields' $i '_active',
  174.               'type' => CustomFieldTypes::BOOL,
  175.               'config' => [
  176.               'label' => [
  177.                 'de-DE' => 'Zusatzfeld aktivieren',
  178.                 'en-GB' => 'Activate additional field',
  179.                 ],
  180.                 'componentName' => 'sw-field',
  181.                 'customFieldType' => 'checkbox',
  182.                 'customFieldPosition' => 1,
  183.                 'type' => 'checkbox',
  184.               ],
  185.             ],
  186.              [
  187.               'name' => 'scha1additionalproductbasketfields' $i '_fieldtype',
  188.               'type' => CustomFieldTypes::SELECT,
  189.               'config' => [
  190.                 'label' => [
  191.                   'de-DE' => 'Feldtyp des Zusatzfelds',
  192.                   'en-GB' => 'type of the additional field',
  193.                 ],
  194.                 'options' => [
  195.                  [
  196.                   'label' => [
  197.                     'de-DE' => 'Eingabefeld',
  198.                     'en-GB' => 'input field',
  199.                   ],
  200.                   'value' => 'input',
  201.                   ],
  202.                  [
  203.                    'label' => [
  204.                     'de-DE' => 'Textfeld',
  205.                     'en-GB' => 'textfield',
  206.                   ],
  207.                    'value' => 'textarea',
  208.                   ],
  209.                  [
  210.                    'label' => [
  211.                     'de-DE' => 'Zahlenfeld',
  212.                     'en-GB' => 'number field',
  213.                     ],
  214.                    'value' => 'number',
  215.                    ],
  216.                  [
  217.                   'label' => [
  218.                    'de-DE' => 'Checkbox',
  219.                    'en-GB' => 'check box',
  220.                   ],
  221.                   'value' => 'boolean',
  222.                 ],
  223.                  [
  224.                   'label' => [
  225.                     'de-DE' => 'Datumsfeld',
  226.                     'en-GB' => 'date field',
  227.                    ],
  228.                   'value' => 'date',
  229.                   ],
  230.                   [
  231.                   'label' => [
  232.                       'de-DE' => 'Auswahlfeld',
  233.                       'en-GB' => 'selection box',
  234.                   ],
  235.                   'value' => 'select',
  236.                   ],
  237.                 ],
  238.                 'componentName' => 'sw-single-select',
  239.                 'customFieldType' => 'select',
  240.                 'customFieldPosition' => 2,
  241.                 'type' => 'select',
  242.               ],
  243.             ],
  244.             [
  245.               'name' => 'scha1additionalproductbasketfields' $i '_title',
  246.               'type' => CustomFieldTypes::TEXT,
  247.               'config' => [
  248.                 'label' => [
  249.                   'de-DE' => 'Beschriftung oberhalb des Zusatzfelds',
  250.                   'en-GB' => 'label above the additional field',
  251.                 ],
  252.                 'placeholder' => [
  253.                     'de-DE' => 'Beschriftung oberhalb des Zusatzfelds',
  254.                     'en-GB' => 'label above the additional field',
  255.                 ],
  256.                 'componentName' => 'sw-field',
  257.                   'customFieldType' => 'text',
  258.                   'customFieldPosition' => 3,
  259.                   'type' => 'text',
  260.               ],
  261.               ],
  262.               [
  263.                 'name' => 'scha1additionalproductbasketfields' $i '_placeholder',
  264.                 'type' => CustomFieldTypes::TEXT,
  265.                 'config' => [
  266.                   'label' => [
  267.                     'de-DE' => 'Platzhalter des Zusatzfelds',
  268.                     'en-GB' => 'placeholder of the additional field',
  269.                   ],
  270.                   'placeholder' => [
  271.                     'de-DE' => 'Platzhalter des Zusatzfelds, bspw. Bitte geben Sie eine Größe ein',
  272.                     'en-GB' => 'Placeholder of the additional field, e.g. Please enter a size',
  273.                   ],
  274.                   'componentName' => 'sw-field',
  275.                   'customFieldType' => 'text',
  276.                   'customFieldPosition' => 4,
  277.                   'type' => 'text',
  278.                 ],
  279.               ],
  280.               [
  281.                 'name' => 'scha1additionalproductbasketfields' $i '_required',
  282.                 'type' => CustomFieldTypes::BOOL,
  283.                 'config' => [
  284.                   'label' => [
  285.                       'de-DE' => 'Zusatzfeld ist ein Pflichtfeld',
  286.                       'en-GB' => 'additional field is a required field',
  287.                   ],
  288.                   'componentName' => 'sw-field',
  289.                   'customFieldType' => 'checkbox',
  290.                   'customFieldPosition' => 5,
  291.                   'type' => 'checkbox',
  292.                 ],
  293.             ],
  294.             [
  295.               'name' => 'scha1additionalproductbasketfields' $i '_minvalue',
  296.               'type' => CustomFieldTypes::INT,
  297.               'config' => [
  298.                 'label' => [
  299.                   'de-DE' => 'Mindestanzahl an Zeichen',
  300.                   'en-GB' => 'Minimum number of characters',
  301.                 ],
  302.                 'placeholder' => [
  303.                   'de-DE' => '1',
  304.                   'en-GB' => '1',
  305.                 ],
  306.                 'helpText' => [
  307.                   'de-DE' => 'Geben Sie den Mindestwert für die Mindestanzahl an einzugebender Zeichen ein.',
  308.                   'en-GB' => 'Enter the minimum value for the minimum number of characters to be entered."',
  309.                 ],
  310.                 'componentName' => 'sw-field',
  311.                 'customFieldType' => 'number',
  312.                 'customFieldPosition' => 6,
  313.                 'type' => 'number',
  314.                 'numberType' => 'int',
  315.               ],
  316.             ],
  317.             [
  318.               'name' => 'scha1additionalproductbasketfields' $i '_maxvalue',
  319.               'type' => CustomFieldTypes::INT,
  320.               'config' => [
  321.                 'label' => [
  322.                   'de-DE' => 'Maximalanzahl an Zeichen',
  323.                   'en-GB' => 'Maximum number of characters',
  324.                 ],
  325.                 'placeholder' => [
  326.                   'de-DE' => '50',
  327.                   'en-GB' => '50',
  328.                 ],
  329.                 'helpText' => [
  330.                   'de-DE' => 'Geben Sie die Maximalanzahl für die Begrenzung an einzugebender Zeichen ein. Die Maximalanzahl wird für die Feldtypen Eingabefeld, Textfeld, Zahlenfeld verwendet.',
  331.                   'en-GB' => 'Enter the maximum value for the upper limit of characters to be entered. The maximum value is used for the field types input field, text field, number field.',
  332.                 ],
  333.                 'componentName' => 'sw-field',
  334.                 'customFieldType' => 'number',
  335.                 'customFieldPosition' => 7,
  336.                 'type' => 'number',
  337.                 'numberType' => 'int',
  338.               ],
  339.               ],
  340.               [
  341.                 'name' => 'scha1additionalproductbasketfields' $i '_stepsvalue',
  342.                 'type' => CustomFieldTypes::TEXT,
  343.                 'config' => [
  344.                   'label' => [
  345.                     'de-DE' => 'Zahlenfeld: Schrittweite',
  346.                     'en-GB' => 'Number field: Steps',
  347.                   ],
  348.                   'placeholder' => [
  349.                     'de-DE' => '5',
  350.                     'en-GB' => '5',
  351.                   ],
  352.                   'helpText' => [
  353.                     'de-DE' => 'Schrittweite für Zahlenfelder". Bei Gleitzahlen muss ein Punkt statt Komma verwendet werden.',
  354.                     'en-GB' => 'Increment for number fields". Floating numbers must use a point instead of a comma',
  355.                   ],
  356.                   'componentName' => 'sw-field',
  357.                   'customFieldType' => 'text',
  358.                   'customFieldPosition' => 8,
  359.                   'type' => 'text',
  360.                 ],
  361.               ],
  362.               [
  363.                 'name' => 'scha1additionalproductbasketfields' $i '_startdate',
  364.                 'type' => CustomFieldTypes::TEXT,
  365.                 'config' => [
  366.                   'label' => [
  367.                     'de-DE' => 'Datumsfeld: Startdatum',
  368.                     'en-GB' => 'Date field: Start date',
  369.                   ],
  370.                   'placeholder' => [
  371.                     'de-DE' => '+2 days',
  372.                     'en-GB' => '+2 days',
  373.                   ],
  374.                   'helpText' => [ 'de-DE' => 'Folgende Formate werden unterstützt: '
  375.                    'today = heutiges Datum, '
  376.                    '+1 days = ein Tag nach heute'
  377.                    '+1 week = 1 Woche heutigen'
  378.                    '+1 month = 1 Monat nach heutigen'
  379.                    '+1 year = 1 Jahr nach heutigen'
  380.                    '"t.m.j" = feste Tage',
  381.                     'en-GB' => 'The following formats are supported:'
  382.                    '+1 days = one day after today'
  383.                    '+1 week = one week after today'
  384.                    '+1 month = one month after today'
  385.                    '+1 year = one year after today'
  386.                    '"d.m.y" = fixed days',
  387.                   ],
  388.                   'componentName' => 'sw-field',
  389.                   'customFieldType' => 'text',
  390.                   'customFieldPosition' => 9,
  391.                   'type' => 'text',
  392.                 ],
  393.               ],
  394.               [
  395.                 'name' => 'scha1additionalproductbasketfields' $i '_enddate',
  396.                 'type' => CustomFieldTypes::TEXT,
  397.                 'config' => [
  398.                   'label' => [
  399.                     'de-DE' => 'Datumsfeld: Enddatum',
  400.                     'en-GB' => 'Date field: end date',
  401.                   ],
  402.                   'placeholder' => [
  403.                     'de-DE' => '+2 days',
  404.                     'en-GB' => '+2 days',
  405.                   ],
  406.                   'helpText' => [ 'de-DE' => 'Folgende Formate werden unterstützt: '
  407.                    'today = heutiges Datum, '
  408.                    '+1 days = ein Tag nach heute'
  409.                    '+1 week = 1 Woche heutigen'
  410.                    '+1 month = 1 Monat nach heutigen'
  411.                    '+1 year = 1 Jahr nach heutigen'
  412.                    '"t.m.j" = feste Tage',
  413.                     'en-GB' => 'The following formats are supported:'
  414.                    '+1 days = one day after today'
  415.                    '+1 week = one week after today'
  416.                    '+1 month = one month after today'
  417.                    '+1 year = one year after today'
  418.                    '"d.m.y" = fixed days',
  419.                   ],
  420.                     'componentName' => 'sw-field',
  421.                     'customFieldType' => 'text',
  422.                     'customFieldPosition' => 10,
  423.                     'type' => 'text',
  424.                 ],
  425.                 ],
  426.                 [
  427.                   'name' => 'scha1additionalproductbasketfields' $i '_disableddates',
  428.                   'type' => CustomFieldTypes::TEXT,
  429.                   'config' => [
  430.                     'label' => [
  431.                       'de-DE' => 'Datumsfeld: Ausgeschlossene Tage',
  432.                       'en-GB' => 'Date field: Excluded days',
  433.                     ],
  434.                     'placeholder' => [
  435.                       'de-DE' => '"01.04.2021","01.05.2021"',
  436.                       'en-GB' => '"01.04.2021","01.05.2021"',
  437.                     ],
  438.                     'helpText' => [
  439.                       'de-DE' => 'Folgende Formate werden unterstützt:'
  440.                      '"t.m.j" = ein ausgeschlossenes Datum'
  441.                      '"t.m.j","t.m.j" = mehrere ausgeschlossene Tage'
  442.                      '"from": "t.m.j", "to": "t.m.j","from": "t.m.j", "to": "t.m.j" = für mehrere Zeiträume oder eine Kombination daraus',
  443.                       'en-GB' => 'The following formats are supported:'
  444.                      '"d.m.y" = an excluded date'
  445.                      '"d.m.j","t.m.j" = multiple excluded days'
  446.                      '"from": ""t.m.j", "to": "t.m.j","from": "t.m.j", "to": "t.m.j" = for multiple periods or a combination thereof',
  447.                     ],
  448.                     'componentName' => 'sw-field',
  449.                     'customFieldType' => 'text',
  450.                     'customFieldPosition' => 11,
  451.                     'type' => 'text',
  452.                   ],
  453.                 ],
  454.                 [
  455.                   'name' => 'scha1additionalproductbasketfields' $i '_daterange',
  456.                   'type' => CustomFieldTypes::BOOL,
  457.                   'config' => [
  458.                     'label' => [
  459.                       'de-DE' => 'Zeitraumauswahl beim Datumsfeld möglich',
  460.                       'en-GB' => 'period selection is possible for the date field',
  461.                     ],
  462.                     'componentName' => 'sw-field',
  463.                     'customFieldType' => 'checkbox',
  464.                     'customFieldPosition' => 13,
  465.                     'type' => 'checkbox',
  466.                   ],
  467.                 ],
  468.                 [
  469.                   'name' => 'scha1additionalproductbasketfields' $i '_selectfieldvalues',
  470.                   'type' => CustomFieldTypes::TEXT,
  471.                   'config' => [
  472.                     'label' => [
  473.                       'de-DE' => 'Optionen für das Auswahlfeld',
  474.                       'en-GB' => 'Choice box options',
  475.                     ],
  476.                     'placeholder' => [
  477.                       'de-DE' => 'rot,gelb,blau',
  478.                       'en-GB' => 'red,yellow,blue',
  479.                     ],
  480.                     'helpText' => [
  481.                       'de-DE' => 'Folgende Syntax wird unterstützt: rot,gelb,blau',
  482.                       'en-GB' => 'The following syntax is supported: red,yellow,blue',
  483.                     ],
  484.                     'componentName' => 'sw-field',
  485.                     'customFieldType' => 'text',
  486.                     'customFieldPosition' => 15,
  487.                     'type' => 'text',
  488.                   ],
  489.                 ],
  490.               ],
  491.            'relations' => [['entityName' => 'product'],], ]], $installContext); 
  492.         }
  493.       }
  494.     }
  495.     
  496.     
  497.     /**
  498.      * 
  499.      * @return string
  500.      */
  501.     private function plainText() {
  502.       $plaintext '{% set currencyIsoCode = order.currency.isoCode %}
  503.         Zusatzinformationen zu Ihrer Bestellung: Bestellnummer: {{ order.orderNumber }}
  504.         Pos.   Artikel-Nr.            Produktbild(Alt-Text)             Beschreibung            Menge            Preis            Summe
  505.         {% for lineItem in order.lineItems %}
  506.         {{ loop.index }}      {% if lineItem.payload.productNumber is defined %}{{ lineItem.payload.productNumber|u.wordwrap(80) }}{% endif %}      {% if nestedItem.cover is defined and nestedItem.cover is not null %}{{ lineItem.cover.alt }}{% endif %}        {{ lineItem.label|u.wordwrap(80) }}{% if lineItem.payload.options is defined and lineItem.payload.options|length >= 1 %}, {% for option in lineItem.payload.options %}{{ option.group }}: {{ option.option }}{% if lineItem.payload.options|last != option %}{{ " | " }}{% endif %}{% endfor %}{% endif %}{% if lineItem.payload.features is defined and lineItem.payload.features|length >= 1 %}{% set referencePriceFeatures = lineItem.payload.features|filter(feature => feature.type == "referencePrice") %}{% if referencePriceFeatures|length >= 1 %}{% set referencePriceFeature = referencePriceFeatures|first %}, {{ referencePriceFeature.value.purchaseUnit }} {{ referencePriceFeature.value.unitName }}({{ referencePriceFeature.value.price|currency(currencyIsoCode) }}* / {{ referencePriceFeature.value.referenceUnit }} {{ referencePriceFeature.value.unitName }}){% endif %}{% endif %}
  507.         
  508.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields1_label}}
  509.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields1_value}}
  510.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields2_label}}
  511.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields2_value}}
  512.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields3_label}}
  513.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields3_value}}
  514.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields4_label}}
  515.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields4_value}}
  516.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields5_label}}
  517.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields5_value}}
  518.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields6_label}}
  519.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields6_value}}
  520.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields7_label}}
  521.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields7_value}}
  522.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields8_label}}
  523.           {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields8_value}}
  524.         {{ lineItem.quantity }}            {{ lineItem.unitPrice|currency(currencyIsoCode) }}            {{ lineItem.totalPrice|currency(currencyIsoCode) }}
  525.         {% endfor %}
  526.         {% set delivery = order.deliveries.first %}
  527.         {% set displayRounded = order.totalRounding.interval != 0.01 or order.totalRounding.decimals != order.itemRounding.decimals %}
  528.         {% set decimals = order.totalRounding.decimals %}
  529.         {% set total = order.price.totalPrice %}
  530.         {% if displayRounded %}
  531.         {% set total = order.price.rawTotal %}
  532.         {% set decimals = order.itemRounding.decimals %}
  533.         {% endif %}
  534.         Den aktuellen Status Ihrer Bestellung können Sie auch jederzeit auf unserer Webseite im  Bereich "Mein Konto" - "Meine Bestellungen" abrufen: {{ rawUrl("frontend.account.order.single.page", { "deepLinkCode": order.deepLinkCode }, salesChannel.domains|first.url) }}
  535.         Für Rückfragen stehen wir Ihnen jederzeit gerne zur Verfügung.';
  536.       return $plaintext;
  537.     }
  538.     
  539.     
  540.     /**
  541.      * 
  542.      * @return string
  543.      */
  544.     private function htmlText() {
  545.       $htmlText '<div style="font-family:Arial, sans-serif; font-size:12px;">
  546.         {% set currencyIsoCode = order.currency.isoCode %}
  547.         Zusatzinformationen zu Ihrer Bestellung: Bestellnummer: {{ order.orderNumber }}<br>
  548.         <br>
  549.         <table border="0" style="font-family:Arial, Helvetica, sans-serif; font-size:12px;">
  550.         <tr>
  551.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Produkt-Nr.</strong></td>
  552.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Produktbild</strong></td>
  553.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Bezeichnung</strong></td>
  554.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Menge</strong></td>
  555.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Preis</strong></td>
  556.         <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Summe</strong></td>
  557.         </tr>
  558.         {% for lineItem in order.nestedLineItems %}
  559.             {% set nestingLevel = 0 %}
  560.             {% set nestedItem = lineItem %}
  561.             {% block lineItem %}
  562.                 <tr>
  563.                     <td>{% if nestedItem.payload.productNumber is defined %}{{ nestedItem.payload.productNumber|u.wordwrap(80) }}{% endif %}</td>
  564.                     <td>{% if nestedItem.cover is defined and nestedItem.cover is not null %}<img src="{{ nestedItem.cover.url }}" width="75" height="auto"/>{% endif %}</td>
  565.                     <td>
  566.                         {% if nestingLevel > 0 %}
  567.                             {% for i in 1..nestingLevel %}
  568.                                 <span style="position: relative;">
  569.                                     <span style="display: inline-block;
  570.                                         position: absolute;
  571.                                         width: 6px;
  572.                                         height: 20px;
  573.                                         top: 0;
  574.                                         border-left:  2px solid rgba(0, 0, 0, 0.15);
  575.                                         margin-left: {{ i * 10 }}px;"></span>
  576.                                 </span>
  577.                             {% endfor %}
  578.                         {% endif %}
  579.                         <div{% if nestingLevel > 0 %} style="padding-left: {{ (nestingLevel + 1) * 10 }}px"{% endif %}>
  580.                             {{ nestedItem.label|u.wordwrap(80) }}
  581.                         </div>
  582.                         {% if nestedItem.payload.options is defined and nestedItem.payload.options|length >= 1 %}
  583.                             <div>
  584.                                 {% for option in nestedItem.payload.options %}
  585.                                     {{ option.group }}: {{ option.option }}
  586.                                     {% if nestedItem.payload.options|last != option %}
  587.                                         {{ " | " }}
  588.                                     {% endif %}
  589.                                 {% endfor %}
  590.                             </div>
  591.                         {% endif %}
  592.                         {% if nestedItem.payload.features is defined and nestedItem.payload.features|length >= 1 %}
  593.                             {% set referencePriceFeatures = nestedItem.payload.features|filter(feature => feature.type == "referencePrice") %}
  594.                             {% if referencePriceFeatures|length >= 1 %}
  595.                                 {% set referencePriceFeature = referencePriceFeatures|first %}
  596.                                 <div>
  597.                                     {{ referencePriceFeature.value.purchaseUnit }} {{ referencePriceFeature.value.unitName }}
  598.                                     ({{ referencePriceFeature.value.price|currency(currencyIsoCode) }}* / {{ referencePriceFeature.value.referenceUnit }} {{ referencePriceFeature.value.unitName }})
  599.                                 </div>
  600.                             {% endif %}
  601.                         {% endif %}
  602.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields1_label}}
  603.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields1_value}}
  604.                         <br>
  605.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields2_label}}
  606.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields2_value}}
  607.                         <br>
  608.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields3_label}}
  609.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields3_value}}
  610.                         <br>
  611.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields4_label}}
  612.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields4_value}}
  613.                         <br>
  614.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields5_label}}
  615.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields5_value}}
  616.                         <br>
  617.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields6_label}}
  618.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields6_value}}
  619.                         <br>
  620.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields7_label}}
  621.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields7_value}}
  622.                         <br>
  623.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields8_label}}
  624.                         {{order.lineItems.at(0).customFields.scha1additionalproductbasketfields8_value}}
  625.                     </td>
  626.                     <td style="text-align: center">{{ nestedItem.quantity }}</td>
  627.                     <td>{{ nestedItem.unitPrice|currency(currencyIsoCode) }}</td>
  628.                     <td>{{ nestedItem.totalPrice|currency(currencyIsoCode) }}</td>
  629.                 </tr>
  630.                 {% if nestedItem.children.count > 0 %}
  631.                     {% set nestingLevel = nestingLevel + 1 %}
  632.                     {% for lineItem in nestedItem.children %}
  633.                         {% set nestedItem = lineItem %}
  634.                         {{ block("lineItem") }}
  635.                     {% endfor %}
  636.                 {% endif %}
  637.               {% endblock %}
  638.             {% endfor %}
  639.           </table>
  640.         <br/>
  641.         Den aktuellen Status Ihrer Bestellung können Sie auch jederzeit auf unserer Webseite im  Bereich "Mein Konto" - "Meine Bestellungen" abrufen: {{ rawUrl("frontend.account.order.single.page", { "deepLinkCode": order.deepLinkCode }, salesChannel.domains|first.url) }}
  642.         </br>
  643.         Für Rückfragen stehen wir Ihnen jederzeit gerne zur Verfügung.';
  644.       return $htmlText;
  645.     }
  646.   }