integrated the business module
This commit is contained in:
		| @@ -57,7 +57,7 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { | ||||
| 		super.configure(http); | ||||
| 		http.authorizeRequests() | ||||
| 		// @formatter:off | ||||
| 		  .antMatchers("/user/**", "/business/**").authenticated() | ||||
| 		  .antMatchers("/dashboard/**", "/business/**").authenticated() | ||||
|   		.anyRequest().permitAll(); | ||||
|   	// @formatter:on | ||||
| //		http.anonymous().disable(); | ||||
|   | ||||
| @@ -0,0 +1,62 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings; | ||||
|  | ||||
| import javax.annotation.security.RolesAllowed; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.ModelAttribute; | ||||
| import org.springframework.web.bind.annotation.PathVariable; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.bookings.impl.BookerBean; | ||||
| import de.jottyfan.camporganizer.module.business.business.IBusinessService; | ||||
| import de.jottyfan.camporganizer.module.business.bookings.impl.AddPaymentBean; | ||||
|  | ||||
| /** | ||||
| * | ||||
| * @author jotty | ||||
| * | ||||
| */ | ||||
| @Controller | ||||
| public class BookingsController { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private HttpServletRequest request; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IBusinessService indexService; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IBookingsService bookingsService; | ||||
|  | ||||
| 	@GetMapping("/business/bookings") | ||||
| 	@RolesAllowed({"business_booking"}) | ||||
| 	public String getBookings(Model model) { | ||||
| 		String username = indexService.getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 		model.addAttribute("bookers", bookingsService.getBookers(username)); | ||||
| 		return "business/bookings"; | ||||
| 	} | ||||
|  | ||||
| 	@GetMapping("/business/bookings/{id}") | ||||
| 	@RolesAllowed({"business_booking"}) | ||||
| 	public String getBooking(Model model, @PathVariable Integer id) { | ||||
| 		String username = indexService.getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 		BookerBean bean = bookingsService.getBooker(id, username); | ||||
| 		model.addAttribute("booker", bean); | ||||
| 		model.addAttribute("addBean", new AddPaymentBean()); | ||||
| 		return bean == null ? getBookings(model) : "business/booker"; | ||||
| 	} | ||||
|  | ||||
| 	@PostMapping("/business/bookings/payment/{id}") | ||||
| 	@RolesAllowed({"business_booking"}) | ||||
| 	public String addBooking(Model model, @ModelAttribute AddPaymentBean bean, @PathVariable Integer id) { | ||||
| 		Double payment = bean.getPayment(); | ||||
| 		bookingsService.addPayment(id, payment); | ||||
| 		return getBooking(model, id); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,38 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.bookings.impl.BookerBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public interface IBookingsService { | ||||
| 	/** | ||||
| 	 * get the bookers information | ||||
| 	 * | ||||
| 	 * @param username the name of the user in this session | ||||
| 	 * @return the list of bookers; an empty one at least | ||||
| 	 */ | ||||
| 	public List<BookerBean> getBookers(String username); | ||||
|  | ||||
| 	/** | ||||
| 	 * get the booker referenced by id | ||||
| 	 * | ||||
| 	 * @param id       the ID of the booker | ||||
| 	 * @param username the name of the user in this session | ||||
| 	 * @return the booker if found; null otherwise | ||||
| 	 */ | ||||
| 	public BookerBean getBooker(Integer id, String username); | ||||
|  | ||||
| 	/** | ||||
| 	 * add payment to the paid values of user with id | ||||
| 	 * | ||||
| 	 * @param id      the ID of the booker | ||||
| 	 * @param payment the payment (additional value) | ||||
| 	 * @return number of affected database rows, should be 1 | ||||
| 	 */ | ||||
| 	public Integer addPayment(Integer id, Double payment); | ||||
| } | ||||
| @@ -0,0 +1,21 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class AddPaymentBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
| 	private Double payment; | ||||
|  | ||||
| 	public Double getPayment() { | ||||
| 		return payment; | ||||
| 	} | ||||
|  | ||||
| 	public void setPayment(Double payment) { | ||||
| 		this.payment = payment; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,120 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class BookerBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private Integer pk; | ||||
| 	private String name; | ||||
| 	private String role; | ||||
| 	private String sex; | ||||
| 	private Boolean accept; | ||||
| 	private LocalDateTime bookingDate; | ||||
| 	private BigDecimal paid; | ||||
| 	private String camp; | ||||
| 	private String price; | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the accept | ||||
| 	 */ | ||||
| 	public Boolean getAccept() { | ||||
| 		return accept; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param accept the accept to set | ||||
| 	 */ | ||||
| 	public void setAccept(Boolean accept) { | ||||
| 		this.accept = accept; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the paid | ||||
| 	 */ | ||||
| 	public BigDecimal getPaid() { | ||||
| 		return paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param paid the paid to set | ||||
| 	 */ | ||||
| 	public void setPaid(BigDecimal paid) { | ||||
| 		this.paid = paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the pk | ||||
| 	 */ | ||||
| 	public Integer getPk() { | ||||
| 		return pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param pk the pk to set | ||||
| 	 */ | ||||
| 	public void setPk(Integer pk) { | ||||
| 		this.pk = pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the name | ||||
| 	 */ | ||||
| 	public String getName() { | ||||
| 		return name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param name the name to set | ||||
| 	 */ | ||||
| 	public void setName(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	public String getRole() { | ||||
| 		return role; | ||||
| 	} | ||||
|  | ||||
| 	public void setRole(String role) { | ||||
| 		this.role = role; | ||||
| 	} | ||||
|  | ||||
| 	public String getSex() { | ||||
| 		return sex; | ||||
| 	} | ||||
|  | ||||
| 	public void setSex(String sex) { | ||||
| 		this.sex = sex; | ||||
| 	} | ||||
|  | ||||
| 	public LocalDateTime getBookingDate() { | ||||
| 		return bookingDate; | ||||
| 	} | ||||
|  | ||||
| 	public void setBookingDate(LocalDateTime bookingDate) { | ||||
| 		this.bookingDate = bookingDate; | ||||
| 	} | ||||
|  | ||||
| 	public String getCamp() { | ||||
| 		return camp; | ||||
| 	} | ||||
|  | ||||
| 	public void setCamp(String camp) { | ||||
| 		this.camp = camp; | ||||
| 	} | ||||
|  | ||||
| 	public String getPrice() { | ||||
| 		return price; | ||||
| 	} | ||||
|  | ||||
| 	public void setPrice(String price) { | ||||
| 		this.price = price; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,146 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings.impl; | ||||
|  | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALESPROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.Record; | ||||
| import org.jooq.Record10; | ||||
| import org.jooq.Record11; | ||||
| import org.jooq.SelectConditionStep; | ||||
| import org.jooq.SelectSeekStep4; | ||||
| import org.jooq.UpdateConditionStep; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
|  | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole; | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumSex; | ||||
| import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Repository | ||||
| @Transactional(transactionManager = "transactionManager") | ||||
| public class BookingsGateway { | ||||
| 	private static final Logger LOGGER = LogManager.getLogger(BookingsGateway.class); | ||||
|  | ||||
| 	@Autowired | ||||
| 	private DSLContext jooq; | ||||
|  | ||||
| 	/** | ||||
| 	 * get a list of all registered persons that have booked the camp | ||||
| 	 * | ||||
| 	 * @param username the name of the current user in this session | ||||
| 	 * | ||||
| 	 * @return a list of bookings; an empty one at least | ||||
| 	 */ | ||||
| 	public List<BookerBean> getBookings(String username) { | ||||
| 		SelectSeekStep4<Record10<Integer, Boolean, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, String, Double>, EnumCamprole, EnumSex, String, String> sql = jooq | ||||
| 		// @formatter:off | ||||
| 		  .select(T_PERSON.PK, T_PERSON.ACCEPT, T_PERSON.PAID, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.CREATED, V_CAMP.NAME, V_CAMP.YEAR) | ||||
| 		  .from(T_PERSON) | ||||
| 		  .leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 		  .where(T_PROFILE.USERNAME.eq(username)) | ||||
| 		  .orderBy(T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.SURNAME, T_PERSON.FORENAME); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<BookerBean> list = new ArrayList<>(); | ||||
| 		for (Record r : sql.fetch()) { | ||||
| 			String forename = r.get(T_PERSON.FORENAME); | ||||
| 			String surname = r.get(T_PERSON.SURNAME); | ||||
| 			EnumCamprole role = r.get(T_PERSON.CAMPROLE); | ||||
| 			EnumSex sex = r.get(T_PERSON.SEX); | ||||
| 			String campName = r.get(V_CAMP.NAME); | ||||
| 			Double campYear = r.get(V_CAMP.YEAR); | ||||
| 			BookerBean bean = new BookerBean(); | ||||
| 			bean.setPk(r.get(T_PERSON.PK)); | ||||
| 			bean.setName(String.format("%s %s", forename, surname)); | ||||
| 			bean.setRole(EnumCamprole.student.equals(role) ? "Teilnehmer" : "Mitarbeiter"); | ||||
| 			bean.setSex(EnumSex.female.equals(sex) ? "weiblich" : "männlich"); | ||||
| 			bean.setBookingDate(r.get(T_PERSON.CREATED)); | ||||
| 			bean.setAccept(r.get(T_PERSON.ACCEPT)); | ||||
| 			bean.setPaid(r.get(T_PERSON.PAID)); | ||||
| 			bean.setCamp(String.format("%s %4.0f", campName, campYear)); | ||||
| 			list.add(bean); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get the booking payment information of the user referenced by id | ||||
| 	 * | ||||
| 	 * @param id       the id of the user | ||||
| 	 * @param username the name of the current's session user | ||||
| 	 * @return the booker bean or null | ||||
| 	 */ | ||||
| 	public BookerBean getBooking(Integer id, String username) { | ||||
| 		SelectConditionStep<Record11<Integer, Boolean, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, String, Double, String>> sql = jooq | ||||
| 		// @formatter:off | ||||
| 		  .select(T_PERSON.PK, T_PERSON.ACCEPT, T_PERSON.PAID, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.CREATED, V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.PRICE) | ||||
| 		  .from(T_PERSON) | ||||
| 		  .leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 		  .where(T_PROFILE.USERNAME.eq(username)) | ||||
| 		  .and(T_PERSON.PK.eq(id)); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		Record r = sql.fetchOne(); | ||||
| 		if (r == null) { | ||||
| 			return null; | ||||
| 		} else { | ||||
| 			String forename = r.get(T_PERSON.FORENAME); | ||||
| 			String surname = r.get(T_PERSON.SURNAME); | ||||
| 			EnumCamprole role = r.get(T_PERSON.CAMPROLE); | ||||
| 			EnumSex sex = r.get(T_PERSON.SEX); | ||||
| 			String campName = r.get(V_CAMP.NAME); | ||||
| 			Double campYear = r.get(V_CAMP.YEAR); | ||||
| 			BookerBean bean = new BookerBean(); | ||||
| 			bean.setPk(r.get(T_PERSON.PK)); | ||||
| 			bean.setName(String.format("%s %s", forename, surname)); | ||||
| 			bean.setRole(EnumCamprole.student.equals(role) ? "Teilnehmer" : "Mitarbeiter"); | ||||
| 			bean.setSex(EnumSex.female.equals(sex) ? "weiblich" : "männlich"); | ||||
| 			bean.setBookingDate(r.get(T_PERSON.CREATED)); | ||||
| 			bean.setAccept(r.get(T_PERSON.ACCEPT)); | ||||
| 			bean.setPaid(r.get(T_PERSON.PAID)); | ||||
| 			bean.setCamp(String.format("%s %4.0f", campName, campYear)); | ||||
| 			bean.setPrice(r.get(V_CAMP.PRICE)); | ||||
| 			return bean; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * add payment for user referenced by pk | ||||
| 	 * | ||||
| 	 * @param pk      the ID of the user | ||||
| 	 * @param payment the payment (additional) | ||||
| 	 * @return the number of affected database rows, should be 1 | ||||
| 	 */ | ||||
| 	public Integer addPayment(Integer pk, Double payment) { | ||||
| 		BigDecimal oldValue = jooq.select(T_PERSON.PAID).from(T_PERSON).where(T_PERSON.PK.eq(pk)).fetchOne().get(T_PERSON.PAID); | ||||
| 		BigDecimal value = oldValue == null ? BigDecimal.valueOf(payment) : oldValue.add(BigDecimal.valueOf(payment)); | ||||
| 		UpdateConditionStep<TPersonRecord> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.update(T_PERSON) | ||||
| 			.set(T_PERSON.PAID, value) | ||||
| 			.where(T_PERSON.PK.eq(pk)); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,36 @@ | ||||
| package de.jottyfan.camporganizer.module.business.bookings.impl; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.bookings.IBookingsService; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Service | ||||
| public class BookingsService implements IBookingsService { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private BookingsGateway bookingsGateway; | ||||
|  | ||||
| 	@Override | ||||
| 	public List<BookerBean> getBookers(String username) { | ||||
| 		return bookingsGateway.getBookings(username); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public BookerBean getBooker(Integer id, String username) { | ||||
| 		return bookingsGateway.getBooking(id, username); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public Integer addPayment(Integer id, Double payment) { | ||||
| 		return bookingsGateway.addPayment(id, payment); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,31 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business; | ||||
|  | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author henkej | ||||
|  * | ||||
|  */ | ||||
| @Controller | ||||
| public class BusinessController { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private HttpServletRequest request; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IBusinessService indexService; | ||||
|  | ||||
| 	@GetMapping("/business") | ||||
| 	public String getIndex(Model model) { | ||||
| 		String username = indexService.getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 		model.addAttribute("campBudgets", indexService.getCampBudgets(username)); | ||||
| 		return "business/business"; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.business.impl.CampBudgetBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public interface IBusinessService { | ||||
| 	/** | ||||
| 	 * get the user of this session | ||||
| 	 * | ||||
| 	 * @param request the request | ||||
| 	 * @return the username of the current user | ||||
| 	 */ | ||||
| 	public String getCurrentUser(HttpServletRequest request); | ||||
|  | ||||
| 	/** | ||||
| 	 * get a list of all camp budgets of all years | ||||
| 	 * | ||||
| 	 * @param username the name of the current user in this session | ||||
| 	 * @return the list; an empty one at least | ||||
| 	 */ | ||||
| 	public List<CampBudgetBean> getCampBudgets(String username); | ||||
| } | ||||
| @@ -0,0 +1,106 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class BusinessBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private final Integer fkPerson; | ||||
| 	private final String forename; | ||||
| 	private final String surname; | ||||
| 	private final String campName; | ||||
| 	private final String campPrice; | ||||
| 	private final LocalDateTime campArrive; | ||||
| 	private final String locationName; | ||||
| 	private BigDecimal paid; | ||||
| 	private boolean changed; | ||||
|  | ||||
| 	public BusinessBean(Integer fkPerson, String forename, String surname, String campName, String campPrice, | ||||
| 			LocalDateTime campArrive, String locationName, BigDecimal paid) { | ||||
| 		super(); | ||||
| 		this.fkPerson = fkPerson; | ||||
| 		this.forename = forename; | ||||
| 		this.surname = surname; | ||||
| 		this.campName = campName; | ||||
| 		this.campPrice = campPrice; | ||||
| 		this.campArrive = campArrive; | ||||
| 		this.locationName = locationName; | ||||
| 		this.paid = paid; | ||||
| 		this.changed = false; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the paid | ||||
| 	 */ | ||||
| 	public BigDecimal getPaid() { | ||||
| 		return paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param paid the paid to set | ||||
| 	 */ | ||||
| 	public void setPaid(BigDecimal paid) { | ||||
| 		this.paid = paid; | ||||
| 		this.changed = true; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkPerson | ||||
| 	 */ | ||||
| 	public Integer getFkPerson() { | ||||
| 		return fkPerson; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the forename | ||||
| 	 */ | ||||
| 	public String getForename() { | ||||
| 		return forename; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the surname | ||||
| 	 */ | ||||
| 	public String getSurname() { | ||||
| 		return surname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campName | ||||
| 	 */ | ||||
| 	public String getCampName() { | ||||
| 		return campName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campPrice | ||||
| 	 */ | ||||
| 	public String getCampPrice() { | ||||
| 		return campPrice; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campArrive | ||||
| 	 */ | ||||
| 	public LocalDateTime getCampArrive() { | ||||
| 		return campArrive; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the locationName | ||||
| 	 */ | ||||
| 	public String getLocationName() { | ||||
| 		return locationName; | ||||
| 	} | ||||
|  | ||||
| 	public boolean isChanged() { | ||||
| 		return changed; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,138 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business.impl; | ||||
|  | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALESPROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP_BUDGET; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.Record4; | ||||
| import org.jooq.Record8; | ||||
| import org.jooq.SelectConditionStep; | ||||
| import org.jooq.SelectSeekStep1; | ||||
| import org.jooq.UpdateConditionStep; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
|  | ||||
| import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Repository | ||||
| @Transactional(transactionManager = "transactionManager") | ||||
| public class BusinessGateway { | ||||
| 	private static final Logger LOGGER = LogManager.getLogger(BusinessGateway.class); | ||||
|  | ||||
| 	@Autowired | ||||
| 	private DSLContext jooq; | ||||
|  | ||||
| 	/** | ||||
| 	 * get a list of all camp budgets of all years | ||||
| 	 * | ||||
| 	 * @param username the name of the user for privilege checks | ||||
| 	 * | ||||
| 	 * @return the list of all camp budgets | ||||
| 	 */ | ||||
| 	public List<CampBudgetBean> getCampBudgets(String username) { | ||||
| 		SelectSeekStep1<Record4<BigDecimal, String, Double, Integer>, LocalDateTime> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.select(V_CAMP_BUDGET.BUDGET, | ||||
| 					    V_CAMP_BUDGET.CAMP_NAME, | ||||
| 					    V_CAMP_BUDGET.YEAR, | ||||
| 					    V_CAMP_BUDGET.FK_CAMP) | ||||
| 			.from(V_CAMP_BUDGET) | ||||
| 			.leftJoin(T_CAMP).on(T_CAMP.PK.eq(V_CAMP_BUDGET.FK_CAMP)) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(V_CAMP_BUDGET.FK_CAMP)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 			.where(T_PROFILE.USERNAME.eq(username)) | ||||
| 			.orderBy(T_CAMP.ARRIVE); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<CampBudgetBean> list = new ArrayList<>(); | ||||
| 		for (Record4<BigDecimal, String, Double, Integer> r : sql.fetch()) { | ||||
| 			BigDecimal b = r.get(V_CAMP_BUDGET.BUDGET); | ||||
| 			String n = r.get(V_CAMP_BUDGET.CAMP_NAME); | ||||
| 			Double y = r.get(V_CAMP_BUDGET.YEAR); | ||||
| 			Integer c = r.get(V_CAMP_BUDGET.FK_CAMP); | ||||
| 			list.add(new CampBudgetBean().withBudget(b).withCampName(n).withCampYear(y).withCampId(c)); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get all registrations for the search mask | ||||
| 	 * | ||||
| 	 * @param username the name of the user for privilege checks | ||||
| 	 * | ||||
| 	 * @return a list of business beans; an empty one at least | ||||
| 	 */ | ||||
| 	public List<BusinessBean> getAllRegistrations(String username) { | ||||
| 		SelectConditionStep<Record8<Integer, String, String, String, String, LocalDateTime, String, BigDecimal>> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.select(T_PERSON.PK, | ||||
| 					    T_PERSON.FORENAME, | ||||
| 					    T_PERSON.SURNAME, | ||||
| 					    T_CAMP.NAME, | ||||
| 					    T_CAMP.PRICE, | ||||
| 					    T_CAMP.ARRIVE, | ||||
| 					    T_LOCATION.NAME, | ||||
| 					    T_PERSON.PAID) | ||||
| 			.from(T_PERSON) | ||||
| 			.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION)) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(T_CAMP.PK)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 			.where(T_PROFILE.USERNAME.eq(username)); | ||||
| 	  // @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<BusinessBean> list = new ArrayList<>(); | ||||
| 		for (Record8<Integer, String, String, String, String, LocalDateTime, String, BigDecimal> r : sql.fetch()) { | ||||
| 			Integer fkPerson = r.get(T_PERSON.PK); | ||||
| 			String forename = r.get(T_PERSON.FORENAME); | ||||
| 			String surname = r.get(T_PERSON.SURNAME); | ||||
| 			String campName = r.get(T_CAMP.NAME); | ||||
| 			String campPrice = r.get(T_CAMP.PRICE); | ||||
| 			LocalDateTime campArrive = r.get(T_CAMP.ARRIVE); | ||||
| 			String locationName = r.get(T_CAMP.NAME); | ||||
| 			BigDecimal paid = r.get(T_PERSON.PAID); | ||||
| 			list.add(new BusinessBean(fkPerson, forename, surname, campName, campPrice, campArrive, locationName, paid)); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * update the database by changed records in the list | ||||
| 	 * | ||||
| 	 * @param list the list of beans | ||||
| 	 * @return the number of affected database rows | ||||
| 	 */ | ||||
| 	public int updatePaid(List<BusinessBean> list) { | ||||
| 		Integer count = 0; | ||||
| 		for (BusinessBean bean : list) { | ||||
| 			if (bean.isChanged()) { | ||||
| 				UpdateConditionStep<TPersonRecord> sql = jooq | ||||
| 				// @formatter:off | ||||
| 					.update(T_PERSON) | ||||
| 					.set(T_PERSON.PAID, bean.getPaid()) | ||||
| 					.where(T_PERSON.PK.eq(bean.getFkPerson())); | ||||
| 				// @formatter:on | ||||
| 				LOGGER.debug(sql.toString()); | ||||
| 				count += sql.execute(); | ||||
| 			} | ||||
| 		} | ||||
| 		return count; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,38 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business.impl; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import org.jooq.exception.DataAccessException; | ||||
| import org.keycloak.KeycloakSecurityContext; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.business.IBusinessService; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Service | ||||
| public class BusinessService implements IBusinessService { | ||||
| 	@Autowired | ||||
| 	private BusinessGateway gateway; | ||||
|  | ||||
| 	@Override | ||||
| 	public String getCurrentUser(HttpServletRequest request) { | ||||
| 		KeycloakSecurityContext ksc = (KeycloakSecurityContext) request | ||||
| 				.getAttribute(KeycloakSecurityContext.class.getName()); | ||||
| 		if (ksc == null) { | ||||
| 			throw new DataAccessException("no keycloak user in session"); | ||||
| 		} | ||||
| 		return ksc.getIdToken().getPreferredUsername(); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public List<CampBudgetBean> getCampBudgets(String username) { | ||||
| 		return gateway.getCampBudgets(username); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,88 @@ | ||||
| package de.jottyfan.camporganizer.module.business.business.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class CampBudgetBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private BigDecimal budget; | ||||
| 	private String campName; | ||||
| 	private Double campYear; | ||||
| 	private Integer campId; | ||||
|  | ||||
| 	public CampBudgetBean withCampId(Integer campId) { | ||||
| 		setCampId(campId); | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public CampBudgetBean withCampName(String campName) { | ||||
| 		setCampName(campName); | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public CampBudgetBean withCampYear(Double campYear) { | ||||
| 		setCampYear(campYear); | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public CampBudgetBean withBudget(BigDecimal budget) { | ||||
| 		setBudget(budget); | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the budget | ||||
| 	 */ | ||||
| 	public BigDecimal getBudget() { | ||||
| 		return budget; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param budget the budget to set | ||||
| 	 */ | ||||
| 	public void setBudget(BigDecimal budget) { | ||||
| 		this.budget = budget; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campName | ||||
| 	 */ | ||||
| 	public String getCampName() { | ||||
| 		return campName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param campName the campName to set | ||||
| 	 */ | ||||
| 	public void setCampName(String campName) { | ||||
| 		this.campName = campName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campYear | ||||
| 	 */ | ||||
| 	public Double getCampYear() { | ||||
| 		return campYear; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param campYear the campYear to set | ||||
| 	 */ | ||||
| 	public void setCampYear(Double campYear) { | ||||
| 		this.campYear = campYear; | ||||
| 	} | ||||
|  | ||||
| 	public Integer getCampId() { | ||||
| 		return campId; | ||||
| 	} | ||||
|  | ||||
| 	public void setCampId(Integer campId) { | ||||
| 		this.campId = campId; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp; | ||||
|  | ||||
| import javax.annotation.security.RolesAllowed; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.PathVariable; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.business.IBusinessService; | ||||
|  | ||||
| /** | ||||
| * | ||||
| * @author jotty | ||||
| * | ||||
| */ | ||||
| @Controller | ||||
| public class CampController { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private HttpServletRequest request; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IBusinessService indexService; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private ICampService campService; | ||||
|  | ||||
| 	@GetMapping("/business/camp/{id}") | ||||
| 	@RolesAllowed({"business"}) | ||||
| 	public String getCamp(Model model, @PathVariable Integer id) { | ||||
| 		String username = indexService.getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 		model.addAttribute("campId", id); | ||||
| 		model.addAttribute("camp", campService.getCamp(id, username)); | ||||
| 		model.addAttribute("booking", campService.getBookings(id, username)); | ||||
| 		model.addAttribute("bookers", campService.getBookers(id, username)); | ||||
| 		return "business/camp"; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,43 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.camp.impl.BookingBean; | ||||
| import de.jottyfan.camporganizer.module.business.camp.impl.CampBean; | ||||
| import de.jottyfan.camporganizer.module.business.camp.impl.PersonBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public interface ICampService { | ||||
|  | ||||
| 	/** | ||||
| 	 * get the camp bean of id | ||||
| 	 * | ||||
| 	 * @param id the id of the camp | ||||
| 	 * @param username the name of the user in this session | ||||
| 	 * @return the camp bean if found; null otherwise | ||||
| 	 */ | ||||
| 	public CampBean getCamp(Integer id, String username); | ||||
|  | ||||
| 	/** | ||||
| 	 * get the booking information for camp with id | ||||
| 	 * | ||||
| 	 * @param id the id of the camp | ||||
| 	 * @param username the name of the user in this session | ||||
| 	 * @return a booking bean | ||||
| 	 */ | ||||
| 	public BookingBean getBookings(Integer id, String username); | ||||
|  | ||||
| 	/** | ||||
| 	 * get the bookers information for camp with id | ||||
| 	 * | ||||
| 	 * @param id the id of the camp | ||||
| 	 * @param username the name of the user in this session | ||||
| 	 * @return the list of bookers; an empty one at least | ||||
| 	 */ | ||||
| 	public List<PersonBean> getBookers(Integer id, String username); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,108 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole; | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumSex; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class BookerBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private Integer pk; | ||||
| 	private String name; | ||||
| 	private EnumCamprole campRole; | ||||
| 	private EnumSex sex; | ||||
| 	private LocalDateTime bookingDate; | ||||
| 	private BigDecimal paid; | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the pk | ||||
| 	 */ | ||||
| 	public Integer getPk() { | ||||
| 		return pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param pk the pk to set | ||||
| 	 */ | ||||
| 	public void setPk(Integer pk) { | ||||
| 		this.pk = pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the name | ||||
| 	 */ | ||||
| 	public String getName() { | ||||
| 		return name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param name the name to set | ||||
| 	 */ | ||||
| 	public void setName(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campRole | ||||
| 	 */ | ||||
| 	public EnumCamprole getCampRole() { | ||||
| 		return campRole; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param campRole the campRole to set | ||||
| 	 */ | ||||
| 	public void setCampRole(EnumCamprole campRole) { | ||||
| 		this.campRole = campRole; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the sex | ||||
| 	 */ | ||||
| 	public EnumSex getSex() { | ||||
| 		return sex; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param sex the sex to set | ||||
| 	 */ | ||||
| 	public void setSex(EnumSex sex) { | ||||
| 		this.sex = sex; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the bookingDate | ||||
| 	 */ | ||||
| 	public LocalDateTime getBookingDate() { | ||||
| 		return bookingDate; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param bookingDate the bookingDate to set | ||||
| 	 */ | ||||
| 	public void setBookingDate(LocalDateTime bookingDate) { | ||||
| 		this.bookingDate = bookingDate; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the paid | ||||
| 	 */ | ||||
| 	public BigDecimal getPaid() { | ||||
| 		return paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param paid the paid to set | ||||
| 	 */ | ||||
| 	public void setPaid(BigDecimal paid) { | ||||
| 		this.paid = paid; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,75 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class BookingBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private Integer approved; | ||||
| 	private Integer rejected; | ||||
| 	private Integer open; | ||||
| 	private BigDecimal paid; | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the approved | ||||
| 	 */ | ||||
| 	public Integer getApproved() { | ||||
| 		return approved; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param approved the approved to set | ||||
| 	 */ | ||||
| 	public void setApproved(Integer approved) { | ||||
| 		this.approved = approved; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the rejected | ||||
| 	 */ | ||||
| 	public Integer getRejected() { | ||||
| 		return rejected; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param rejected the rejected to set | ||||
| 	 */ | ||||
| 	public void setRejected(Integer rejected) { | ||||
| 		this.rejected = rejected; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the open | ||||
| 	 */ | ||||
| 	public Integer getOpen() { | ||||
| 		return open; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param open the open to set | ||||
| 	 */ | ||||
| 	public void setOpen(Integer open) { | ||||
| 		this.open = open; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the paid | ||||
| 	 */ | ||||
| 	public BigDecimal getPaid() { | ||||
| 		return paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param paid the paid to set | ||||
| 	 */ | ||||
| 	public void setPaid(BigDecimal paid) { | ||||
| 		this.paid = paid; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,129 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.privileges.impl.ProfileBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class CampBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 2L; | ||||
|  | ||||
| 	private Integer pk; | ||||
| 	private String name; | ||||
| 	private Double year; | ||||
| 	private LocalDateTime arrive; | ||||
| 	private LocalDateTime depart; | ||||
| 	private String locationName; | ||||
| 	private String price; | ||||
| 	private List<ProfileBean> profiles; | ||||
|  | ||||
| 	public CampBean() { | ||||
| 		profiles = new ArrayList<>(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the name | ||||
| 	 */ | ||||
| 	public String getName() { | ||||
| 		return name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param name the name to set | ||||
| 	 */ | ||||
| 	public void setName(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the year | ||||
| 	 */ | ||||
| 	public Double getYear() { | ||||
| 		return year; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param year the year to set | ||||
| 	 */ | ||||
| 	public void setYear(Double year) { | ||||
| 		this.year = year; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the arrive | ||||
| 	 */ | ||||
| 	public LocalDateTime getArrive() { | ||||
| 		return arrive; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param arrive the arrive to set | ||||
| 	 */ | ||||
| 	public void setArrive(LocalDateTime arrive) { | ||||
| 		this.arrive = arrive; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the depart | ||||
| 	 */ | ||||
| 	public LocalDateTime getDepart() { | ||||
| 		return depart; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param depart the depart to set | ||||
| 	 */ | ||||
| 	public void setDepart(LocalDateTime depart) { | ||||
| 		this.depart = depart; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the locationName | ||||
| 	 */ | ||||
| 	public String getLocationName() { | ||||
| 		return locationName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param locationName the locationName to set | ||||
| 	 */ | ||||
| 	public void setLocationName(String locationName) { | ||||
| 		this.locationName = locationName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the price | ||||
| 	 */ | ||||
| 	public String getPrice() { | ||||
| 		return price; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param price the price to set | ||||
| 	 */ | ||||
| 	public void setPrice(String price) { | ||||
| 		this.price = price; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the profiles | ||||
| 	 */ | ||||
| 	public List<ProfileBean> getProfiles() { | ||||
| 		return profiles; | ||||
| 	} | ||||
|  | ||||
| 	public Integer getPk() { | ||||
| 		return pk; | ||||
| 	} | ||||
|  | ||||
| 	public void setPk(Integer pk) { | ||||
| 		this.pk = pk; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,110 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALESPROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.Record; | ||||
| import org.jooq.Record6; | ||||
| import org.jooq.Record8; | ||||
| import org.jooq.SelectConditionStep; | ||||
| import org.jooq.SelectSeekStep4; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
|  | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole; | ||||
| import de.jottyfan.camporganizer.db.jooq.enums.EnumSex; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Repository | ||||
| @Transactional(transactionManager = "transactionManager") | ||||
| public class CampGateway { | ||||
| 	private static final Logger LOGGER = LogManager.getLogger(CampGateway.class); | ||||
|  | ||||
| 	@Autowired | ||||
| 	private DSLContext jooq; | ||||
|  | ||||
| 	/** | ||||
| 	 * get the camp referenced by pk | ||||
| 	 * | ||||
| 	 * @param pk       the ID of the camp | ||||
| 	 * @param username the name of the current user in this session | ||||
| 	 * | ||||
| 	 * @return the camp if found or null | ||||
| 	 */ | ||||
| 	public CampBean getCamp(Integer pk, String username) { | ||||
| 		SelectConditionStep<Record6<String, Double, LocalDateTime, LocalDateTime, String, String>> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.select(V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.ARRIVE, V_CAMP.DEPART, V_CAMP.LOCATION_NAME, V_CAMP.PRICE) | ||||
| 			.from(V_CAMP) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(V_CAMP.PK)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 			.where(V_CAMP.PK.eq(pk)) | ||||
| 			.and(T_PROFILE.USERNAME.eq(username)); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		CampBean bean = new CampBean(); | ||||
| 		for (Record6<String, Double, LocalDateTime, LocalDateTime, String, String> r : sql.fetch()) { | ||||
| 			bean.setName(r.get(V_CAMP.NAME)); | ||||
| 			bean.setYear(r.get(V_CAMP.YEAR)); | ||||
| 			bean.setArrive(r.get(V_CAMP.ARRIVE)); | ||||
| 			bean.setDepart(r.get(V_CAMP.DEPART)); | ||||
| 			bean.setLocationName(r.get(V_CAMP.LOCATION_NAME)); | ||||
| 			bean.setPrice(r.get(V_CAMP.PRICE)); | ||||
| 		} | ||||
| 		return bean; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * get a list of all registered persons that have booked the camp | ||||
| 	 * | ||||
| 	 * @param pk       the ID of the camp | ||||
| 	 * @param username the name of the current user in this session | ||||
| 	 * | ||||
| 	 * @return a list of bookings; an empty one at least | ||||
| 	 */ | ||||
| 	public List<PersonBean> getBookings(Integer pk, String username) { | ||||
| 		SelectSeekStep4<Record8<Integer, Boolean, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime>, EnumCamprole, EnumSex, String, String> sql = jooq | ||||
| 		// @formatter:off | ||||
| 		  .select(T_PERSON.PK, T_PERSON.ACCEPT, T_PERSON.PAID, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.CREATED) | ||||
| 		  .from(T_PERSON) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 		  .where(T_PERSON.FK_CAMP.eq(pk)) | ||||
| 		  .and(T_PROFILE.USERNAME.eq(username)) | ||||
| 		  .orderBy(T_PERSON.CAMPROLE, T_PERSON.SEX, T_PERSON.SURNAME, T_PERSON.FORENAME); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<PersonBean> list = new ArrayList<>(); | ||||
| 		for (Record r : sql.fetch()) { | ||||
| 			String forename = r.get(T_PERSON.FORENAME); | ||||
| 			String surname = r.get(T_PERSON.SURNAME); | ||||
| 			EnumCamprole role = r.get(T_PERSON.CAMPROLE); | ||||
| 			EnumSex sex = r.get(T_PERSON.SEX); | ||||
| 			PersonBean bean = new PersonBean(); | ||||
| 			bean.setPk(r.get(T_PERSON.PK)); | ||||
| 			bean.setName(String.format("%s %s", forename, surname)); | ||||
| 			bean.setRole(EnumCamprole.student.equals(role) ? "Teilnehmer" : "Mitarbeiter"); | ||||
| 			bean.setSex(EnumSex.female.equals(sex) ? "weiblich" : "männlich"); | ||||
| 			bean.setBookingDate(r.get(T_PERSON.CREATED)); | ||||
| 			bean.setAccept(r.get(T_PERSON.ACCEPT)); | ||||
| 			bean.setPaid(r.get(T_PERSON.PAID)); | ||||
| 			list.add(bean); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import java.math.BigDecimal; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.camp.ICampService; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Service | ||||
| public class CampService implements ICampService { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private CampGateway campGateway; | ||||
|  | ||||
| 	@Override | ||||
| 	public CampBean getCamp(Integer id, String username) { | ||||
| 		return campGateway.getCamp(id, username); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public BookingBean getBookings(Integer id, String username) { | ||||
| 		Integer approved = 0; | ||||
| 		Integer open = 0; | ||||
| 		Integer rejected = 0; | ||||
| 		BigDecimal paid = new BigDecimal(0); | ||||
| 		for (PersonBean p : campGateway.getBookings(id, username)) { | ||||
| 			Boolean acceptence = p.getAccept(); | ||||
| 			if (acceptence == null) { | ||||
| 				open += 1; | ||||
| 			} else if (acceptence) { | ||||
| 				approved +=1; | ||||
| 			} else { | ||||
| 				rejected +=1; | ||||
| 			} | ||||
| 			paid = paid.add(p.getPaid() == null ? new BigDecimal(0) : p.getPaid()); | ||||
| 		} | ||||
| 		BookingBean bean = new BookingBean(); | ||||
| 		bean.setApproved(approved); | ||||
| 		bean.setOpen(open); | ||||
| 		bean.setRejected(rejected); | ||||
| 		bean.setPaid(paid); | ||||
| 		return bean; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public List<PersonBean> getBookers(Integer id, String username) { | ||||
| 		return campGateway.getBookings(id, username); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,102 @@ | ||||
| package de.jottyfan.camporganizer.module.business.camp.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.math.BigDecimal; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class PersonBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 2L; | ||||
|  | ||||
| 	private Integer pk; | ||||
| 	private String name; | ||||
| 	private String role; | ||||
| 	private String sex; | ||||
| 	private Boolean accept; | ||||
| 	private LocalDateTime bookingDate; | ||||
| 	private BigDecimal paid; | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the accept | ||||
| 	 */ | ||||
| 	public Boolean getAccept() { | ||||
| 		return accept; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param accept the accept to set | ||||
| 	 */ | ||||
| 	public void setAccept(Boolean accept) { | ||||
| 		this.accept = accept; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the paid | ||||
| 	 */ | ||||
| 	public BigDecimal getPaid() { | ||||
| 		return paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param paid the paid to set | ||||
| 	 */ | ||||
| 	public void setPaid(BigDecimal paid) { | ||||
| 		this.paid = paid; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the pk | ||||
| 	 */ | ||||
| 	public Integer getPk() { | ||||
| 		return pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param pk the pk to set | ||||
| 	 */ | ||||
| 	public void setPk(Integer pk) { | ||||
| 		this.pk = pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the name | ||||
| 	 */ | ||||
| 	public String getName() { | ||||
| 		return name; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param name the name to set | ||||
| 	 */ | ||||
| 	public void setName(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
|  | ||||
| 	public String getRole() { | ||||
| 		return role; | ||||
| 	} | ||||
|  | ||||
| 	public void setRole(String role) { | ||||
| 		this.role = role; | ||||
| 	} | ||||
|  | ||||
| 	public String getSex() { | ||||
| 		return sex; | ||||
| 	} | ||||
|  | ||||
| 	public void setSex(String sex) { | ||||
| 		this.sex = sex; | ||||
| 	} | ||||
|  | ||||
| 	public LocalDateTime getBookingDate() { | ||||
| 		return bookingDate; | ||||
| 	} | ||||
|  | ||||
| 	public void setBookingDate(LocalDateTime bookingDate) { | ||||
| 		this.bookingDate = bookingDate; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.camp.impl.CampBean; | ||||
| import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesBean; | ||||
| import de.jottyfan.camporganizer.module.business.privileges.impl.ProfileBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public interface IPrivilegesService { | ||||
|  | ||||
| 	/** | ||||
| 	 * get all current privileges for the sales | ||||
| 	 * | ||||
| 	 * @return the privileges for sales | ||||
| 	 */ | ||||
| 	public Map<Integer, CampBean> getPrivileges(); | ||||
|  | ||||
| 	/** | ||||
| 	 * get all profiles | ||||
| 	 * | ||||
| 	 * @return the profiles | ||||
| 	 */ | ||||
| 	public List<ProfileBean> getProfiles(); | ||||
|  | ||||
| 	/** | ||||
| 	 * add a privilege | ||||
| 	 * | ||||
| 	 * @param bean the bean | ||||
| 	 */ | ||||
| 	public void add(PrivilegesBean bean); | ||||
|  | ||||
| 	/** | ||||
| 	 * remove a privilege | ||||
| 	 * | ||||
| 	 * @param bean the bean | ||||
| 	 * @param currentUser the current user in this sessionö | ||||
| 	 */ | ||||
| 	public void remove(PrivilegesBean bean, String currentUser); | ||||
| } | ||||
| @@ -0,0 +1,62 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges; | ||||
|  | ||||
| import javax.annotation.security.RolesAllowed; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.websocket.server.PathParam; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.ModelAttribute; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.business.IBusinessService; | ||||
| import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesBean; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author henkej | ||||
|  * | ||||
|  */ | ||||
| @Controller | ||||
| public class PrivilegesController { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private HttpServletRequest request; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IPrivilegesService privilegesService; | ||||
|  | ||||
| 	@Autowired | ||||
| 	private IBusinessService indexService; | ||||
|  | ||||
| 	@GetMapping("/business/privileges") | ||||
| 	@RolesAllowed({ "admin" }) | ||||
| 	public String getIndex(Model model) { | ||||
| 		String username = indexService.getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 		model.addAttribute("privileges", privilegesService.getPrivileges()); | ||||
| 		model.addAttribute("profiles", privilegesService.getProfiles()); | ||||
| 		model.addAttribute("bean", new PrivilegesBean()); | ||||
| 		return "business/privileges"; | ||||
| 	} | ||||
|  | ||||
| 	@PostMapping("/business/privileges/add") | ||||
| 	@RolesAllowed({ "admin" }) | ||||
| 	public String getAdd(@ModelAttribute PrivilegesBean bean, Model model) { | ||||
| 		privilegesService.add(bean); | ||||
| 		return getIndex(model); | ||||
| 	} | ||||
|  | ||||
| 	@GetMapping("/business/privileges/delete") | ||||
| 	@RolesAllowed({ "admin" }) | ||||
| 	public String getDelete(@PathParam(value = "fkCamp") Integer fkCamp, | ||||
| 			@PathParam(value = "fkProfile") Integer fkProfile, Model model) { | ||||
| 		PrivilegesBean bean = new PrivilegesBean(); | ||||
| 		bean.setFkCamp(fkCamp); | ||||
| 		bean.setFkProfile(fkProfile); | ||||
| 		privilegesService.remove(bean, indexService.getCurrentUser(request)); | ||||
| 		return getIndex(model); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,134 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class PrivilegesBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private String forename; | ||||
| 	private String surname; | ||||
| 	private String username; | ||||
| 	private LocalDateTime duedate; | ||||
| 	private Integer fkProfile; | ||||
| 	private Integer fkCamp; | ||||
| 	private String campName; | ||||
| 	private Double campYear; | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the forename | ||||
| 	 */ | ||||
| 	public String getForename() { | ||||
| 		return forename; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param forename the forename to set | ||||
| 	 */ | ||||
| 	public void setForename(String forename) { | ||||
| 		this.forename = forename; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the surname | ||||
| 	 */ | ||||
| 	public String getSurname() { | ||||
| 		return surname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param surname the surname to set | ||||
| 	 */ | ||||
| 	public void setSurname(String surname) { | ||||
| 		this.surname = surname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkProfile | ||||
| 	 */ | ||||
| 	public Integer getFkProfile() { | ||||
| 		return fkProfile; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkProfile the fkProfile to set | ||||
| 	 */ | ||||
| 	public void setFkProfile(Integer fkProfile) { | ||||
| 		this.fkProfile = fkProfile; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fkCamp | ||||
| 	 */ | ||||
| 	public Integer getFkCamp() { | ||||
| 		return fkCamp; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fkCamp the fkCamp to set | ||||
| 	 */ | ||||
| 	public void setFkCamp(Integer fkCamp) { | ||||
| 		this.fkCamp = fkCamp; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campName | ||||
| 	 */ | ||||
| 	public String getCampName() { | ||||
| 		return campName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param campName the campName to set | ||||
| 	 */ | ||||
| 	public void setCampName(String campName) { | ||||
| 		this.campName = campName; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the campYear | ||||
| 	 */ | ||||
| 	public Double getCampYear() { | ||||
| 		return campYear; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param campYear the campYear to set | ||||
| 	 */ | ||||
| 	public void setCampYear(Double campYear) { | ||||
| 		this.campYear = campYear; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the username | ||||
| 	 */ | ||||
| 	public String getUsername() { | ||||
| 		return username; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param username the username to set | ||||
| 	 */ | ||||
| 	public void setUsername(String username) { | ||||
| 		this.username = username; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the duedate | ||||
| 	 */ | ||||
| 	public LocalDateTime getDuedate() { | ||||
| 		return duedate; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param duedate the duedate to set | ||||
| 	 */ | ||||
| 	public void setDuedate(LocalDateTime duedate) { | ||||
| 		this.duedate = duedate; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,111 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges.impl; | ||||
|  | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.T_SALESPROFILE; | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; | ||||
|  | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.DeleteConditionStep; | ||||
| import org.jooq.InsertReturningStep; | ||||
| import org.jooq.Record5; | ||||
| import org.jooq.Record8; | ||||
| import org.jooq.SelectSeekStep3; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
|  | ||||
| import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Repository | ||||
| @Transactional(transactionManager = "transactionManager") | ||||
| public class PrivilegesGateway { | ||||
| 	private static final Logger LOGGER = LogManager.getLogger(PrivilegesGateway.class); | ||||
|  | ||||
| 	@Autowired | ||||
| 	private DSLContext jooq; | ||||
|  | ||||
| 	public List<PrivilegesBean> getPrivileges() { | ||||
| 		SelectSeekStep3<Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double>, LocalDateTime, String, String> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.select(T_PROFILE.FORENAME, T_PROFILE.SURNAME, T_PROFILE.DUEDATE, T_PROFILE.USERNAME, T_PROFILE.PK, V_CAMP.PK, V_CAMP.NAME, V_CAMP.YEAR) | ||||
| 			.from(V_CAMP) | ||||
| 			.leftJoin(T_SALESPROFILE).on(T_SALESPROFILE.FK_CAMP.eq(V_CAMP.PK)) | ||||
| 			.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_SALESPROFILE.FK_PROFILE)) | ||||
| 			.orderBy(V_CAMP.ARRIVE, T_PROFILE.SURNAME, T_PROFILE.FORENAME); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<PrivilegesBean> list = new ArrayList<>(); | ||||
| 		for (Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double> r : sql.fetch()) { | ||||
| 			PrivilegesBean bean = new PrivilegesBean(); | ||||
| 			bean.setCampName(r.get(V_CAMP.NAME)); | ||||
| 			bean.setCampYear(r.get(V_CAMP.YEAR)); | ||||
| 			bean.setFkCamp(r.get(V_CAMP.PK)); | ||||
| 			bean.setFkProfile(r.get(T_PROFILE.PK)); | ||||
| 			bean.setForename(r.get(T_PROFILE.FORENAME)); | ||||
| 			bean.setSurname(r.get(T_PROFILE.SURNAME)); | ||||
| 			bean.setUsername(r.get(T_PROFILE.USERNAME)); | ||||
| 			bean.setDuedate(r.get(T_PROFILE.DUEDATE)); | ||||
| 			list.add(bean); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	public List<ProfileBean> getProfiles() { | ||||
| 		SelectSeekStep3<Record5<Integer, String, String, LocalDateTime, String>, String, String, LocalDateTime> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.select(T_PROFILE.PK, T_PROFILE.FORENAME, T_PROFILE.SURNAME, T_PROFILE.DUEDATE, T_PROFILE.USERNAME) | ||||
| 			.from(T_PROFILE) | ||||
| 			.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME, T_PROFILE.DUEDATE); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		List<ProfileBean> list = new ArrayList<>(); | ||||
| 		for (Record5<Integer, String, String, LocalDateTime, String> r : sql.fetch()) { | ||||
| 			ProfileBean bean = new ProfileBean(); | ||||
| 			bean.setPk(r.get(T_PROFILE.PK)); | ||||
| 			bean.setForename(r.get(T_PROFILE.FORENAME)); | ||||
| 			bean.setSurname(r.get(T_PROFILE.SURNAME)); | ||||
| 			bean.setUsername(r.get(T_PROFILE.USERNAME)); | ||||
| 			bean.setDuedate(r.get(T_PROFILE.DUEDATE)); | ||||
| 			list.add(bean); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| 	public Integer add(PrivilegesBean bean) { | ||||
| 		InsertReturningStep<TSalesprofileRecord> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.insertInto(T_SALESPROFILE, T_SALESPROFILE.FK_CAMP, T_SALESPROFILE.FK_PROFILE) | ||||
| 			.values(bean.getFkCamp(), bean.getFkProfile()) | ||||
| 			.onConflict(T_SALESPROFILE.FK_CAMP, T_SALESPROFILE.FK_PROFILE) | ||||
| 			.doNothing(); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
|  | ||||
| 	public Integer remove(PrivilegesBean bean, String currentUser) { | ||||
| 		DeleteConditionStep<TSalesprofileRecord> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.deleteFrom(T_SALESPROFILE) | ||||
| 			.where(T_SALESPROFILE.FK_CAMP.eq(bean.getFkCamp())) | ||||
| 			.and(T_SALESPROFILE.FK_PROFILE.eq(bean.getFkProfile())) | ||||
| 			.and(T_SALESPROFILE.FK_PROFILE.notIn(jooq | ||||
| 				.select(T_PROFILE.PK) | ||||
| 				.from(T_PROFILE) | ||||
| 				.where(T_PROFILE.USERNAME.eq(currentUser)))); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.debug(sql.toString()); | ||||
| 		return sql.execute(); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,61 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges.impl; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import de.jottyfan.camporganizer.module.business.camp.impl.CampBean; | ||||
| import de.jottyfan.camporganizer.module.business.privileges.IPrivilegesService; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| @Service | ||||
| public class PrivilegesService implements IPrivilegesService { | ||||
| 	@Autowired | ||||
| 	private PrivilegesGateway gateway; | ||||
|  | ||||
| 	@Override | ||||
| 	public Map<Integer, CampBean> getPrivileges() { | ||||
| 		List<PrivilegesBean> list = gateway.getPrivileges(); | ||||
| 		Map<Integer, CampBean> camps = new HashMap<>(); | ||||
| 		for (PrivilegesBean bean : list) { | ||||
| 			CampBean campBean = camps.get(bean.getFkCamp()); | ||||
| 			if (campBean == null) { | ||||
| 				campBean = new CampBean(); | ||||
| 				camps.put(bean.getFkCamp(), campBean); | ||||
| 			} | ||||
| 			campBean.setPk(bean.getFkCamp()); | ||||
| 			campBean.setName(bean.getCampName()); | ||||
| 			campBean.setYear(bean.getCampYear()); | ||||
| 			ProfileBean profileBean = new ProfileBean(); | ||||
| 			profileBean.setPk(bean.getFkProfile()); | ||||
| 			profileBean.setForename(bean.getForename()); | ||||
| 			profileBean.setSurname(bean.getSurname()); | ||||
| 			profileBean.setUsername(bean.getUsername()); | ||||
| 			profileBean.setDuedate(bean.getDuedate()); | ||||
| 			campBean.getProfiles().add(profileBean); | ||||
| 		} | ||||
| 		return camps; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public List<ProfileBean> getProfiles() { | ||||
| 		return gateway.getProfiles(); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void add(PrivilegesBean bean) { | ||||
| 		gateway.add(bean); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void remove(PrivilegesBean bean, String currentUser) { | ||||
| 		gateway.remove(bean, currentUser); | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,113 @@ | ||||
| package de.jottyfan.camporganizer.module.business.privileges.impl; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDateTime; | ||||
| import java.time.format.DateTimeFormatter; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @author jotty | ||||
|  * | ||||
|  */ | ||||
| public class ProfileBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private Integer pk; | ||||
| 	private String forename; | ||||
| 	private String surname; | ||||
| 	private String username; | ||||
| 	private LocalDateTime duedate; | ||||
|  | ||||
| 	public String dropdown() { | ||||
| 		StringBuilder buf = new StringBuilder(); | ||||
| 		buf.append(forename).append(" "); | ||||
| 		buf.append(surname).append(" ("); | ||||
| 		buf.append(username).append(", "); | ||||
| 		buf.append(duedate == null ? "" : duedate.format(DateTimeFormatter.ofPattern("dd.MM.yyyy"))); | ||||
| 		buf.append(")"); | ||||
| 		return buf.toString(); | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		StringBuilder buf = new StringBuilder(); | ||||
| 		buf.append("{pk=").append(pk); | ||||
| 		buf.append(", forename=").append(forename); | ||||
| 		buf.append(", surname=").append(surname); | ||||
| 		buf.append(", username=").append(username); | ||||
| 		buf.append(", duedate=").append(duedate); | ||||
| 		buf.append("}"); | ||||
| 		return buf.toString(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the pk | ||||
| 	 */ | ||||
| 	public Integer getPk() { | ||||
| 		return pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param pk the pk to set | ||||
| 	 */ | ||||
| 	public void setPk(Integer pk) { | ||||
| 		this.pk = pk; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the forename | ||||
| 	 */ | ||||
| 	public String getForename() { | ||||
| 		return forename; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param forename the forename to set | ||||
| 	 */ | ||||
| 	public void setForename(String forename) { | ||||
| 		this.forename = forename; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the surname | ||||
| 	 */ | ||||
| 	public String getSurname() { | ||||
| 		return surname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param surname the surname to set | ||||
| 	 */ | ||||
| 	public void setSurname(String surname) { | ||||
| 		this.surname = surname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the username | ||||
| 	 */ | ||||
| 	public String getUsername() { | ||||
| 		return username; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param username the username to set | ||||
| 	 */ | ||||
| 	public void setUsername(String username) { | ||||
| 		this.username = username; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the duedate | ||||
| 	 */ | ||||
| 	public LocalDateTime getDuedate() { | ||||
| 		return duedate; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param duedate the duedate to set | ||||
| 	 */ | ||||
| 	public void setDuedate(LocalDateTime duedate) { | ||||
| 		this.duedate = duedate; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -2,7 +2,6 @@ package de.jottyfan.camporganizer.module.common; | ||||
|  | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
|  | ||||
| import org.jooq.exception.DataAccessException; | ||||
| import org.keycloak.KeycloakSecurityContext; | ||||
| import org.springframework.ui.Model; | ||||
|  | ||||
| @@ -27,11 +26,22 @@ public abstract class CommonController { | ||||
|  | ||||
| 	/** | ||||
| 	 * setup the session for the template | ||||
| 	 * @param model the model | ||||
| 	 * | ||||
| 	 * @param model   the model | ||||
| 	 * @param request the request | ||||
| 	 */ | ||||
| 	public void setupSession(Model model, HttpServletRequest request) { | ||||
| 		String username = getCurrentUser(request); | ||||
| 		model.addAttribute("currentUser", username); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * return true if the user has a valid keycloak session token | ||||
| 	 * | ||||
| 	 * @param request the request | ||||
| 	 * @return true or false | ||||
| 	 */ | ||||
| 	public boolean isLoggedIn(HttpServletRequest request) { | ||||
| 		return getCurrentUser(request) != null; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -29,19 +29,19 @@ public class IndexController extends CommonController { | ||||
| 	public String index(Model model) { | ||||
| 		super.setupSession(model, request); | ||||
| 		model.addAttribute("camps", service.getAllCamps()); | ||||
| 		return "/index"; | ||||
| 		return super.isLoggedIn(request) ? dashboard(model) : "/index"; | ||||
| 	} | ||||
|  | ||||
| 	@GetMapping("/user") | ||||
| 	public String user(Model model) { | ||||
| 	@GetMapping("/dashboard") | ||||
| 	public String dashboard(Model model) { | ||||
| 		super.setupSession(model, request); | ||||
| 		model.addAttribute("camps", service.getAllCamps()); | ||||
| 		return "/user/index"; | ||||
| 		return "/dashboard"; | ||||
| 	} | ||||
|  | ||||
| 	@GetMapping("/logout") | ||||
| 	public String getLogout(HttpServletRequest request) throws ServletException { | ||||
| 		request.logout(); | ||||
| 		LOGGER.debug("logout"); | ||||
| 		return "redirect:/"; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,10 +2,8 @@ package de.jottyfan.camporganizer.module.common; | ||||
|  | ||||
| import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP; | ||||
|  | ||||
| import java.sql.Timestamp; | ||||
| import java.time.LocalDateTime; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
|   | ||||
| @@ -77,7 +77,7 @@ body { | ||||
| 	background: transparent; | ||||
| 	border: 2px solid transparent; | ||||
| 	padding: 8px; | ||||
| 	color: silver; | ||||
| 	color: gray; | ||||
| } | ||||
|  | ||||
| .btn-icon-silent:hover { | ||||
|   | ||||
							
								
								
									
										77
									
								
								src/main/resources/templates/business/booker.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/main/resources/templates/business/booker.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer Business</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs> </libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="zur Hauptseite"><i class="fas fa-home"></i></a> | ||||
| 		<a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent" title="zur Finanzübersicht"><i class="far fa-money-bill-alt"></i></a> | ||||
| 		<a th:href="@{/business/bookings}" class="btn btn-secondary btn-icon-silent" title="Buchungsübersicht" sec:authorize="hasRole('business_booking')"><i class="fas fa-users"></i></a> | ||||
| 		<a th:href="@{'/business/bookings/' + ${booker.pk}}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<div class="container" style="max-width: 100%"> | ||||
| 			<div class="row"> | ||||
| 				<div class="col"> | ||||
| 					<div class="card" style="width: 480px" sec:authorize="hasRole('business_booking')"> | ||||
| 						<div class="card-header">Angemeldete Person</div> | ||||
| 						<div class="card-body"> | ||||
| 							<table class="table"> | ||||
| 								<tbody> | ||||
| 									<tr> | ||||
| 										<th>Name</th> | ||||
| 										<td th:text="${booker.name}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Geschlecht</th> | ||||
| 										<td th:text="${booker.sex}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Freizeit</th> | ||||
| 										<td th:text="${booker.camp}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Rolle</th> | ||||
| 										<td th:text="${booker.role}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Angemeldet</th> | ||||
| 										<td th:text="${#temporals.format(booker.bookingDate, 'dd.MM.yyyy')}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Bestätigt</th> | ||||
| 										<td th:text="${booker.accept == null ? '' : (booker.accept ? 'Ja' : 'abgelehnt')}"></td> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Preis</th> | ||||
| 										<td th:text="${booker.price}" /> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<th>Kontostand</th> | ||||
| 										<td><span th:text="${#strings.replace(#numbers.formatCurrency(booker.paid), '¤', '€')}" th:if="${booker.paid != null}"></span> | ||||
| 									</tr> | ||||
| 								</tbody> | ||||
| 							</table> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="col"> | ||||
| 					<div class="card" style="width: 480px" sec:authorize="hasRole('business_booking')"> | ||||
| 						<div class="card-header">Einzahlung</div> | ||||
| 						<div class="card-body"> | ||||
| 							<form action="#" th:action="@{'/business/bookings/payment/' + ${booker.pk}}" th:object="${addBean}" method="post"> | ||||
| 								<input type="number" step="0.01" th:field="*{payment}"> <input type="submit" style="padding: 4px" value="einzahlen"> | ||||
| 							</form> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										58
									
								
								src/main/resources/templates/business/bookings.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/main/resources/templates/business/bookings.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer Business</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs> </libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="zur Hauptseite"><i class="fas fa-home"></i></a> | ||||
| 		<a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent" title="zur Finanzübersicht"><i class="far fa-money-bill-alt"></i></a> | ||||
| 		<a th:href="@{/business/bookings}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<div class="card" sec:authorize="hasRole('business_booking')"> | ||||
| 			<div class="card-header">Angemeldete Personen</div> | ||||
| 			<div class="card-body"> | ||||
| 				<table id="bookers" class="table"> | ||||
| 					<thead> | ||||
| 						<tr> | ||||
| 							<th>Name</th> | ||||
| 							<th>Geschlecht</th> | ||||
| 							<th>Freizeit</th> | ||||
| 							<th>Rolle</th> | ||||
| 							<th>Kontostand</th> | ||||
| 							<th>Angemeldet</th> | ||||
| 							<th>Bestätigt</th> | ||||
| 						</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 						<th:block th:each="b : ${bookers}"> | ||||
| 							<tr> | ||||
| 								<td th:text="${b.name}"></td> | ||||
| 								<td th:text="${b.sex}"></td> | ||||
| 								<td th:text="${b.camp}"></td> | ||||
| 								<td th:text="${b.role}"></td> | ||||
| 								<td><span th:text="${#strings.replace(#numbers.formatCurrency(b.paid), '¤', '€')}"></span> <a class="btn btn-icon-silent" th:href="@{/business/bookings/{id}(id=${b.pk})}" | ||||
| 									title="bearbeiten"><i class="fas fa-edit"></i></a></td> | ||||
| 								<td th:text="${#temporals.format(b.bookingDate, 'dd.MM.yyyy')}"></td> | ||||
| 								<td th:text="${b.accept == null ? '' : (b.accept ? 'Ja' : 'abgelehnt')}"></td> | ||||
| 							</tr> | ||||
| 						</th:block> | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 				<script> | ||||
| 					$(document).ready(function() { | ||||
| 						$("#bookers").DataTable({ | ||||
| 							language : locale_de | ||||
| 						}); | ||||
| 					}); | ||||
| 				</script> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										43
									
								
								src/main/resources/templates/business/business.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/main/resources/templates/business/business.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer Business</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs></libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="zur Hauptseite"><i class="fas fa-home"></i></a> | ||||
| 		<a th:href="@{/business}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 		<a th:href="@{/business/bookings}" class="btn btn-secondary btn-icon-silent" title="zur Buchungsübersicht" sec:authorize="hasRole('business_booking')"><i class="fas fa-users"></i></a> | ||||
| 		<a th:href="@{/business/privileges}" class="btn btn-secondary btn-icon-silent" title="Nutzerverwaltung" sec:authorize="hasRole('admin')"><i class="fas fa-user-lock"></i></a> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<div class="card" style="width: 500px"> | ||||
| 			<div class="card-header">Finanzübersicht über alle Freizeiten</div> | ||||
| 			<div class="card-body"> | ||||
| 				<table class="table"> | ||||
| 					<thead> | ||||
| 						<tr> | ||||
| 							<th scope="col">Jahr</th> | ||||
| 							<th scope="col">Freizeit</th> | ||||
| 							<th scope="col">Kontostand</th> | ||||
| 						</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 						<th:block th:each="b : ${campBudgets}" sec:authorize="hasRole('business')"> | ||||
| 							<tr> | ||||
| 								<td th:text="${#numbers.formatDecimal(b.campYear, 1, 0)}"></td> | ||||
| 								<td><a th:href="@{/business/camp/{id}(id=${b.campId})}" th:text="${b.campName}" class="tablelink" title="Freizeitübersicht laden"></a></td> | ||||
| 								<td th:text="${#strings.replace(#numbers.formatCurrency(b.budget), '¤', '€')}"></td> | ||||
| 							</tr> | ||||
| 						</th:block> | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										105
									
								
								src/main/resources/templates/business/camp.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/main/resources/templates/business/camp.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer Business</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs> </libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="zur Hauptseite"><i class="fas fa-home"></i></a> | ||||
| 		<a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent" title="zur Finanzübersicht"><i class="far fa-money-bill-alt"></i></a> | ||||
| 		<a th:href="@{/business/camp/{id}(id=${campId})}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<div class="container" style="max-width: 100%"> | ||||
| 			<div class="row"> | ||||
| 				<div class="col"> | ||||
| 					<div class="card" style="width: 480px" th:if="${camp != null}"> | ||||
| 						<div class="card-header"> | ||||
| 							<span th:text="${camp.name}"></span> von <span th:text="${#numbers.formatInteger(camp.year, 0)}"></span> | ||||
| 						</div> | ||||
| 						<div class="card-body"> | ||||
| 							<table class="table"> | ||||
| 								<tbody> | ||||
| 									<tr> | ||||
| 										<td>Freizeitname</td> | ||||
| 										<th th:text="${camp.name}"></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>Zeit</td> | ||||
| 										<th><span th:text="${#temporals.format(camp.arrive, 'dd.MM.')}"></span> - <span th:text="${#temporals.format(camp.depart, 'dd.MM.yyyy')}"></span></th> | ||||
| 									<tr> | ||||
| 										<td>Ort</td> | ||||
| 										<th th:text="${camp.locationName}"></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>Preis</td> | ||||
| 										<th><pre th:utext="${camp.price}"></pre></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>bestätigt</td> | ||||
| 										<th th:text="${booking.approved}"></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>abgelehnt</td> | ||||
| 										<th th:text="${booking.rejected}"></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>offen</td> | ||||
| 										<th th:text="${booking.open}"></th> | ||||
| 									</tr> | ||||
| 									<tr> | ||||
| 										<td>Beiträge</td> | ||||
| 										<th th:text="${#strings.replace(#numbers.formatCurrency(booking.paid), '¤', '€')}"></th> | ||||
| 								</tbody> | ||||
| 							</table> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="col" sec:authorize="hasRole('business_booking')"> | ||||
| 					<div class="card"> | ||||
| 						<div class="card-header">Angemeldete Personen</div> | ||||
| 						<div class="card-body"> | ||||
| 							<table id="bookers" class="table"> | ||||
| 								<thead> | ||||
| 									<tr> | ||||
| 										<th>Name</th> | ||||
| 										<th>Geschlecht</th> | ||||
| 										<th>Rolle</th> | ||||
| 										<th>Kontostand</th> | ||||
| 										<th>Angemeldet</th> | ||||
| 										<th>Bestätigt</th> | ||||
| 									</tr> | ||||
| 								</thead> | ||||
| 								<tbody> | ||||
| 									<th:block th:each="b : ${bookers}"> | ||||
| 										<tr> | ||||
| 											<td th:text="${b.name}"></td> | ||||
| 											<td th:text="${b.sex}"></td> | ||||
| 											<td th:text="${b.role}"></td> | ||||
| 											<td th:text="${#strings.replace(#numbers.formatCurrency(b.paid), '¤', '€')}"></td> | ||||
| 											<td th:text="${#temporals.format(b.bookingDate, 'dd.MM.yyyy')}"></td> | ||||
| 											<td th:text="${b.accept == null ? '' : (b.accept ? 'Ja' : 'abgelehnt')}"></td> | ||||
| 										</tr> | ||||
| 									</th:block> | ||||
| 								</tbody> | ||||
| 							</table> | ||||
| 							<script> | ||||
| 								$(document).ready(function() { | ||||
| 									$("#bookers").DataTable({ | ||||
| 										language: locale_de | ||||
| 									}); | ||||
| 								}); | ||||
| 							</script> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="alert alert-danger" role="alert" th:if="${camp == null}">Es wurde keine Freizeit gefunden, die über diese ID angesprochen werden kann.</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										80
									
								
								src/main/resources/templates/business/privileges.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/main/resources/templates/business/privileges.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer Business</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs> | ||||
| </libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="zur Hauptseite"><i class="fas fa-home"></i></a> | ||||
| 		<a th:href="@{/business/}" class="btn btn-secondary btn-icon-silent" title="zur Finanzübersicht"><i class="far fa-money-bill-alt"></i></a> | ||||
| 		<a th:href="@{/business/privileges}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<div class="card"> | ||||
| 			<div class="card-header">Nutzerverwaltung für die Abrechnung von Freizeiten</div> | ||||
| 			<div class="card-body"> | ||||
| 				<table id="privs"> | ||||
| 					<thead> | ||||
| 						<tr> | ||||
| 							<th scope="col">Freizeit</th> | ||||
| 							<th scope="col">Abrechnung darf bearbeiten</th> | ||||
| 							<th scope="col"></th> | ||||
| 						</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 						<th:block th:each="e : ${privileges.entrySet()}" sec:authorize="hasRole('admin')"> | ||||
| 							<tr> | ||||
| 								<td><span th:text="${e.value.name}"></span> <span th:text="${#numbers.formatDecimal(e.value.year, 1, 0)}"></span></td> | ||||
| 								<td><th:block th:each="p : ${e.value.profiles}"> | ||||
| 										<div class="dropdown" style="display: inline" th:if="${p.pk != null}"> | ||||
| 											<button class="btn dropdown-toggle" style="border: 1px solid silver" type="button" th:id="'btn_' + ${e.key} + '_' + ${p.pk}" data-bs-toggle="dropdown" aria-expanded="false"> | ||||
| 												<span th:text="${p.forename} + ' ' + ${p.surname}"></span> | ||||
| 											</button> | ||||
| 											<ul class="dropdown-menu" style="background-image: linear-gradient(to bottom right, #defac0, #9ef542) !important;" th:aria-labelledby="'btn_' + ${e.key} + '_' + ${p.pk}"> | ||||
| 												<li><div style="padding: 8px"> | ||||
| 														Login: <span th:text="${p.username}"></span> | ||||
| 													</div></li> | ||||
| 												<li><div style="padding: 8px"> | ||||
| 														Ablaufdatum: <span th:text="${#temporals.format(p.duedate, 'dd.MM.yyyy')}"></span> | ||||
| 													</div></li> | ||||
| 												<li><hr class="dropdown-divider" th:if="${p.username != currentUser}"></li> | ||||
| 												<li><a class="dropdown-item" th:if="${p.username != currentUser}" th:href="@{/business/privileges/delete?fkCamp={c}&fkProfile={r}(c=${e.key},r=${p.pk})}">Recht entziehen</a></li> | ||||
| 											</ul> | ||||
| 										</div> | ||||
| 									</th:block></td> | ||||
| 								<td> | ||||
| 									<form action="#" th:action="@{/business/privileges/add?fkCamp={cid}(cid=${e.key})}" th:object="${bean}" method="post"> | ||||
| 										<span class="btn-group"> <select th:id="${e.value.pk}" class="form-control select2-single" th:field="*{fkProfile}"> | ||||
| 												<option value="">Auswählen</option> | ||||
| 												<th:block th:each="u : ${profiles}"> | ||||
| 													<option th:if="${u != null}" th:value="${u.pk}" th:text="${u.dropdown()}" /> | ||||
| 												</th:block> | ||||
| 										</select> <input type="submit" style="padding: 4px" value="Recht erteilen"> | ||||
| 										</span> | ||||
| 										<script> | ||||
| 											var id = "[[${e.value.pk}]]"; | ||||
| 											$("#" + id).select2(); | ||||
| 										</script> | ||||
| 									</form> | ||||
| 								</td> | ||||
| 							</tr> | ||||
| 						</th:block> | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 				<script> | ||||
| 					$(document).ready(function() { | ||||
| 						$("#privs").DataTable({ | ||||
| 							language: locale_de | ||||
| 						}); | ||||
| 					}); | ||||
| 				</script> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										19
									
								
								src/main/resources/templates/dashboard.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main/resources/templates/dashboard.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer 2</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs></libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 		<a th:href="@{/business}" class="btn btn-secondary btn-icon-silent" title="Abrechnungen"><i class="far fa-money-bill-alt"></i></a> | ||||
| 		<span>Das Buchungsportal dess Onkel Werner Freizeiten e.V.</span> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
| @@ -23,7 +23,7 @@ | ||||
| 				<b th:inline="text">[[${currentUser}]]</b> aus Version <span th:text="${@manifestBean.getVersion()}"></span> <a th:href="@{/logout}">ausloggen</a> | ||||
| 			</span> | ||||
| 			<span th:if="${#strings.isEmpty(currentUser)}"> | ||||
| 				<a th:href="@{/user}">einloggen</a> | ||||
| 				<a th:href="@{/dashboard}">einloggen</a> | ||||
| 			</span> | ||||
| 		</div> | ||||
| 		<span th:replace="${header}">Layout header</span> | ||||
|   | ||||
| @@ -1,61 +0,0 @@ | ||||
| <!DOCTYPE html> | ||||
| <html th:replace="~{template :: layout(~{::title}, ~{::libs}, ~{::header}, ~{::content})}" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer 2</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <libs></libs> | ||||
| </head> | ||||
| <body> | ||||
| 	<header> | ||||
| 		<a th:href="@{/}" class="btn btn-secondary btn-icon-silent" title="aktualisieren"><i class="fas fa-sync"></i></a> | ||||
| 		<span>Das Buchungsportal dess Onkel Werner Freizeiten e.V.</span> | ||||
| 	</header> | ||||
| 	<content> | ||||
| 	<div class="mainpage"> | ||||
| 		<script type="text/javascript"> | ||||
| 			var mytoggle = new MyToggle(); | ||||
| 		</script> | ||||
| 		<h1>Unsere Freizeiten</h1> | ||||
| 		<div class="card bottomdist16" th:each="c : ${camps}"> | ||||
| 			<div class="card-header mytoggle_btn" th:onclick="mytoggle.toggle('campdiv_[[${c.pk}]]')"> | ||||
| 				<span th:text="${c.name}"></span> <span th:text="${#numbers.formatInteger(c.year, 0)}" th:if="${c.year != null}"></span> | ||||
| 			</div> | ||||
| 			<div th:id="'campdiv_' + ${c.pk}" class="card-body mytoggle_collapsed"> | ||||
| 				<div class="container"> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3">Ort</div> | ||||
| 						<div class="col-sm-9"> | ||||
| 							<a th:href="${c.url}" th:text="${c.locationName}" target="_blank"></a> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3">Jungen und Mädchen</div> | ||||
| 						<div class="col-sm-9" th:text="${c.minAge} + ' - ' + ${c.maxAge}"></div> | ||||
| 					</div> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3">Zeit</div> | ||||
| 						<div class="col-sm-9"> | ||||
| 							<span th:text="${#temporals.format(c.arrive, 'dd.MM.')} + ' - ' + ${#temporals.format(c.depart, 'dd.MM.yyyy')}" th:if="${c.arrive != null &&  c.depart != null}"></span> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3">Preis</div> | ||||
| 						<div class="col-sm-9" th:text="${c.price}"></div> | ||||
| 					</div> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3">Ferien</div> | ||||
| 						<div class="col-sm-9" th:text="${c.countries}"></div> | ||||
| 					</div> | ||||
| 					<div class="row"> | ||||
| 						<div class="col-sm-3"></div> | ||||
| 						<div class="col-sm-9"> | ||||
| 							<button class="btn btn-primary">jetzt anmelden</button> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</content> | ||||
| </body> | ||||
| </html> | ||||
		Reference in New Issue
	
	Block a user