com.devnexus.ting.web.controller.RegisterController.java Source code

Java tutorial

Introduction

Here is the source code for com.devnexus.ting.web.controller.RegisterController.java

Source

/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.devnexus.ting.web.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.devnexus.ting.common.SpringProfile;
import com.devnexus.ting.core.service.BusinessService;
import com.devnexus.ting.model.CouponCode;
import com.devnexus.ting.model.Event;
import com.devnexus.ting.model.EventSignup;
import com.devnexus.ting.model.PayPalPayment;
import com.devnexus.ting.model.PaypalLink;
import com.devnexus.ting.model.RegistrationDetails;
import com.devnexus.ting.model.ScheduleItemList;
import com.devnexus.ting.model.SpeakerList;
import com.devnexus.ting.model.TicketGroup;
import com.devnexus.ting.model.TicketOrderDetail;
import com.devnexus.ting.web.form.RegisterForm;
import com.devnexus.ting.web.form.SignupRegisterView;
import com.devnexus.ting.web.payment.PayPalSession;
import com.google.common.base.Strings;
import com.paypal.api.payments.Amount;
import com.paypal.api.payments.Item;
import com.paypal.api.payments.ItemList;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payer;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.RedirectUrls;
import com.paypal.api.payments.Transaction;
import com.paypal.base.rest.PayPalRESTException;

/**
 *
 * Display Register Form
 *
 * @author Summers Pittman
 */
@Controller
public class RegisterController {

    @Autowired
    private Environment environment;

    private enum PaymentMethod {

        PAYPAL, INVOICE
    };

    @Autowired
    private BusinessService businessService;

    @RequestMapping(value = "/s/register-overview", method = RequestMethod.GET)
    public String getRegistrationOverview(Model model) {

        EventSignup signUp = businessService.getEventSignup();

        prepareHeader(signUp.getEvent(), model);

        List<TicketGroup> currentTickets = signUp.getGroups().stream().filter((TicketGroup group) -> {
            Date now = new Date();
            return (now.after(group.getOpenDate()) && now.before(group.getCloseDate()));
        }).collect(Collectors.toList());

        List<TicketGroup> invididualTicketGroups = currentTickets.stream().filter((TicketGroup group) -> {
            return group.getMinPurchase() == 1;
        }).collect(Collectors.toList());
        List<TicketGroup> groupTicketGroups = currentTickets.stream().filter((TicketGroup group) -> {
            return group.getMinPurchase() > 1;
        }).collect(Collectors.toList());

        model.addAttribute("invididualTicketGroups", invididualTicketGroups);
        model.addAttribute("groupTicketGroups", groupTicketGroups);

        return "register-overview";
    }

    @RequestMapping(value = "/s/register", method = RequestMethod.GET)
    public String getRegistrationFormForCurrentEvent(Model model) {
        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);

        SignupRegisterView signupView = new SignupRegisterView(eventSignup);

        model.addAttribute("signupRegisterView", signupView);

        model.addAttribute("registerForm", new RegisterForm(signupView.getGroups()));

