* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ namespace PrestaShopBundle\Controller\Admin\Sell\Customer; use Exception; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\BulkDeleteCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\BulkDisableCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\BulkEnableCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\DeleteCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\EditCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\SetPrivateNoteAboutCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\SetRequiredFieldsForCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Command\TransformGuestToCustomerCommand; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerByEmailNotFoundException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerConstraintException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerDefaultGroupAccessException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerNotFoundException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerTransformationException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\DuplicateCustomerEmailException; use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\MissingCustomerRequiredFieldsException; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetCustomerCarts; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetCustomerForAddressCreation; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetCustomerForEditing; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetCustomerForViewing; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetCustomerOrders; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\GetRequiredFieldsForCustomer; use PrestaShop\PrestaShop\Core\Domain\Customer\Query\SearchCustomers; use PrestaShop\PrestaShop\Core\Domain\Customer\QueryResult\AddressCreationCustomerInformation; use PrestaShop\PrestaShop\Core\Domain\Customer\QueryResult\EditableCustomer; use PrestaShop\PrestaShop\Core\Domain\Customer\QueryResult\ViewableCustomer; use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\Password; use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint; use PrestaShop\PrestaShop\Core\Domain\ShowcaseCard\Query\GetShowcaseCardIsClosed; use PrestaShop\PrestaShop\Core\Domain\ShowcaseCard\ValueObject\ShowcaseCard; use PrestaShop\PrestaShop\Core\Grid\Definition\Factory\CustomerGridDefinitionFactory; use PrestaShop\PrestaShop\Core\Search\Filters\CustomerAddressFilters; use PrestaShop\PrestaShop\Core\Search\Filters\CustomerDiscountFilters; use PrestaShop\PrestaShop\Core\Search\Filters\CustomerFilters; use PrestaShopBundle\Component\CsvResponse; use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController as AbstractAdminController; use PrestaShopBundle\Form\Admin\Sell\Customer\DeleteCustomersType; use PrestaShopBundle\Form\Admin\Sell\Customer\PrivateNoteType; use PrestaShopBundle\Form\Admin\Sell\Customer\RequiredFieldsType; use PrestaShopBundle\Form\Admin\Sell\Customer\TransferGuestAccountType; use PrestaShopBundle\Security\Annotation\AdminSecurity; use PrestaShopBundle\Security\Annotation\DemoRestricted; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Class CustomerController manages "Sell > Customers" page. */ class CustomerController extends AbstractAdminController { /** * Show customers listing. * * @AdminSecurity( * "is_granted('read', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to view this." * ) * * @param Request $request * @param CustomerFilters $filters * * @return Response */ public function indexAction(Request $request, CustomerFilters $filters) { $customersKpiFactory = $this->get('prestashop.core.kpi_row.factory.customers'); $customerGridFactory = $this->get('prestashop.core.grid.factory.customer'); $customerGrid = $customerGridFactory->getGrid($filters); $deleteCustomerForm = $this->createForm(DeleteCustomersType::class); $showcaseCardIsClosed = $this->getQueryBus()->handle( new GetShowcaseCardIsClosed((int) $this->getContext()->employee->id, ShowcaseCard::CUSTOMERS_CARD) ); return $this->render('@PrestaShop/Admin/Sell/Customer/index.html.twig', [ 'help_link' => $this->generateSidebarLink($request->attributes->get('_legacy_controller')), 'customerGrid' => $this->presentGrid($customerGrid), 'customersKpi' => $customersKpiFactory->build(), 'customerRequiredFieldsForm' => $this->getRequiredFieldsForm()->createView(), 'isSingleShopContext' => $this->get('prestashop.adapter.shop.context')->isSingleShopContext(), 'deleteCustomersForm' => $deleteCustomerForm->createView(), 'showcaseCardName' => ShowcaseCard::CUSTOMERS_CARD, 'isShowcaseCardClosed' => $showcaseCardIsClosed, 'layoutHeaderToolbarBtn' => $this->getCustomerToolbarButtons(), ]); } /** * @deprecated since 1.7.8 and will be removed in next major. Use CommonController:searchGridAction instead * * Process Grid search. * * @AdminSecurity("is_granted('read', request.get('_legacy_controller'))") * * @param Request $request * * @return RedirectResponse */ public function searchGridAction(Request $request) { $responseBuilder = $this->get('prestashop.bundle.grid.response_builder'); return $responseBuilder->buildSearchResponse( $this->get('prestashop.core.grid.definition.factory.customer'), $request, CustomerGridDefinitionFactory::GRID_ID, 'admin_customers_index' ); } /** * Show customer create form & handle processing of it. * * @AdminSecurity("is_granted('create', request.get('_legacy_controller'))") * * @param Request $request * * @return Response */ public function createAction(Request $request) { if (!$this->get('prestashop.adapter.shop.context')->isSingleShopContext()) { return $this->redirectToRoute('admin_customers_index'); } $this->addGroupSelectionToRequest($request); $customerForm = $this->get('prestashop.core.form.identifiable_object.builder.customer_form_builder')->getForm(); $customerForm->handleRequest($request); $customerFormHandler = $this->get('prestashop.core.form.identifiable_object.handler.customer_form_handler'); try { $result = $customerFormHandler->handle($customerForm); if ($customerId = $result->getIdentifiableObjectId()) { $this->addFlash('success', $this->trans('Successful creation', 'Admin.Notifications.Success')); if ($request->query->has('submitFormAjax')) { /** @var ViewableCustomer $customerInformation */ $customerInformation = $this->getQueryBus()->handle(new GetCustomerForViewing((int) $customerId)); return $this->render('@PrestaShop/Admin/Sell/Customer/modal_create_success.html.twig', [ 'customerId' => $customerId, 'customerEmail' => $customerInformation->getPersonalInformation()->getEmail(), ]); } return $this->redirectToRoute('admin_customers_index'); } } catch (Exception $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } return $this->render('@PrestaShop/Admin/Sell/Customer/create.html.twig', [ 'customerForm' => $customerForm->createView(), 'isB2bFeatureActive' => $this->get('prestashop.core.b2b.b2b_feature')->isActive(), 'minPasswordLength' => Password::MIN_LENGTH, 'displayInIframe' => $request->query->has('submitFormAjax'), 'help_link' => $this->generateSidebarLink($request->attributes->get('_legacy_controller')), ]); } /** * Show customer edit form & handle processing of it. * * @AdminSecurity("is_granted('update', request.get('_legacy_controller'))") * * @param int $customerId * @param Request $request * * @return Response */ public function editAction($customerId, Request $request) { $this->addGroupSelectionToRequest($request); /** @var EditableCustomer $customerInformation */ $customerInformation = $this->getQueryBus()->handle(new GetCustomerForEditing((int) $customerId)); $customerFormOptions = [ 'is_password_required' => false, ]; try { $customerForm = $this->get('prestashop.core.form.identifiable_object.builder.customer_form_builder') ->getFormFor((int) $customerId, [], $customerFormOptions); } catch (Exception $exception) { $this->addFlash( 'error', $this->getErrorMessageForException($exception, $this->getErrorMessages($exception)) ); return $this->redirectToRoute('admin_customers_index'); } try { $customerForm->handleRequest($request); $customerFormHandler = $this->get('prestashop.core.form.identifiable_object.handler.customer_form_handler'); $result = $customerFormHandler->handleFor((int) $customerId, $customerForm); if ($result->isSubmitted() && $result->isValid()) { $this->addFlash('success', $this->trans('Successful update', 'Admin.Notifications.Success')); return $this->redirectToRoute('admin_customers_index'); } } catch (Exception $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); if ($e instanceof CustomerNotFoundException) { return $this->redirectToRoute('admin_customers_index'); } } return $this->render('@PrestaShop/Admin/Sell/Customer/edit.html.twig', [ 'customerForm' => $customerForm->createView(), 'customerInformation' => $customerInformation, 'isB2bFeatureActive' => $this->get('prestashop.core.b2b.b2b_feature')->isActive(), 'minPasswordLength' => Password::MIN_LENGTH, 'help_link' => $this->generateSidebarLink($request->attributes->get('_legacy_controller')), ]); } /** * View customer information. * * @AdminSecurity("is_granted('read', request.get('_legacy_controller'))", redirectRoute="admin_customers_index") * @DemoRestricted(redirectRoute="admin_customers_index") * * @param int $customerId * @param Request $request * @param CustomerDiscountFilters $customerDiscountFilters * @param CustomerAddressFilters $customerAddressFilters * * @return Response */ public function viewAction( $customerId, Request $request, CustomerDiscountFilters $customerDiscountFilters, CustomerAddressFilters $customerAddressFilters ) { try { /** @var ViewableCustomer $customerInformation */ $customerInformation = $this->getQueryBus()->handle(new GetCustomerForViewing((int) $customerId)); } catch (CustomerNotFoundException $e) { $this->addFlash( 'error', $this->trans('This customer does not exist.', 'Admin.Orderscustomers.Notification') ); return $this->redirectToRoute('admin_customers_index'); } $transferGuestAccountForm = null; if ($customerInformation->getPersonalInformation()->isGuest()) { $transferGuestAccountForm = $this->createForm(TransferGuestAccountType::class, [ 'id_customer' => $customerId, ])->createView(); } $privateNoteForm = $this->createForm(PrivateNoteType::class, [ 'note' => $customerInformation->getGeneralInformation()->getPrivateNote(), ]); $customerDiscountGridFactory = $this->get('prestashop.core.grid.factory.customer.discount'); $customerDiscountFilters = new CustomerDiscountFilters([ 'filters' => [ 'id_customer' => $customerId, ], ] + $customerDiscountFilters->all()); $customerDiscountGrid = $customerDiscountGridFactory->getGrid($customerDiscountFilters); $customerAddressGridFactory = $this->get('prestashop.core.grid.factory.customer.address'); $customerAddressFilters = new CustomerAddressFilters([ 'filters' => [ 'id_customer' => $customerId, ], ] + $customerAddressFilters->all()); $customerAddressGrid = $customerAddressGridFactory->getGrid($customerAddressFilters); if ($request->query->has('conf')) { $this->manageLegacyFlashes($request->query->get('conf')); } return $this->render('@PrestaShop/Admin/Sell/Customer/view.html.twig', [ 'enableSidebar' => true, 'help_link' => $this->generateSidebarLink($request->attributes->get('_legacy_controller')), 'customerInformation' => $customerInformation, 'customerDiscountGrid' => $this->presentGrid($customerDiscountGrid), 'customerAddressGrid' => $this->presentGrid($customerAddressGrid), 'isMultistoreEnabled' => $this->get('prestashop.adapter.feature.multistore')->isActive(), 'transferGuestAccountForm' => $transferGuestAccountForm, 'privateNoteForm' => $privateNoteForm->createView(), ]); } /** * Set private note about customer. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller')) && is_granted('create', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index" * ) * * @param int $customerId * @param Request $request * * @return Response */ public function setPrivateNoteAction($customerId, Request $request) { $privateNoteForm = $this->createForm(PrivateNoteType::class); $privateNoteForm->handleRequest($request); if ($privateNoteForm->isSubmitted()) { $data = $privateNoteForm->getData(); try { $this->getCommandBus()->handle(new SetPrivateNoteAboutCustomerCommand( (int) $customerId, $data['note'] )); $this->addFlash('success', $this->trans('Successful update', 'Admin.Notifications.Success')); } catch (CustomerException $e) { $this->addFlash( 'error', $this->getErrorMessageForException($e, $this->getErrorMessages($e)) ); } } return $this->redirectToRoute('admin_customers_view', [ 'customerId' => $customerId, ]); } /** * Transforms guest to customer * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller')) && is_granted('create', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index" * ) * * @param int $customerId * @param Request $request * * @return RedirectResponse */ public function transformGuestToCustomerAction($customerId, Request $request) { try { $this->getCommandBus()->handle(new TransformGuestToCustomerCommand((int) $customerId)); $this->addFlash('success', $this->trans('Successful creation', 'Admin.Notifications.Success')); } catch (CustomerException $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } if ($request->query->get('id_order')) { $legacyLink = $this->getAdminLink('AdminOrders', [ 'id_order' => $request->query->get('id_order'), 'vieworder' => true, ]); return $this->redirect($legacyLink); } return $this->redirectToRoute('admin_customers_view', [ 'customerId' => $customerId, ]); } /** * Sets required fields for customer * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller')) && is_granted('create', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index" * ) * * @param Request $request * * @return RedirectResponse */ public function setRequiredFieldsAction(Request $request) { $requiredFieldsForm = $this->getRequiredFieldsForm(); $requiredFieldsForm->handleRequest($request); if ($requiredFieldsForm->isSubmitted()) { $data = $requiredFieldsForm->getData(); $this->getCommandBus()->handle(new SetRequiredFieldsForCustomerCommand($data['required_fields'])); $this->addFlash('success', $this->trans('Successful update', 'Admin.Notifications.Success')); } return $this->redirectToRoute('admin_customers_index'); } /** * Search for customers by query. * * @AdminSecurity("is_granted('read', request.get('_legacy_controller')) || is_granted('create', 'AdminOrders')") * * @param Request $request * * @return JsonResponse */ public function searchAction(Request $request) { $query = $request->query->get('customer_search'); $phrases = explode(' OR ', $query); $isRequestFromLegacyPage = !$request->query->has('sf2'); if (!$request->query->has('shopId')) { // this is important for keeping backwards compatibility, null acts different compared to AllShops constraint. $shopConstraint = null; } else { $shopId = $request->query->getInt('shopId'); $shopConstraint = $shopId ? ShopConstraint::shop($shopId) : ShopConstraint::allShops(); } try { $customers = $this->getQueryBus()->handle(new SearchCustomers( $phrases, $shopConstraint )); } catch (Exception $e) { return $this->json( ['message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e))], Response::HTTP_INTERNAL_SERVER_ERROR ); } // if call is made from legacy page // it will return response so legacy can understand it if ($isRequestFromLegacyPage) { return $this->json([ 'found' => !empty($customers), 'customers' => $customers, ]); } return $this->json($customers); } /** * Provides customer information for address creation in json format * * @AdminSecurity("is_granted('read', request.get('_legacy_controller'))") * * @param Request $request * * @return JsonResponse */ public function getCustomerInformationAction(Request $request): Response { try { $email = $request->query->get('email'); /** @var AddressCreationCustomerInformation $customerInformation */ $customerInformation = $this->getQueryBus()->handle(new GetCustomerForAddressCreation($email)); return $this->json($customerInformation); } catch (Exception $e) { $code = Response::HTTP_INTERNAL_SERVER_ERROR; if ($e instanceof CustomerException) { $code = Response::HTTP_NOT_FOUND; } return $this->json([ 'message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e)), ], $code ); } } /** * Toggle customer status. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to edit this." * ) * * @param int $customerId * * @return JsonResponse */ public function toggleStatusAction($customerId) { try { /** @var EditableCustomer $editableCustomer */ $editableCustomer = $this->getQueryBus()->handle(new GetCustomerForEditing((int) $customerId)); $editCustomerCommand = new EditCustomerCommand((int) $customerId); $editCustomerCommand->setIsEnabled(!$editableCustomer->isEnabled()); $this->getCommandBus()->handle($editCustomerCommand); $response = [ 'status' => true, 'message' => $this->trans('The status has been successfully updated.', 'Admin.Notifications.Success'), ]; } catch (CustomerException $e) { $response = [ 'status' => false, 'message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e)), ]; } return $this->json($response); } /** * Toggle customer newsletter subscription status. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to edit this." * ) * * @param int $customerId * * @return JsonResponse */ public function toggleNewsletterSubscriptionAction($customerId) { try { /** @var EditableCustomer $editableCustomer */ $editableCustomer = $this->getQueryBus()->handle(new GetCustomerForEditing((int) $customerId)); $editCustomerCommand = new EditCustomerCommand((int) $customerId); // toggle newsletter subscription $editCustomerCommand->setNewsletterSubscribed(!$editableCustomer->isNewsletterSubscribed()); $this->getCommandBus()->handle($editCustomerCommand); $response = [ 'status' => true, 'message' => $this->trans('The status has been successfully updated.', 'Admin.Notifications.Success'), ]; } catch (CustomerException $e) { $response = [ 'status' => false, 'message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e)), ]; } return $this->json($response); } /** * Toggle customer partner offer subscription status. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to edit this." * ) * * @param int $customerId * * @return JsonResponse */ public function togglePartnerOfferSubscriptionAction($customerId) { try { /** @var EditableCustomer $editableCustomer */ $editableCustomer = $this->getQueryBus()->handle(new GetCustomerForEditing((int) $customerId)); $editCustomerCommand = new EditCustomerCommand((int) $customerId); $editCustomerCommand->setIsPartnerOffersSubscribed(!$editableCustomer->isPartnerOffersSubscribed()); $this->getCommandBus()->handle($editCustomerCommand); $response = [ 'status' => true, 'message' => $this->trans('The status has been successfully updated.', 'Admin.Notifications.Success'), ]; } catch (CustomerException $e) { $response = [ 'status' => false, 'message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e)), ]; } return $this->json($response); } /** * Delete customers in bulk action. * * @AdminSecurity( * "is_granted('delete', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to delete this." * ) * * @param Request $request * * @return RedirectResponse */ public function deleteBulkAction(Request $request) { $form = $this->createForm(DeleteCustomersType::class); $form->handleRequest($request); if ($form->isSubmitted()) { $data = $form->getData(); $customerIds = array_map(function ($customerId) { return (int) $customerId; }, $data['customers_to_delete']); try { $command = new BulkDeleteCustomerCommand( $customerIds, $data['delete_method'] ); $this->getCommandBus()->handle($command); $this->addFlash( 'success', $this->trans('The selection has been successfully deleted.', 'Admin.Notifications.Success') ); } catch (CustomerException $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } } return $this->redirectToRoute('admin_customers_index'); } /** * Delete customer. * * @AdminSecurity( * "is_granted('delete', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to delete this." * ) * * @param Request $request * * @return RedirectResponse */ public function deleteAction(Request $request) { $form = $this->createForm(DeleteCustomersType::class); $form->handleRequest($request); if ($form->isSubmitted()) { $data = $form->getData(); $customerId = (int) reset($data['customers_to_delete']); try { $command = new DeleteCustomerCommand( $customerId, $data['delete_method'] ); $this->getCommandBus()->handle($command); $this->addFlash('success', $this->trans('Successful deletion', 'Admin.Notifications.Success')); } catch (CustomerException $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } } return $this->redirectToRoute('admin_customers_index'); } /** * Enable customers in bulk action. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to edit this." * ) * * @param Request $request * * @return RedirectResponse */ public function enableBulkAction(Request $request) { $customerIds = array_map(function ($customerId) { return (int) $customerId; }, $request->request->get('customer_customers_bulk', [])); try { $command = new BulkEnableCustomerCommand($customerIds); $this->getCommandBus()->handle($command); $this->addFlash('success', $this->trans('Successful update', 'Admin.Notifications.Success')); } catch (CustomerException $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } return $this->redirectToRoute('admin_customers_index'); } /** * Disable customers in bulk action. * * @AdminSecurity( * "is_granted('update', request.get('_legacy_controller'))", * redirectRoute="admin_customers_index", * message="You do not have permission to edit this." * ) * * @param Request $request * * @return RedirectResponse */ public function disableBulkAction(Request $request) { try { $customerIds = array_map(function ($customerId) { return (int) $customerId; }, $request->request->get('customer_customers_bulk', [])); $command = new BulkDisableCustomerCommand($customerIds); $this->getCommandBus()->handle($command); $this->addFlash('success', $this->trans('Successful update', 'Admin.Notifications.Success')); } catch (CustomerException $e) { $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages($e))); } return $this->redirectToRoute('admin_customers_index'); } /** * Export filtered customers * * @AdminSecurity("is_granted('read', request.get('_legacy_controller'))") * * @param CustomerFilters $filters * * @return CsvResponse */ public function exportAction(CustomerFilters $filters) { $filters = new CustomerFilters(['limit' => null] + $filters->all()); $gridFactory = $this->get('prestashop.core.grid.factory.customer'); $grid = $gridFactory->getGrid($filters); $headers = [ 'id_customer' => $this->trans('ID', 'Admin.Global'), 'social_title' => $this->trans('Social title', 'Admin.Global'), 'firstname' => $this->trans('First name', 'Admin.Global'), 'lastname' => $this->trans('Last name', 'Admin.Global'), 'email' => $this->trans('Email address', 'Admin.Global'), 'default_group' => $this->trans('Group', 'Admin.Global'), 'company' => $this->trans('Company', 'Admin.Global'), 'total_spent' => $this->trans('Sales', 'Admin.Global'), 'enabled' => $this->trans('Enabled', 'Admin.Global'), 'newsletter' => $this->trans('Newsletter', 'Admin.Global'), 'partner_offers' => $this->trans('Partner offers', 'Admin.Orderscustomers.Feature'), 'registration' => $this->trans('Registration', 'Admin.Orderscustomers.Feature'), 'connect' => $this->trans('Last visit', 'Admin.Orderscustomers.Feature'), ]; $data = []; foreach ($grid->getData()->getRecords()->all() as $record) { $data[] = [ 'id_customer' => $record['id_customer'], 'social_title' => '--' === $record['social_title'] ? '' : $record['social_title'], 'firstname' => $record['firstname'], 'lastname' => $record['lastname'], 'email' => $record['email'], 'default_group' => $record['default_group'], 'company' => '--' === $record['company'] ? '' : $record['company'], 'total_spent' => '--' === $record['total_spent'] ? '' : $record['total_spent'], 'enabled' => $record['active'], 'newsletter' => $record['newsletter'], 'partner_offers' => $record['optin'], 'registration' => $record['date_add'], 'connect' => '--' === $record['connect'] ? '' : $record['connect'], ]; } return (new CsvResponse()) ->setData($data) ->setHeadersData($headers) ->setFileName('customer_' . date('Y-m-d_His') . '.csv'); } /** * @AdminSecurity("is_granted('read', request.get('_legacy_controller')) || is_granted('create', 'AdminOrders')") * * @param int $customerId * * @return JsonResponse */ public function getCartsAction(int $customerId) { try { $carts = $this->getQueryBus()->handle(new GetCustomerCarts($customerId)); } catch (Exception $e) { return $this->json( ['message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e))], Response::HTTP_INTERNAL_SERVER_ERROR ); } return $this->json([ 'carts' => $carts, ]); } /** * @AdminSecurity("is_granted('read', request.get('_legacy_controller')) || is_granted('create', 'AdminOrders')") * * @param int $customerId * * @return JsonResponse */ public function getOrdersAction(int $customerId) { try { $orders = $this->getQueryBus()->handle(new GetCustomerOrders($customerId)); } catch (Exception $e) { return $this->json( ['message' => $this->getErrorMessageForException($e, $this->getErrorMessages($e))], Response::HTTP_INTERNAL_SERVER_ERROR ); } return $this->json([ 'orders' => $orders, ]); } /** * @return FormInterface */ private function getRequiredFieldsForm() { $requiredFields = $this->getQueryBus()->handle(new GetRequiredFieldsForCustomer()); return $this->createForm(RequiredFieldsType::class, ['required_fields' => $requiredFields]); } /** * If customer form is submitted and groups are not selected * we add empty groups to request * * @param Request $request */ private function addGroupSelectionToRequest(Request $request) { if (!$request->isMethod(Request::METHOD_POST)) { return; } if (!$request->request->has('customer') || isset($request->request->get('customer')['group_ids']) ) { return; } $customerData = $request->request->get('customer'); $customerData['group_ids'] = []; $request->request->set('customer', $customerData); } /** * Get errors that can be used to translate exceptions into user friendly messages * * @param Exception $e * * @return array */ private function getErrorMessages(Exception $e) { return [ CustomerNotFoundException::class => $this->trans( 'This customer does not exist.', 'Admin.Orderscustomers.Notification' ), DuplicateCustomerEmailException::class => sprintf( '%s %s', $this->trans('An account already exists for this email address:', 'Admin.Orderscustomers.Notification'), $e instanceof DuplicateCustomerEmailException ? $e->getEmail()->getValue() : '' ), CustomerDefaultGroupAccessException::class => $this->trans( 'A default customer group must be selected in group box.', 'Admin.Orderscustomers.Notification' ), CustomerByEmailNotFoundException::class => $this->trans( 'This email address is not registered.', 'Admin.Orderscustomers.Notification' ), CustomerConstraintException::class => [ CustomerConstraintException::INVALID_PASSWORD => $this->trans( 'Password should be at least %length% characters long.', 'Admin.Orderscustomers.Help', ['%length%' => Password::MIN_LENGTH] ), CustomerConstraintException::INVALID_FIRST_NAME => $this->trans( 'The %s field is invalid.', 'Admin.Notifications.Error', [sprintf('"%s"', $this->trans('First name', 'Admin.Global'))] ), CustomerConstraintException::INVALID_LAST_NAME => $this->trans( 'The %s field is invalid.', 'Admin.Notifications.Error', [sprintf('"%s"', $this->trans('Last name', 'Admin.Global'))] ), CustomerConstraintException::INVALID_EMAIL => $this->trans( 'The %s field is invalid.', 'Admin.Notifications.Error', [sprintf('"%s"', $this->trans('Email', 'Admin.Global'))] ), CustomerConstraintException::INVALID_BIRTHDAY => $this->trans( 'The %s field is invalid.', 'Admin.Notifications.Error', [sprintf('"%s"', $this->trans('Birthday', 'Admin.Orderscustomers.Feature'))] ), CustomerConstraintException::INVALID_APE_CODE => $this->trans( 'The %s field is invalid.', 'Admin.Notifications.Error', [sprintf('"%s"', $this->trans('APE', 'Admin.Orderscustomers.Feature'))] ), ], CustomerTransformationException::class => [ CustomerTransformationException::CUSTOMER_IS_NOT_GUEST => $this->trans( 'This customer already exists as a non-guest.', 'Admin.Orderscustomers.Notification' ), CustomerTransformationException::TRANSFORMATION_FAILED => $this->trans( 'An error occurred while updating customer information.', 'Admin.Orderscustomers.Notification' ), ], MissingCustomerRequiredFieldsException::class => $this->trans( 'The %s field is required.', 'Admin.Notifications.Error', [ implode( ',', $e instanceof MissingCustomerRequiredFieldsException ? $e->getMissingRequiredFields() : [] ), ] ), ]; } /** * Manage legacy flashes * * @todo Remove this code when legacy edit will be migrated. * * @param int $messageId The message id from legacy context */ private function manageLegacyFlashes($messageId) { $messages = [ 1 => $this->trans('Successful deletion', 'Admin.Notifications.Success'), 4 => $this->trans('Update successful.', 'Admin.Notifications.Success'), ]; if (isset($messages[$messageId])) { $this->addFlash( 'success', $messages[$messageId] ); } } /** * @return array */ private function getCustomerToolbarButtons(): array { $toolbarButtons = []; $isSingleShopContext = $this->get('prestashop.adapter.shop.context')->isSingleShopContext(); $toolbarButtons['add'] = [ 'href' => $this->generateUrl('admin_customers_create'), 'desc' => $this->trans('Add new customer', 'Admin.Orderscustomers.Feature'), 'icon' => 'add_circle_outline', 'disabled' => !$isSingleShopContext, ]; if (!$isSingleShopContext) { $toolbarButtons['add']['help'] = $this->trans( 'You can use this feature in a single-store context only. Switch contexts to enable it.', 'Admin.Orderscustomers.Feature' ); $toolbarButtons['add']['href'] = '#'; } return $toolbarButtons; } }