diff --git a/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php index d10872c9bc..a9ee08ee87 100644 --- a/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php +++ b/src/CoreShop/Bundle/CoreBundle/Form/Type/Checkout/AddressType.php @@ -16,12 +16,16 @@ use CoreShop\Bundle\ResourceBundle\Form\Type\AbstractResourceType; use CoreShop\Component\Address\Formatter\AddressFormatterInterface; use CoreShop\Component\Address\Model\AddressInterface; +use CoreShop\Component\Core\Model\CartInterface; use CoreShop\Component\Core\Model\CustomerInterface; +use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\NotBlank; final class AddressType extends AbstractResourceType @@ -32,18 +36,26 @@ final class AddressType extends AbstractResourceType private $addressFormatHelper; /** - * @param string $dataClass FQCN + * @var TranslatorInterface + */ + private $translator; + + /** + * @param string $dataClass * @param string[] $validationGroups * @param AddressFormatterInterface $addressFormatHelper + * @param TranslatorInterface $translator */ public function __construct( $dataClass, array $validationGroups, - AddressFormatterInterface $addressFormatHelper + AddressFormatterInterface $addressFormatHelper, + TranslatorInterface $translator ) { parent::__construct($dataClass, $validationGroups); $this->addressFormatHelper = $addressFormatHelper; + $this->translator = $translator; } /** @@ -51,9 +63,26 @@ public function __construct( */ public function buildForm(FormBuilderInterface $builder, array $options) { + $defaultShippingAddress = null; + $defaultInvoiceAddress = null; + + if ($options['customer']->getDefaultAddress() instanceof AddressInterface) { + /** @var AddressInterface $address */ + $address = $options['customer']->getDefaultAddress(); + $addressIdentifier = $address->getAddressIdentifier(); + + if (null === $addressIdentifier) { + $defaultShippingAddress = $address; + $defaultInvoiceAddress = $address; + } else { + $defaultShippingAddress = $addressIdentifier->getName() === 'shipping' ? $address : null; + $defaultInvoiceAddress = $addressIdentifier->getName() === 'invoice' ? $address : null; + } + } + $builder ->add('shippingAddress', AddressChoiceType::class, [ - 'constraints' => [new NotBlank()], + 'constraints' => [new NotBlank(['groups' => $this->validationGroups])], 'customer' => $options['customer']->getId(), 'label' => 'coreshop.form.address.shipping', 'allowed_address_identifier' => [null, 'shipping'], @@ -67,10 +96,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) return []; }, - 'empty_data' => $options['customer']->getDefaultAddress(), + 'empty_data' => $defaultShippingAddress, ]) ->add('invoiceAddress', AddressChoiceType::class, [ - 'constraints' => [new NotBlank()], + 'constraints' => [new NotBlank(['groups' => $this->validationGroups])], 'customer' => $options['customer']->getId(), 'label' => 'coreshop.form.address.invoice', 'allowed_address_identifier' => [null, 'invoice'], @@ -84,28 +113,67 @@ public function buildForm(FormBuilderInterface $builder, array $options) return []; }, - 'empty_data' => $options['customer']->getDefaultAddress(), + 'empty_data' => $defaultInvoiceAddress, ]) - ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + ->addEventListener(FormEvents::PRE_SET_DATA, static function (FormEvent $event) { + /** @var CartInterface $cart */ $cart = $event->getData(); $checkboxData = true; - if ($cart->getShippingAddress() instanceof AddressInterface && $cart->getInvoiceAddress() instanceof AddressInterface) { - if ($cart->getShippingAddress()->getId() !== $cart->getInvoiceAddress()->getId()) { + $checkboxDisabled = false; + + if ($event->getForm()->has('shippingAddress') && + $event->getForm()->get('shippingAddress')->getConfig()->hasOption('choices') + ) { + $choiceList = $event->getForm()->get('shippingAddress')->getConfig()->getOption('choices'); + + if (!is_array($choiceList) || count($choiceList) === 0) { $checkboxData = null; + $checkboxDisabled = true; } } + + if ($cart->getShippingAddress() instanceof AddressInterface && + $cart->getInvoiceAddress() instanceof AddressInterface && + $cart->getShippingAddress()->getId() !== $cart->getInvoiceAddress()->getId() + ) { + $checkboxData = null; + } + $event->getForm()->add('useInvoiceAsShipping', CheckboxType::class, [ 'required' => false, 'mapped' => false, + 'disabled' => $checkboxDisabled, 'label' => 'coreshop.form.address.use_invoice_as_shipping', 'data' => $checkboxData, ]); }) ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { $formData = $event->getData(); - if (isset($formData['invoiceAddress']) && (isset($formData['useInvoiceAsShipping']) && '1' === $formData['useInvoiceAsShipping'])) { - $formData['shippingAddress'] = $formData['invoiceAddress']; - $event->setData($formData); + + if (isset($formData['invoiceAddress'], $formData['useInvoiceAsShipping']) && '1' === $formData['useInvoiceAsShipping']) { + $valid = true; + + if ($event->getForm()->has('shippingAddress') && + $event->getForm()->get('shippingAddress')->getConfig()->hasOption('choices') + ) { + $invoiceAddressId = $formData['invoiceAddress']; + $choiceList = $event->getForm()->get('shippingAddress')->getConfig()->getOption('choices'); + + if (is_array($choiceList) && count($choiceList) > 0) { + $valid = count(array_filter($choiceList, static function (AddressInterface $address) use ($invoiceAddressId) { + return $address->getId() === (int) $invoiceAddressId; + })) > 0; + } + } + + if ($valid === true) { + $formData['shippingAddress'] = $formData['invoiceAddress']; + $event->setData($formData); + } else { + $message = $this->translator->trans('coreshop.checkout.address.invoice_as_shipping_invalid'); + $event->getForm()->addError(new FormError($message)); + } + } }); } diff --git a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml index 88b792c43b..0a306b92ba 100644 --- a/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml +++ b/src/CoreShop/Bundle/CoreBundle/Resources/config/services/checkout.yml @@ -65,6 +65,7 @@ services: - '%coreshop.model.cart.class%' - '%coreshop.form.type.checkout.address.validation_groups%' - '@coreshop.address.formatter' + - '@translator' tags: - {name: form.type} diff --git a/src/CoreShop/Bundle/CoreBundle/Resources/translations/admin.en.yml b/src/CoreShop/Bundle/CoreBundle/Resources/translations/admin.en.yml index 3132955821..7dcd771579 100644 --- a/src/CoreShop/Bundle/CoreBundle/Resources/translations/admin.en.yml +++ b/src/CoreShop/Bundle/CoreBundle/Resources/translations/admin.en.yml @@ -237,4 +237,4 @@ coreshop_customer_transformer_assignment_form_success: 'Customer has been succes coreshop_customer_transformer_assignment_form_new_company_title: 'New Company Data' coreshop_customer_transformer_assignment_new_form_button: 'Create Company and assign Customer' coreshop_customer_transformer_assignment_new_form_description: 'Once this form is submitted, a new company will be created. Please check the data carefully. In addition, you must define whether the customer addresses are to be retained by the customer or transferred to the new company.' -coreshop_customer_transformer_assignment_new_form_maybe_duplicates_title: 'Similar Companies' \ No newline at end of file +coreshop_customer_transformer_assignment_new_form_maybe_duplicates_title: 'Similar Companies' diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/install/pimcore/translations.yml b/src/CoreShop/Bundle/FrontendBundle/Resources/install/pimcore/translations.yml index f3d70f0e0f..a312c9f56e 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/install/pimcore/translations.yml +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/install/pimcore/translations.yml @@ -1573,3 +1573,10 @@ translations: en: 'Total to be paid' de: 'Zu zahlender Betrag' it: 'Totale da pagare' + + coreshop.checkout.address.invoice_as_shipping_invalid: + languages: + de_CH: 'Die Verwendung der Rechnungsadresse als Versandadresse ist hier nicht möglich. Haben Sie eine Adresse gewählt die strikt als Rechnungsadresse deklariert ist?' + de: 'Die Verwendung der Rechnungsadresse als Versandadresse ist hier nicht möglich. Haben Sie eine Adresse gewählt die strikt als Rechnungsadresse deklariert ist?' + en: 'Using the invoice address as shipping address is not possible. Maybe your selected invoice address is a strict type of invoice address?' + it: '' diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/public/static/js/shop.js b/src/CoreShop/Bundle/FrontendBundle/Resources/public/static/js/shop.js index 9f5d9f47a0..6dc847d6d6 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/public/static/js/shop.js +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/public/static/js/shop.js @@ -78,22 +78,20 @@ $(document).ready(function () { $shippingAddAddressButton = $shippingPanel.parent().find('.card-footer'), $useIasS = $addressStep.find('[name="useInvoiceAsShipping"]'); - if ($invoiceAddress.find('option:selected').length) { - var address = $invoiceAddress.find('option:selected').data('address'); - if (address) { - $invoicePanel.html(address.html); - } - } - - if ($shippingAddress.find('option:selected').length) { - var address = $shippingAddress.find('option:selected').data('address'); - if (address) { - $shippingPanel.html(address.html); - } - } - $invoiceAddress.on('change', function () { - var address = $(this).find('option:selected').data('address'); + var selected = $(this).find('option:selected'); + var address = selected.data('address'); + var addressType = selected.data('address-type'); + + if ($useIasS) { + if (addressType === 'invoice') { + $useIasS.prop("disabled", true); + $useIasS.prop("checked", false); + $useIasS.change(); + } else { + $useIasS.prop("disabled", false); + } + } if (address) { address = address.html; @@ -144,6 +142,32 @@ $(document).ready(function () { } } }); + + if ($invoiceAddress.find('option:selected').length) { + var address = $invoiceAddress.find('option:selected').data('address'); + var addressType = $invoiceAddress.find('option:selected').data('address-type'); + + if ($useIasS) { + if (addressType === 'invoice') { + $useIasS.prop("disabled", true); + $useIasS.prop("checked", false); + $useIasS.change(); + } else { + $useIasS.prop("disabled", false); + } + } + + if (address) { + $invoicePanel.html(address.html); + } + } + + if ($shippingAddress.find('option:selected').length) { + var address = $shippingAddress.find('option:selected').data('address'); + if (address) { + $shippingPanel.html(address.html); + } + } }; -}(window.shop = window.shop || {}, jQuery)); \ No newline at end of file +}(window.shop = window.shop || {}, jQuery)); diff --git a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/address.html.twig b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/address.html.twig index 208d553c0d..7ceeb55e16 100644 --- a/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/address.html.twig +++ b/src/CoreShop/Bundle/FrontendBundle/Resources/views/Checkout/steps/address.html.twig @@ -23,8 +23,8 @@ {% if hasShippableItems %} -
+ {% set hideShipmentSelector = form.shippingAddress.vars.choices|length > 0 and form.useInvoiceAsShipping is defined and form.useInvoiceAsShipping.vars.data and form.shippingAddress.vars.valid != false %} +
{{ form_row(form.shippingAddress) }}
{% endif %}