        return "register";
    }

    @RequestMapping(value = "/s/register/{registrationKey}", method = RequestMethod.GET)
    public String viewRegistrationFormForCurrentEvent(@PathVariable("registrationKey") String registrationKey,
            Model model) {

        RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
        model.addAttribute("registrationDetails", registerForm);

        return "view-registration";
    }

    @RequestMapping(value = "/s/register", method = RequestMethod.POST)
    public String validateInitialFormAndPrepareDetailsForm(Model model, @Valid RegisterForm registerForm,
            BindingResult result) {

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));

        int totalTickets = 0;

        for (int i = 0; i < registerForm.getTicketGroupRegistrations().size(); i++) {
            RegisterForm.TicketGroupRegistration ticketReg = registerForm.getTicketGroupRegistrations().get(i);
            TicketGroup ticketGroup = businessService.getTicketGroup(ticketReg.getTicketGroupId());
            ticketReg.setGroup(ticketGroup);
            if (ticketReg.getTicketCount() > 0 && ticketReg.getTicketCount() < ticketGroup.getMinPurchase()) {
                result.addError(new FieldError("registerForm", "ticketGroupRegistrations[" + i + "].ticketCount",
                        "You need to buy more tickets."));
            }

            totalTickets += ticketReg.getTicketCount();

            if (ticketGroup.getCouponCodes() != null && ticketGroup.getCouponCodes().size() > 0
                    && !Strings.isNullOrEmpty(ticketReg.getCouponCode())) {
                if (!hasCode(ticketGroup.getCouponCodes(), ticketReg.getCouponCode())) {
                    result.addError(new FieldError("registerForm", "ticketGroupRegistrations[" + i + "].couponCode",
                            "Invalid Coupon Code."));
                }
            }
        }

        if (totalTickets == 0) {
            for (int i = 0; i < registerForm.getTicketGroupRegistrations().size(); i++) {
                result.addError(new FieldError("registerForm", "ticketGroupRegistrations[" + i + "].ticketCount",
                        "You must purchase a ticket to continue."));
            }
        }

        if (result.hasErrors()) {
            model.addAttribute("registerForm", registerForm);
            return "register";
        }

        RegistrationDetails registerFormPageTwo = new RegistrationDetails();
        registerFormPageTwo.copyPageOne(registerForm);

        registerFormPageTwo.setFinalCost(getTotal(registerFormPageTwo));

        model.addAttribute("registrationDetails", registerFormPageTwo);

        return "register2";

    }

    @RequestMapping(value = "/s/lookupCouponCode/{ticketGroupId}/{couponCode}", method = RequestMethod.GET)
    @ResponseBody
    public String getCodedPrice(Model model, @PathVariable("ticketGroupId") final Long ticketGroupId,
            @PathVariable("couponCode") final String couponCode) {
        TicketGroup group = businessService.getTicketGroup(ticketGroupId);
        if (hasCode(group.getCouponCodes(), couponCode)) {
            CouponCode code = findCode(group.getCouponCodes(), couponCode);
            return code.getPrice().setScale(2).toPlainString();
        } else {
            return group.getPrice().setScale(2).toPlainString();
        }

    }

    @RequestMapping(value = "/s/registerPageTwo/{registrationKey}", method = RequestMethod.GET)
    public String loadPageTwo(@PathVariable("registrationKey") final String registrationKey, Model model) {

        RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
        model.addAttribute("registrationDetails", registerForm);

        return "register2";

    }

    @RequestMapping(value = "/s/executeRegistration/{registrationKey}", method = RequestMethod.GET)
    public String confirmPayment(@PathVariable("registrationKey") final String registrationKey,
            @RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId, Model model) {

        RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
        model.addAttribute("registrationDetails", registerForm);
        model.addAttribute("registrationKey", registrationKey);
        model.addAttribute("paymentId", paymentId);
        model.addAttribute("payerId", payerId);
        return "confirmRegistration";

    }

    @RequestMapping(value = "/s/viewRegistration/{registrationKey}", method = RequestMethod.GET)
    public String viewRegistration(@PathVariable("registrationKey") final String registrationKey,
            @RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId, Model model) {

        RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
        model.addAttribute("registrationDetails", registerForm);
        model.addAttribute("registrationKey", registrationKey);
        model.addAttribute("paymentId", paymentId);
        model.addAttribute("payerId", payerId);
        return "viewRegistration";

    }

    @RequestMapping(value = "/s/payment-successful", method = RequestMethod.GET)
    public String paymentSuccessFul() {
        return "payment-successful";
    }

    @RequestMapping(value = "/s/executeRegistration/{registrationKey}", method = RequestMethod.POST)
    public String executePayment(@PathVariable("registrationKey") final String registrationKey,
            @RequestParam("paymentId") String paymentId, @RequestParam("payerId") String payerId, Model model) {

        try {

            PayPalSession payPalSession = payPalSession();

            Payment payment = payPalSession.execute(paymentId, payerId);
            RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);

            registerForm.setPaymentState(RegistrationDetails.PaymentState.PAID);

            PayPalPayment payPalPayment = new PayPalPayment();
            payPalPayment.setPayerId(payerId);
            payPalPayment.setPaymentId(paymentId);
            payPalPayment.setRegistrationKey(registrationKey);
            for (Links link : payment.getLinks()) {
                PaypalLink paypalLink = new PaypalLink();
                paypalLink.setHref(link.getHref());
                paypalLink.setHttpMethod(link.getMethod());
                paypalLink.setRel(link.getRel());
                payPalPayment.addLink(paypalLink);
            }
            businessService.saveAndEmailPaidRegistration(registerForm, payPalPayment);

            return "redirect:/s/payment-successful";

        } catch (PayPalRESTException payPalRESTException) {
            Event currentEvent = businessService.getCurrentEvent();
            RegistrationDetails registerForm = businessService.getRegistrationForm(registrationKey);
            EventSignup eventSignup = businessService.getEventSignup();
            prepareHeader(currentEvent, model);
            model.addAttribute("payPalError", payPalRESTException.getDetails());
            model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
            model.addAttribute("registrationDetails", registerForm);
            model.addAttribute("registrationKey", registrationKey);
            model.addAttribute("paymentId", paymentId);
            model.addAttribute("payerId", payerId);
            return "confirmRegistration";
        }
    }

    @RequestMapping(value = "/s/registerPageTwo", method = RequestMethod.POST)
    public String validateDetailsForm(HttpServletRequest request, Model model,
            @Valid RegistrationDetails registerForm, BindingResult result) {

        Event currentEvent = businessService.getCurrentEvent();
        EventSignup eventSignup = businessService.getEventSignup();
        PaymentMethod paymentMethod = PaymentMethod.PAYPAL;
        prepareHeader(currentEvent, model);
        model.addAttribute("signupRegisterView", new SignupRegisterView(eventSignup));
        model.addAttribute("registrationDetails", registerForm);
        registerForm.setFinalCost(getTotal(registerForm));
        registerForm.setEvent(currentEvent);

        if (result.hasErrors()) {
            return "register2";
        }

        for (int index = 0; index < registerForm.getOrderDetails().size(); index++) {
            TicketOrderDetail orderDetails = registerForm.getOrderDetails().get(index);

            TicketGroup ticketGroup = businessService.getTicketGroup(orderDetails.getTicketGroup());

            if (!com.google.common.base.Strings.isNullOrEmpty(orderDetails.getCouponCode())
                    && ticketGroup.getCouponCodes() != null && ticketGroup.getCouponCodes().size() > 0) {
                if (!hasCode(ticketGroup.getCouponCodes(), orderDetails.getCouponCode())) {
                    result.addError(new FieldError("registrationDetails", "orderDetails[" + index + "].couponCode",
                            "Invalid Coupon Code."));
                }
            }

            if (StringUtils.isEmpty(orderDetails.getFirstName())) {
                result.rejectValue("orderDetails[" + index + "].firstName", "firstName.isRequired",
                        "First Name is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getLastName())) {
                result.rejectValue("orderDetails[" + index + "].lastName", "lastName.isRequired",
                        "Last Name is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getEmailAddress())) {
                result.rejectValue("orderDetails[" + index + "].emailAddress", "emailAddress.isReq uired",
                        "Email Address is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getCity())) {
                result.rejectValue("orderDetails[" + index + "].city", "city.isRequired", "City is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getState())) {
                result.rejectValue("orderDetails[" + index + "].state", "state.isRequired", "State is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getCountry())) {
                result.rejectValue("orderDetails[" + index + "].country", "country.isRequired",
                        "Country is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getJobTitle())) {
                result.rejectValue("orderDetails[" + index + "].jobTitle", "jobTitle.isRequired",
                        "Job Title is required.");
            }

            if (StringUtils.isEmpty(orderDetails.getCompany())) {
                result.rejectValue("orderDetails[" + index + "].company", "company.isRequired",
                        "Company is required.");
            }

        }

        if (result.hasErrors()) {

            return "register2";
        }

        for (TicketOrderDetail detail : registerForm.getOrderDetails()) {
            detail.setRegistration(registerForm);
        }

        switch (paymentMethod) {

        case INVOICE:
            registerForm.setPaymentState(RegistrationDetails.PaymentState.REQUIRES_INVOICE);
            registerForm.setFinalCost(getTotal(registerForm));
            businessService.createPendingRegistrationForm(registerForm);
            return "index";
        case PAYPAL:
            registerForm.setPaymentState(RegistrationDetails.PaymentState.PAYPAL_CREATED);
            registerForm.setFinalCost(getTotal(registerForm));
            registerForm = businessService.createPendingRegistrationForm(registerForm);
            String baseUrl = String.format("%s://%s:%d/", request.getScheme(), request.getServerName(),
                    request.getServerPort());
            Payment createdPayment = runPayPal(registerForm, baseUrl);
            return "redirect:" + createdPayment.getLinks().stream().filter(link -> {
                return link.getRel().equals("approval_url");
            }).findFirst().get().getHref();
        default:
            throw new IllegalStateException("The system did not understand the payment type.");

        }

    }

    private void prepareHeader(Event event, Model model) {
        final ScheduleItemList scheduleItemList = businessService.getScheduleForEvent(event.getId());

        model.addAttribute("event", event);
        SpeakerList speakers = new SpeakerList();
        speakers.setSpeakers(businessService.getSpeakersForEvent(event.getId()));
        model.addAttribute("speakerList", speakers);

        model.addAttribute("scheduleItemList", scheduleItemList);

    }

    private Payment runPayPal(RegistrationDetails registerForm, String serverBaseUrl) {
        final PayPalSession payPalSession = payPalSession();

        Amount amount = new Amount();
        amount.setCurrency("USD");
        final BigDecimal total = getTotal(registerForm);

        Transaction transaction = new Transaction();
        transaction.setDescription("DevNexus Registration");
        transaction.setAmount(amount);

        ItemList itemlist = new ItemList();
        List<Item> items = new ArrayList<>(registerForm.getOrderDetails().size());
        for (TicketOrderDetail order : registerForm.getOrderDetails()) {
            items.add(new Item("1",
                    String.format("Registration for %s %s", order.getFirstName(), order.getLastName()),
                    getOrderPrice(order).setScale(2).toString(), "USD"));
        }
        itemlist.setItems(items);

        amount.setTotal(total.setScale(2).toString());
        List<Transaction> transactions = new ArrayList<Transaction>();
        transactions.add(transaction);
        transaction.setItemList(itemlist);
        Payer payer = new Payer();
        payer.setPaymentMethod("paypal");

        Payment payment = new Payment();
        payment.setIntent("sale");
        payment.setPayer(payer);
        payment.setTransactions(transactions);
        RedirectUrls redirectUrls = new RedirectUrls();
        redirectUrls.setCancelUrl(serverBaseUrl + "/s/registerPageTwo/" + registerForm.getRegistrationFormKey());
        redirectUrls
                .setReturnUrl(serverBaseUrl + "/s/executeRegistration/" + registerForm.getRegistrationFormKey());
        payment.setRedirectUrls(redirectUrls);

        return payPalSession.createPayment(payment);
    }

    private BigDecimal getTotal(RegistrationDetails registerForm) {
        BigDecimal total = BigDecimal.ZERO;

        for (TicketOrderDetail order : registerForm.getOrderDetails()) {

            total = total.add(getOrderPrice(order));
        }

        return total.setScale(2);
    }

    private boolean hasCode(Collection<CouponCode> couponCodes, String couponCode) {
        for (CouponCode code : couponCodes) {
            if (code.getCode().equals(couponCode)) {
                return true;
            }
        }
        return false;
    }

    private CouponCode findCode(List<CouponCode> couponCodes, String couponCode) {
        for (CouponCode code : couponCodes) {
            if (code.getCode().equals(couponCode)) {
                return code;
            }
        }
        return CouponCode.EMPTY;
    }

    public PayPalSession payPalSession() {
        if (environment.acceptsProfiles(SpringProfile.PAYPAL_SANDBOX)) {
            return PayPalSession.getSession(environment.getRequiredProperty("PAYPAL_CLIENT_ID"),
                    environment.getRequiredProperty("PAYPAL_CLIENT_SECRET"));
        } else if (environment.acceptsProfiles(SpringProfile.PAYPAL_LIVE)) {
            return PayPalSession.getLiveSession(environment.getRequiredProperty("PAYPAL_CLIENT_ID"),
                    environment.getRequiredProperty("PAYPAL_CLIENT_SECRET"));
        } else {
            return PayPalSession.DUMMY;
        }
    }

    private BigDecimal getOrderPrice(TicketOrderDetail order) {
        TicketGroup ticketGroup = businessService.getTicketGroup(order.getTicketGroup());
        BigDecimal ticketPrice = ticketGroup.getPrice();
        if (!com.google.common.base.Strings.isNullOrEmpty(order.getCouponCode())) {
            CouponCode code = findCode(ticketGroup.getCouponCodes(), order.getCouponCode());
            if (CouponCode.EMPTY != code) {
                ticketPrice = code.getPrice();
            }
        }
        return ticketPrice;
    }

}