package org.synyx.urlaubsverwaltung.web.application; import org.apache.log4j.Logger; import org.joda.time.DateMidnight; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.DataBinder; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; 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.servlet.mvc.support.RedirectAttributes; import org.synyx.urlaubsverwaltung.core.account.domain.Account; import org.synyx.urlaubsverwaltung.core.account.service.AccountService; import org.synyx.urlaubsverwaltung.core.application.domain.Application; import org.synyx.urlaubsverwaltung.core.application.service.ApplicationInteractionService; import org.synyx.urlaubsverwaltung.core.application.service.VacationTypeService; import org.synyx.urlaubsverwaltung.core.person.Person; import org.synyx.urlaubsverwaltung.core.person.PersonService; import org.synyx.urlaubsverwaltung.core.person.Role; import org.synyx.urlaubsverwaltung.security.SessionService; import org.synyx.urlaubsverwaltung.web.ControllerConstants; import org.synyx.urlaubsverwaltung.web.DateMidnightPropertyEditor; import org.synyx.urlaubsverwaltung.web.DecimalNumberPropertyEditor; import org.synyx.urlaubsverwaltung.web.PersonPropertyEditor; import org.synyx.urlaubsverwaltung.web.TimePropertyEditor; import org.synyx.urlaubsverwaltung.web.person.PersonConstants; import org.synyx.urlaubsverwaltung.web.person.UnknownPersonException; import java.math.BigDecimal; import java.sql.Time; import java.util.List; import java.util.Locale; import java.util.Optional; /** * Controller to apply for leave. * * @author Aljona Murygina - murygina@synyx.de */ @Controller @RequestMapping("/web") public class ApplyForLeaveController { private static final Logger LOG = Logger.getLogger(ApplyForLeaveController.class); @Autowired private SessionService sessionService; @Autowired private PersonService personService; @Autowired private AccountService accountService; @Autowired private VacationTypeService vacationTypeService; @Autowired private ApplicationInteractionService applicationInteractionService; @Autowired private ApplicationValidator applicationValidator; @InitBinder public void initBinder(DataBinder binder, Locale locale) { binder.registerCustomEditor(DateMidnight.class, new DateMidnightPropertyEditor()); binder.registerCustomEditor(Time.class, new TimePropertyEditor()); binder.registerCustomEditor(BigDecimal.class, new DecimalNumberPropertyEditor(locale)); binder.registerCustomEditor(Person.class, new PersonPropertyEditor(personService)); } /** * Show form to apply for leave. * * @param personId of the person that applies for leave * @param model to be filled * * @return form to apply for leave */ @RequestMapping(value = "/application/new", method = RequestMethod.GET) public String newApplicationForm( @RequestParam(value = PersonConstants.PERSON_ATTRIBUTE, required = false) Integer personId, Model model) throws UnknownPersonException, AccessDeniedException { Person signedInUser = sessionService.getSignedInUser(); Person person; if (personId == null) { person = signedInUser; } else { person = personService.getPersonByID(personId).orElseThrow(() -> new UnknownPersonException(personId)); } boolean isApplyingForOneSelf = person.equals(signedInUser); // only office may apply for leave on behalf of other users if (!isApplyingForOneSelf && !signedInUser.hasRole(Role.OFFICE)) { throw new AccessDeniedException(String.format( "User '%s' has not the correct permissions to apply for leave for user '%s'", signedInUser.getLoginName(), person.getLoginName())); } Optional<Account> holidaysAccount = accountService.getHolidaysAccount(DateMidnight.now().getYear(), person); if (holidaysAccount.isPresent()) { prepareApplicationForLeaveForm(person, new ApplicationForLeaveForm(), model); } model.addAttribute("noHolidaysAccount", !holidaysAccount.isPresent()); return "application/app_form"; } private void prepareApplicationForLeaveForm(Person person, ApplicationForLeaveForm appForm, Model model) { List<Person> persons = personService.getActivePersons(); model.addAttribute(PersonConstants.PERSON_ATTRIBUTE, person); model.addAttribute(PersonConstants.PERSONS_ATTRIBUTE, persons); model.addAttribute("application", appForm); model.addAttribute("vacationTypes", vacationTypeService.getVacationTypes()); } @RequestMapping(value = "/application", method = RequestMethod.POST) public String newApplication(@ModelAttribute("application") ApplicationForLeaveForm appForm, Errors errors, Model model, RedirectAttributes redirectAttributes) throws UnknownPersonException { LOG.info("POST new application received: " + appForm.toString()); Person applier = sessionService.getSignedInUser(); applicationValidator.validate(appForm, errors); if (errors.hasErrors()) { prepareApplicationForLeaveForm(appForm.getPerson(), appForm, model); if (errors.hasGlobalErrors()) { model.addAttribute(ControllerConstants.ERRORS_ATTRIBUTE, errors); } LOG.info(String.format("new application (%s) has errors: %s", appForm.toString(), errors.toString())); return "application/app_form"; } Application application = appForm.generateApplicationForLeave(); Application savedApplicationForLeave = applicationInteractionService.apply(application, applier, Optional.ofNullable(appForm.getComment())); LOG.info("new application with sucess applied" + savedApplicationForLeave.toString()); redirectAttributes.addFlashAttribute("applySuccess", true); return "redirect:/web/application/" + savedApplicationForLeave.getId(); } }