diff --git a/.classpath b/.classpath index f3bdce0..607b789 100644 --- a/.classpath +++ b/.classpath @@ -12,6 +12,13 @@ + + + + + + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs index e479558..e889521 100644 --- a/.settings/org.eclipse.buildship.core.prefs +++ b/.settings/org.eclipse.buildship.core.prefs @@ -1,13 +1,2 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 -gradle.user.home= -java.home= -jvm.arguments= -offline.mode=false -override.workspace.settings=false -show.console.view=false -show.executions.view=false diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index a2ed0c0..31a62d0 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,8 +1,14 @@ - - - - - - - + + + + + + + + + + + + + diff --git a/src/main/java/de/jottyfan/camporganizer/config/SecurityConfig.java b/src/main/java/de/jottyfan/camporganizer/config/SecurityConfig.java index 4004168..2dad836 100644 --- a/src/main/java/de/jottyfan/camporganizer/config/SecurityConfig.java +++ b/src/main/java/de/jottyfan/camporganizer/config/SecurityConfig.java @@ -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(); diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/BookingsController.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/BookingsController.java new file mode 100644 index 0000000..a34d1c4 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/BookingsController.java @@ -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); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/IBookingsService.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/IBookingsService.java new file mode 100644 index 0000000..fae57e0 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/IBookingsService.java @@ -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 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); +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/AddPaymentBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/AddPaymentBean.java new file mode 100644 index 0000000..02d5de3 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/AddPaymentBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookerBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookerBean.java new file mode 100644 index 0000000..f185138 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookerBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsGateway.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsGateway.java new file mode 100644 index 0000000..ef61de0 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsGateway.java @@ -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 getBookings(String username) { + SelectSeekStep4, 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 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> 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 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(); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsService.java b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsService.java new file mode 100644 index 0000000..c5ae3d4 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/bookings/impl/BookingsService.java @@ -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 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); + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/BusinessController.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/BusinessController.java new file mode 100644 index 0000000..c388b35 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/BusinessController.java @@ -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"; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/IBusinessService.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/IBusinessService.java new file mode 100644 index 0000000..f611bfa --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/IBusinessService.java @@ -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 getCampBudgets(String username); +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessBean.java new file mode 100644 index 0000000..5e8f367 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessGateway.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessGateway.java new file mode 100644 index 0000000..cf57553 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessGateway.java @@ -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 getCampBudgets(String username) { + SelectSeekStep1, 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 list = new ArrayList<>(); + for (Record4 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 getAllRegistrations(String username) { + SelectConditionStep> 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 list = new ArrayList<>(); + for (Record8 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 list) { + Integer count = 0; + for (BusinessBean bean : list) { + if (bean.isChanged()) { + UpdateConditionStep 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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessService.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessService.java new file mode 100644 index 0000000..eaae3f4 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/BusinessService.java @@ -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 getCampBudgets(String username) { + return gateway.getCampBudgets(username); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/CampBudgetBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/CampBudgetBean.java new file mode 100644 index 0000000..d1f41a3 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/business/impl/CampBudgetBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/CampController.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/CampController.java new file mode 100644 index 0000000..8d17af2 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/CampController.java @@ -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"; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/ICampService.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/ICampService.java new file mode 100644 index 0000000..57b1f12 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/ICampService.java @@ -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 getBookers(Integer id, String username); + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookerBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookerBean.java new file mode 100644 index 0000000..1ce624a --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookerBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookingBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookingBean.java new file mode 100644 index 0000000..0d2bda3 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/BookingBean.java @@ -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; + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampBean.java new file mode 100644 index 0000000..c7ee468 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampBean.java @@ -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 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 getProfiles() { + return profiles; + } + + public Integer getPk() { + return pk; + } + + public void setPk(Integer pk) { + this.pk = pk; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampGateway.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampGateway.java new file mode 100644 index 0000000..92b53cf --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampGateway.java @@ -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> 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 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 getBookings(Integer pk, String username) { + SelectSeekStep4, 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 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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampService.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampService.java new file mode 100644 index 0000000..5932011 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/CampService.java @@ -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 getBookers(Integer id, String username) { + return campGateway.getBookings(id, username); + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/PersonBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/PersonBean.java new file mode 100644 index 0000000..acbdde9 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/camp/impl/PersonBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/IPrivilegesService.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/IPrivilegesService.java new file mode 100644 index 0000000..d0f27b2 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/IPrivilegesService.java @@ -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 getPrivileges(); + + /** + * get all profiles + * + * @return the profiles + */ + public List 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); +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/PrivilegesController.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/PrivilegesController.java new file mode 100644 index 0000000..cfd2672 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/PrivilegesController.java @@ -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); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesBean.java new file mode 100644 index 0000000..63393e8 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesBean.java @@ -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; + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesGateway.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesGateway.java new file mode 100644 index 0000000..5b401aa --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesGateway.java @@ -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 getPrivileges() { + SelectSeekStep3, 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 list = new ArrayList<>(); + for (Record8 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 getProfiles() { + SelectSeekStep3, 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 list = new ArrayList<>(); + for (Record5 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 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 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(); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesService.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesService.java new file mode 100644 index 0000000..6046798 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/PrivilegesService.java @@ -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 getPrivileges() { + List list = gateway.getPrivileges(); + Map 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 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); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/ProfileBean.java b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/ProfileBean.java new file mode 100644 index 0000000..4955726 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/business/privileges/impl/ProfileBean.java @@ -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; + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/common/CommonController.java b/src/main/java/de/jottyfan/camporganizer/module/common/CommonController.java index a6c4be8..e55edf7 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/common/CommonController.java +++ b/src/main/java/de/jottyfan/camporganizer/module/common/CommonController.java @@ -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; + } } diff --git a/src/main/java/de/jottyfan/camporganizer/module/common/IndexController.java b/src/main/java/de/jottyfan/camporganizer/module/common/IndexController.java index d87a6f3..0e0aae2 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/common/IndexController.java +++ b/src/main/java/de/jottyfan/camporganizer/module/common/IndexController.java @@ -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:/"; } } diff --git a/src/main/java/de/jottyfan/camporganizer/module/common/IndexService.java b/src/main/java/de/jottyfan/camporganizer/module/common/IndexService.java index 4872b79..6854a61 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/common/IndexService.java +++ b/src/main/java/de/jottyfan/camporganizer/module/common/IndexService.java @@ -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; diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index e6fa006..a682909 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -77,7 +77,7 @@ body { background: transparent; border: 2px solid transparent; padding: 8px; - color: silver; + color: gray; } .btn-icon-silent:hover { diff --git a/src/main/resources/templates/business/booker.html b/src/main/resources/templates/business/booker.html new file mode 100644 index 0000000..ae37429 --- /dev/null +++ b/src/main/resources/templates/business/booker.html @@ -0,0 +1,77 @@ + + + +Camp Organizer Business + + + + +
+ + + + +
+ +
+
+
+
+
+
Angemeldete Person
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Geschlecht
Freizeit
Rolle
Angemeldet
Bestätigt
Preis +
Kontostand +
+
+
+
+
+
+
Einzahlung
+
+
+ +
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/business/bookings.html b/src/main/resources/templates/business/bookings.html new file mode 100644 index 0000000..130fed4 --- /dev/null +++ b/src/main/resources/templates/business/bookings.html @@ -0,0 +1,58 @@ + + + +Camp Organizer Business + + + + +
+ + + +
+ +
+
+
Angemeldete Personen
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
NameGeschlechtFreizeitRolleKontostandAngemeldetBestätigt
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/business/business.html b/src/main/resources/templates/business/business.html new file mode 100644 index 0000000..80fe54e --- /dev/null +++ b/src/main/resources/templates/business/business.html @@ -0,0 +1,43 @@ + + + +Camp Organizer Business + + + + +
+ + + + +
+ +
+
+
Finanzübersicht über alle Freizeiten
+
+ + + + + + + + + + + + + + + + + +
JahrFreizeitKontostand
+
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/business/camp.html b/src/main/resources/templates/business/camp.html new file mode 100644 index 0000000..43a0522 --- /dev/null +++ b/src/main/resources/templates/business/camp.html @@ -0,0 +1,105 @@ + + + +Camp Organizer Business + + + + +
+ + + +
+ +
+
+
+
+
+
+ von +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Freizeitname
Zeit -
Ort
Preis
bestätigt
abgelehnt
offen
Beiträge
+
+
+
+
+
+
Angemeldete Personen
+
+ + + + + + + + + + + + + + + + + + + + + + + +
NameGeschlechtRolleKontostandAngemeldetBestätigt
+ +
+
+
+
+
+ +
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/business/privileges.html b/src/main/resources/templates/business/privileges.html new file mode 100644 index 0000000..108f695 --- /dev/null +++ b/src/main/resources/templates/business/privileges.html @@ -0,0 +1,80 @@ + + + +Camp Organizer Business + + + + + +
+ + + +
+ +
+
+
Nutzerverwaltung für die Abrechnung von Freizeiten
+
+ + + + + + + + + + + + + + + + + +
FreizeitAbrechnung darf bearbeiten
  + + +
+ + + +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html new file mode 100644 index 0000000..7f848a3 --- /dev/null +++ b/src/main/resources/templates/dashboard.html @@ -0,0 +1,19 @@ + + + +Camp Organizer 2 + + + + +
+ + + Das Buchungsportal dess Onkel Werner Freizeiten e.V. +
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/template.html b/src/main/resources/templates/template.html index 46a6c1d..f702cf1 100644 --- a/src/main/resources/templates/template.html +++ b/src/main/resources/templates/template.html @@ -23,7 +23,7 @@ [[${currentUser}]] aus Version ausloggen - einloggen + einloggen Layout header diff --git a/src/main/resources/templates/user/index.html b/src/main/resources/templates/user/index.html deleted file mode 100644 index 6d3f21c..0000000 --- a/src/main/resources/templates/user/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -Camp Organizer 2 - - - - -
- - Das Buchungsportal dess Onkel Werner Freizeiten e.V. -
- -
- -

Unsere Freizeiten

-
-
-   -
-
-
-
-
Ort
-
- -
-
-
-
Jungen und Mädchen
-
-
-
-
Zeit
-
- -
-
-
-
Preis
-
-
-
-
Ferien
-
-
-
-
-
- -
-
-
-
-
-
-
- - \ No newline at end of file