package org.synyx.urlaubsverwaltung.web.overtime;
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.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.servlet.mvc.support.RedirectAttributes;
import org.synyx.urlaubsverwaltung.core.overtime.Overtime;
import org.synyx.urlaubsverwaltung.core.overtime.OvertimeAction;
import org.synyx.urlaubsverwaltung.core.overtime.OvertimeService;
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.person.PersonConstants;
import org.synyx.urlaubsverwaltung.web.person.UnknownPersonException;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.Optional;
/**
* Manage overtime of persons.
*
* @author Aljona Murygina - murygina@synyx.de
*/
@Controller
@RequestMapping("/web")
public class OvertimeController {
@Autowired
private OvertimeService overtimeService;
@Autowired
private PersonService personService;
@Autowired
private SessionService sessionService;
@Autowired
private OvertimeValidator validator;
@InitBinder
public void initBinder(DataBinder binder, Locale locale) {
binder.registerCustomEditor(DateMidnight.class, new DateMidnightPropertyEditor());
binder.registerCustomEditor(BigDecimal.class, new DecimalNumberPropertyEditor(locale));
binder.registerCustomEditor(Person.class, new PersonPropertyEditor(personService));
}
@RequestMapping(value = "/overtime", method = RequestMethod.GET)
public String showPersonalOvertime() {
Person signedInUser = sessionService.getSignedInUser();
return "redirect:/web/overtime?person=" + signedInUser.getId();
}
@RequestMapping(value = "/overtime", method = RequestMethod.GET, params = PersonConstants.PERSON_ATTRIBUTE)
public String showOvertime(
@RequestParam(value = PersonConstants.PERSON_ATTRIBUTE, required = true) Integer personId,
@RequestParam(value = ControllerConstants.YEAR_ATTRIBUTE, required = false) Integer requestedYear, Model model)
throws UnknownPersonException {
Integer year = requestedYear == null ? DateMidnight.now().getYear() : requestedYear;
Person person = personService.getPersonByID(personId).orElseThrow(() -> new UnknownPersonException(personId));
Person signedInUser = sessionService.getSignedInUser();
if (!sessionService.isSignedInUserAllowedToAccessPersonData(signedInUser, person)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to see overtime records of user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
model.addAttribute("year", year);
model.addAttribute("person", person);
model.addAttribute("records", overtimeService.getOvertimeRecordsForPersonAndYear(person, year));
model.addAttribute("overtimeTotal", overtimeService.getTotalOvertimeForPersonAndYear(person, year));
model.addAttribute("overtimeLeft", overtimeService.getLeftOvertimeForPerson(person));
return "overtime/overtime_list";
}
@RequestMapping(value = "/overtime/{id}", method = RequestMethod.GET)
public String showOvertimeDetails(@PathVariable("id") Integer id, Model model) throws UnknownOvertimeException,
AccessDeniedException {
Overtime overtime = overtimeService.getOvertimeById(id).orElseThrow(() -> new UnknownOvertimeException(id));
Person person = overtime.getPerson();
Person signedInUser = sessionService.getSignedInUser();
if (!sessionService.isSignedInUserAllowedToAccessPersonData(signedInUser, person)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to see overtime records of user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
model.addAttribute("record", overtime);
model.addAttribute("comments", overtimeService.getCommentsForOvertime(overtime));
model.addAttribute("overtimeTotal",
overtimeService.getTotalOvertimeForPersonAndYear(person, overtime.getEndDate().getYear()));
model.addAttribute("overtimeLeft", overtimeService.getLeftOvertimeForPerson(person));
return "overtime/overtime_details";
}
@RequestMapping(value = "/overtime/new", method = RequestMethod.GET)
public String recordOvertime(
@RequestParam(value = PersonConstants.PERSON_ATTRIBUTE, required = false) Integer personId, Model model)
throws UnknownPersonException {
Person signedInUser = sessionService.getSignedInUser();
Person person;
if (personId != null) {
person = personService.getPersonByID(personId).orElseThrow(() -> new UnknownPersonException(personId));
} else {
person = signedInUser;
}
if (!signedInUser.equals(person) && !signedInUser.hasRole(Role.OFFICE)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to record overtime for user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
model.addAttribute("overtime", new OvertimeForm(person));
return "overtime/overtime_form";
}
@RequestMapping(value = "/overtime", method = RequestMethod.POST)
public String recordOvertime(@ModelAttribute("overtime") OvertimeForm overtimeForm, Errors errors, Model model,
RedirectAttributes redirectAttributes) {
Person signedInUser = sessionService.getSignedInUser();
Person person = overtimeForm.getPerson();
if (!signedInUser.equals(person) && !signedInUser.hasRole(Role.OFFICE)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to record overtime for user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
validator.validate(overtimeForm, errors);
if (errors.hasErrors()) {
model.addAttribute("overtime", overtimeForm);
return "overtime/overtime_form";
}
Overtime recordedOvertime = overtimeService.record(overtimeForm.generateOvertime(),
Optional.ofNullable(overtimeForm.getComment()), sessionService.getSignedInUser());
redirectAttributes.addFlashAttribute("overtimeRecord", OvertimeAction.CREATED.name());
return "redirect:/web/overtime/" + recordedOvertime.getId();
}
@RequestMapping(value = "/overtime/{id}/edit", method = RequestMethod.GET)
public String editOvertime(@PathVariable("id") Integer id, Model model) throws UnknownOvertimeException {
Overtime overtime = overtimeService.getOvertimeById(id).orElseThrow(() -> new UnknownOvertimeException(id));
Person signedInUser = sessionService.getSignedInUser();
Person person = overtime.getPerson();
if (!signedInUser.equals(person) && !signedInUser.hasRole(Role.OFFICE)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to edit overtime record of user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
model.addAttribute("overtime", new OvertimeForm(overtime));
return "overtime/overtime_form";
}
@RequestMapping(value = "/overtime/{id}", method = RequestMethod.POST)
public String updateOvertime(@PathVariable("id") Integer id,
@ModelAttribute("overtime") OvertimeForm overtimeForm, Errors errors, Model model,
RedirectAttributes redirectAttributes) throws UnknownOvertimeException {
Overtime overtime = overtimeService.getOvertimeById(id).orElseThrow(() -> new UnknownOvertimeException(id));
Person signedInUser = sessionService.getSignedInUser();
Person person = overtime.getPerson();
if (!signedInUser.equals(person) && !signedInUser.hasRole(Role.OFFICE)) {
throw new AccessDeniedException(String.format(
"User '%s' has not the correct permissions to edit overtime record of user '%s'",
signedInUser.getLoginName(), person.getLoginName()));
}
validator.validate(overtimeForm, errors);
if (errors.hasErrors()) {
model.addAttribute("overtime", overtimeForm);
return "overtime/overtime_form";
}
overtimeForm.updateOvertime(overtime);
overtimeService.record(overtime, Optional.ofNullable(overtimeForm.getComment()),
sessionService.getSignedInUser());
redirectAttributes.addFlashAttribute("overtimeRecord", OvertimeAction.EDITED.name());
return "redirect:/web/overtime/" + id;
}
}