@RequestMapping(value = "/change", method = RequestMethod.POST)
 public String changePassword(
     @Valid final UpdatePwdForm form,
     final BindingResult bindingResult,
     final Model model,
     final RedirectAttributes redirectModel)
     throws CMSItemNotFoundException {
   if (bindingResult.hasErrors()) {
     prepareErrorMessage(model, UPDATE_PWD_CMS_PAGE);
     return ControllerConstants.Views.Pages.Password.PasswordResetChangePage;
   }
   if (!StringUtils.isBlank(form.getToken())) {
     try {
       customerFacade.updatePassword(form.getToken(), form.getPwd());
       GlobalMessages.addFlashMessage(
           redirectModel,
           GlobalMessages.CONF_MESSAGES_HOLDER,
           "account.confirmation.password.updated");
     } catch (final TokenInvalidatedException e) {
       GlobalMessages.addFlashMessage(
           redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER, "updatePwd.token.invalidated");
     } catch (final RuntimeException e) {
       GlobalMessages.addFlashMessage(
           redirectModel, GlobalMessages.ERROR_MESSAGES_HOLDER, "updatePwd.token.invalid");
     }
   }
   return REDIRECT_LOGIN;
 }
  @RequestMapping(
      value = "/cart/update",
      method = RequestMethod.POST,
      produces = "application/json")
  public String updateCartQuantities(
      @RequestParam("storeNamePost") final String storeId,
      @RequestParam("entryNumber") final long entryNumber,
      @RequestParam("hiddenPickupQty") final long quantity,
      final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData =
        cartFacade.updateCartEntry(entryNumber, storeId);

    if (entryNumber == cartModificationData.getEntry().getEntryNumber().intValue()) {
      final CartModificationData cartModification =
          cartFacade.updateCartEntry(entryNumber, quantity);
      if (cartModification.getQuantity() == quantity) {
        // Success
        if (cartModification.getQuantity() == 0) {
          // Success in removing entry
          GlobalMessages.addFlashMessage(
              redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "basket.page.message.remove");
        } else {
          // Success in update quantity
          GlobalMessages.addFlashMessage(
              redirectModel,
              GlobalMessages.CONF_MESSAGES_HOLDER,
              "basket.page.message.update.pickupinstoreitem");
        }
      } else {
        // Less than successful
        GlobalMessages.addFlashMessage(
            redirectModel,
            GlobalMessages.ERROR_MESSAGES_HOLDER,
            "basket.information.quantity.reducedNumberOfItemsAdded."
                + cartModification.getStatusCode());
      }
    } else if (!CommerceCartModificationStatus.SUCCESS.equals(
        cartModificationData.getStatusCode())) {
      // When update pickupInStore happens to be same as existing entry with POS and SKU and that
      // merged POS has lower stock
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @RequestMapping(value = "/request/external", method = RequestMethod.POST)
  public String externalPasswordRequest(
      @Valid final ForgottenPwdForm form,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectModel)
      throws CMSItemNotFoundException {
    storeCmsPageInModel(model, getContentPageForLabelOrId(null));
    setUpMetaDataForContentPage(model, getContentPageForLabelOrId(null));
    model.addAttribute(
        WebConstants.BREADCRUMBS_KEY,
        resourceBreadcrumbBuilder.getBreadcrumbs("forgottenPwd.title"));

    if (bindingResult.hasErrors()) {
      return ControllerConstants.Views.Pages.Password.PasswordResetRequest;
    } else {
      try {
        customerFacade.forgottenPassword(form.getEmail());
        GlobalMessages.addFlashMessage(
            redirectModel,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "account.confirmation.forgotten.password.link.sent");
      } catch (final UnknownIdentifierException unknownIdentifierException) {
        LOG.warn("Email: " + form.getEmail() + " does not exist in the database.");
      }
      return REDIRECT_PWD_REQ_CONF;
    }
  }
  @RequestMapping(value = "/select-suggested-address", method = RequestMethod.POST)
  public String doSelectSuggestedAddress(
      final AddressForm addressForm, final RedirectAttributes redirectModel) {
    final Set<String> resolveCountryRegions =
        org.springframework.util.StringUtils.commaDelimitedListToSet(
            Config.getParameter("resolve.country.regions"));

    final AddressData selectedAddress = new AddressData();
    selectedAddress.setId(addressForm.getAddressId());
    selectedAddress.setTitleCode(addressForm.getTitleCode());
    selectedAddress.setFirstName(addressForm.getFirstName());
    selectedAddress.setLastName(addressForm.getLastName());
    selectedAddress.setLine1(addressForm.getLine1());
    selectedAddress.setLine2(addressForm.getLine2());
    selectedAddress.setTown(addressForm.getTownCity());
    selectedAddress.setPostalCode(addressForm.getPostcode());
    selectedAddress.setBillingAddress(false);
    selectedAddress.setShippingAddress(true);
    selectedAddress.setVisibleInAddressBook(true);

    final CountryData countryData = i18NFacade.getCountryForIsocode(addressForm.getCountryIso());
    selectedAddress.setCountry(countryData);

    if (resolveCountryRegions.contains(countryData.getIsocode())) {
      if (addressForm.getRegionIso() != null && !StringUtils.isEmpty(addressForm.getRegionIso())) {
        final RegionData regionData =
            getI18NFacade().getRegion(addressForm.getCountryIso(), addressForm.getRegionIso());
        selectedAddress.setRegion(regionData);
      }
    }

    if (resolveCountryRegions.contains(countryData.getIsocode())) {
      if (addressForm.getRegionIso() != null && !StringUtils.isEmpty(addressForm.getRegionIso())) {
        final RegionData regionData =
            getI18NFacade().getRegion(addressForm.getCountryIso(), addressForm.getRegionIso());
        selectedAddress.setRegion(regionData);
      }
    }

    if (Boolean.TRUE.equals(addressForm.getEditAddress())) {
      selectedAddress.setDefaultAddress(
          Boolean.TRUE.equals(addressForm.getDefaultAddress())
              || userFacade.getAddressBook().size() <= 1);
      userFacade.editAddress(selectedAddress);
    } else {
      selectedAddress.setDefaultAddress(
          Boolean.TRUE.equals(addressForm.getDefaultAddress()) || userFacade.isAddressBookEmpty());
      userFacade.addAddress(selectedAddress);
    }

    GlobalMessages.addFlashMessage(
        redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "account.confirmation.address.added");

    return REDIRECT_TO_ADDRESS_BOOK_PAGE;
  }
  @Override
  protected String processRegisterUserRequest(
      final String referer,
      final RegisterForm form,
      final BindingResult bindingResult,
      final Model model,
      final HttpServletRequest request,
      final HttpServletResponse response,
      final RedirectAttributes redirectModel)
      throws CMSItemNotFoundException {
    if (bindingResult.hasErrors()) {
      model.addAttribute(form);
      model.addAttribute(new LoginForm());
      model.addAttribute(new GuestForm());
      GlobalMessages.addErrorMessage(model, "form.global.error");
      final Breadcrumb loginBreadcrumbEntry =
          new Breadcrumb(
              "#",
              getMessageSource()
                  .getMessage("header.link.login", null, getI18nService().getCurrentLocale()),
              null);
      model.addAttribute("breadcrumbs", Collections.singletonList(loginBreadcrumbEntry));

      return handleRegistrationError(model);
    }

    final RegisterData data = new RegisterData();
    data.setFirstName(form.getFirstName());
    data.setLastName(form.getLastName());
    data.setLogin(form.getEmail());
    data.setPassword(form.getPwd());
    data.setTitleCode(form.getTitleCode());
    data.setMobileNumber(form.getMobileNumber());
    try {
      getCustomerFacade().register(data);
      getAutoLoginStrategy().login(form.getEmail().toLowerCase(), form.getPwd(), request, response);

      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "registration.confirmation.message.title");
    } catch (final DuplicateUidException e) {
      LOG.warn("registration failed: " + e);
      model.addAttribute(form);
      model.addAttribute(new LoginForm());
      model.addAttribute(new GuestForm());
      GlobalMessages.addErrorMessage(model, "form.global.error");
      bindingResult.rejectValue("email", "registration.error.account.exists.title");

      return handleRegistrationError(model);
    }

    return REDIRECT_PREFIX + getSuccessRedirect(request, response);
  }
  @RequestMapping(value = "/update-email", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updateEmail(
      final UpdateEmailForm updateEmailForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes,
      final HttpServletRequest request)
      throws CMSItemNotFoundException {
    getEmailValidator().validate(updateEmailForm, bindingResult);

    String returnAction = REDIRECT_TO_PROFILE_PAGE;

    if (!bindingResult.hasErrors()
        && !updateEmailForm.getEmail().equals(updateEmailForm.getChkEmail())) {
      bindingResult.rejectValue(
          "chkEmail",
          "validation.checkEmail.equals",
          new Object[] {},
          "validation.checkEmail.equals");
    }

    if (bindingResult.hasErrors()) {
      returnAction = errorUpdatingEmail(model);
    } else {
      try {
        customerFacade.changeUid(updateEmailForm.getEmail(), updateEmailForm.getPassword());
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "text.account.profile.confirmationUpdated",
            null);

        // Replace the spring security authentication with the new UID
        final String newUid = customerFacade.getCurrentCustomer().getUid().toLowerCase();
        final Authentication oldAuthentication =
            SecurityContextHolder.getContext().getAuthentication();
        final UsernamePasswordAuthenticationToken newAuthentication =
            new UsernamePasswordAuthenticationToken(
                newUid, null, oldAuthentication.getAuthorities());
        newAuthentication.setDetails(oldAuthentication.getDetails());
        SecurityContextHolder.getContext().setAuthentication(newAuthentication);
      } catch (final DuplicateUidException e) {
        bindingResult.rejectValue("email", "profile.email.unique");
        returnAction = errorUpdatingEmail(model);
      } catch (final PasswordMismatchException passwordMismatchException) {
        bindingResult.rejectValue("password", "profile.currentPassword.invalid");
        returnAction = errorUpdatingEmail(model);
      }
    }

    return returnAction;
  }
 @RequestMapping(value = "/remove-payment-method", method = RequestMethod.POST)
 @RequireHardLogIn
 public String removePaymentMethod(
     final Model model,
     @RequestParam(value = "paymentInfoId") final String paymentMethodId,
     final RedirectAttributes redirectAttributes)
     throws CMSItemNotFoundException {
   userFacade.unlinkCCPaymentInfo(paymentMethodId);
   GlobalMessages.addFlashMessage(
       redirectAttributes,
       GlobalMessages.CONF_MESSAGES_HOLDER,
       "text.account.profile.paymentCart.removed");
   return REDIRECT_TO_PAYMENT_INFO_PAGE;
 }
  @RequestMapping(
      value = "/cart/update/delivery",
      method = {RequestMethod.GET, RequestMethod.POST})
  public String updateToDelivery(
      @RequestParam("entryNumber") final long entryNumber, final RedirectAttributes redirectModel)
      throws CommerceCartModificationException {
    final CartModificationData cartModificationData = cartFacade.updateCartEntry(entryNumber, null);
    if (CommerceCartModificationStatus.SUCCESS.equals(cartModificationData.getStatusCode())) {
      // Success in update quantity
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "basket.page.message.update.pickupinstoreitem.toship");
    } else {
      // Less than successful
      GlobalMessages.addFlashMessage(
          redirectModel,
          GlobalMessages.ERROR_MESSAGES_HOLDER,
          "basket.information.quantity.reducedNumberOfItemsAdded."
              + cartModificationData.getStatusCode());
    }

    return REDIRECT_PREFIX + "/cart";
  }
  @Override
  public ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes) {
    if (!getCheckoutFlowFacade().hasValidCart()) {
      LOG.info("Missing, empty or unsupported cart");
      return ValidationResults.REDIRECT_TO_CART;
    }

    if (getCheckoutFlowFacade().hasNoDeliveryAddress()) {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.INFO_MESSAGES_HOLDER,
          "checkout.multi.deliveryAddress.notprovided");
      return ValidationResults.REDIRECT_TO_DELIVERY_ADDRESS;
    }

    if (getCheckoutFlowFacade().hasNoDeliveryMode()) {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.INFO_MESSAGES_HOLDER,
          "checkout.multi.deliveryMethod.notprovided");
      return ValidationResults.REDIRECT_TO_DELIVERY_METHOD;
    }
    return ValidationResults.SUCCESS;
  }
  @RequestMapping(
      value = "/remove-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN,
      method = {RequestMethod.GET, RequestMethod.POST})
  @RequireHardLogIn
  public String removeAddress(
      @PathVariable("addressCode") final String addressCode,
      final RedirectAttributes redirectModel) {
    final AddressData addressData = new AddressData();
    addressData.setId(addressCode);
    userFacade.removeAddress(addressData);

    GlobalMessages.addFlashMessage(
        redirectModel, GlobalMessages.CONF_MESSAGES_HOLDER, "account.confirmation.address.removed");
    return REDIRECT_TO_ADDRESS_BOOK_PAGE;
  }
  @RequestMapping(value = "/update-password", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updatePassword(
      final UpdatePasswordForm updatePasswordForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes)
      throws CMSItemNotFoundException {
    getPasswordValidator().validate(updatePasswordForm, bindingResult);
    if (!bindingResult.hasErrors()) {
      if (updatePasswordForm.getNewPassword().equals(updatePasswordForm.getCheckNewPassword())) {
        try {
          customerFacade.changePassword(
              updatePasswordForm.getCurrentPassword(), updatePasswordForm.getNewPassword());
        } catch (final PasswordMismatchException localException) {
          bindingResult.rejectValue(
              "currentPassword",
              "profile.currentPassword.invalid",
              new Object[] {},
              "profile.currentPassword.invalid");
        }
      } else {
        bindingResult.rejectValue(
            "checkNewPassword",
            "validation.checkPwd.equals",
            new Object[] {},
            "validation.checkPwd.equals");
      }
    }

    if (bindingResult.hasErrors()) {
      GlobalMessages.addErrorMessage(model, "form.global.error");
      storeCmsPageInModel(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));
      setUpMetaDataForContentPage(model, getContentPageForLabelOrId(UPDATE_PASSWORD_CMS_PAGE));

      model.addAttribute(
          "breadcrumbs",
          accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile.updatePasswordForm"));
      return getViewForPage(model);
    } else {
      GlobalMessages.addFlashMessage(
          redirectAttributes,
          GlobalMessages.CONF_MESSAGES_HOLDER,
          "text.account.confirmation.password.updated",
          null);
      return REDIRECT_TO_PROFILE_PAGE;
    }
  }
  @Override
  public ValidationResults validateOnEnter(final RedirectAttributes redirectAttributes) {

    final ValidationResults result = super.validateOnEnter(redirectAttributes);
    if (ValidationResults.SUCCESS.equals(result)) {
      if (getV2CheckoutFacade().hasNoServiceableMode()) {
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.ERROR_MESSAGES_HOLDER,
            "checkout.multi.serviceablemode.notprovided");
        return ValidationResults.REDIRECT_TO_DELIVERY_ADDRESS;
      }
    }

    return result;
  }
 @RequestMapping(
     value = "/set-default-address/" + ADDRESS_CODE_PATH_VARIABLE_PATTERN,
     method = RequestMethod.GET)
 @RequireHardLogIn
 public String setDefaultAddress(
     @PathVariable("addressCode") final String addressCode,
     final RedirectAttributes redirectModel) {
   final AddressData addressData = new AddressData();
   addressData.setDefaultAddress(true);
   addressData.setVisibleInAddressBook(true);
   addressData.setId(addressCode);
   userFacade.setDefaultAddress(addressData);
   GlobalMessages.addFlashMessage(
       redirectModel,
       GlobalMessages.CONF_MESSAGES_HOLDER,
       "account.confirmation.default.address.changed");
   return REDIRECT_TO_ADDRESS_BOOK_PAGE;
 }
  @RequestMapping(value = "/update-profile", method = RequestMethod.POST)
  @RequireHardLogIn
  public String updateProfile(
      final UpdateProfileForm updateProfileForm,
      final BindingResult bindingResult,
      final Model model,
      final RedirectAttributes redirectAttributes)
      throws CMSItemNotFoundException {
    getProfileValidator().validate(updateProfileForm, bindingResult);

    String returnAction = ControllerConstants.Views.Pages.Account.AccountProfileEditPage;
    final CustomerData currentCustomerData = customerFacade.getCurrentCustomer();
    final CustomerData customerData = new CustomerData();
    customerData.setTitleCode(updateProfileForm.getTitleCode());
    customerData.setFirstName(updateProfileForm.getFirstName());
    customerData.setLastName(updateProfileForm.getLastName());
    customerData.setUid(currentCustomerData.getUid());
    customerData.setDisplayUid(currentCustomerData.getDisplayUid());

    model.addAttribute("titleData", userFacade.getTitles());

    if (bindingResult.hasErrors()) {
      GlobalMessages.addErrorMessage(model, "form.global.error");
    } else {
      try {
        customerFacade.updateProfile(customerData);
        GlobalMessages.addFlashMessage(
            redirectAttributes,
            GlobalMessages.CONF_MESSAGES_HOLDER,
            "text.account.profile.confirmationUpdated",
            null);
        returnAction = REDIRECT_TO_PROFILE_PAGE;
      } catch (final DuplicateUidException e) {
        bindingResult.rejectValue("email", "registration.error.account.exists.title");
        GlobalMessages.addErrorMessage(model, "form.global.error");
      }
    }

    storeCmsPageInModel(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
    setUpMetaDataForContentPage(model, getContentPageForLabelOrId(PROFILE_CMS_PAGE));
    model.addAttribute(
        "breadcrumbs", accountBreadcrumbBuilder.getBreadcrumbs("text.account.profile"));
    return returnAction;
  }