65 Commits

Author SHA1 Message Date
27c1669ed3 make scrolling work again 2025-06-07 19:42:49 +02:00
3bb68aff1f last finetuning 2025-06-07 18:45:01 +02:00
4c32a12d2d slide of thumbnails experiments 2025-05-31 10:25:38 +02:00
485a222be4 stock images description properties file 2025-05-29 17:53:18 +02:00
82ce501f39 start page final changes 2025-05-29 16:51:55 +02:00
d3389e4813 more welcome page gimmicks 2025-05-13 23:06:17 +02:00
bdfe54a148 some progress on landing page 2025-05-05 22:17:02 +02:00
1d67aefa4d redesign of the landing page, see #20 2025-04-05 17:48:18 +02:00
a801d3178a changed menu, see #19 2025-04-03 22:45:26 +02:00
15a4388490 transition on logo hover 2025-03-30 22:25:47 +02:00
5a891c085d login icon hover effect 2025-03-27 22:29:39 +01:00
8cf1857c24 logo as button, see #18 2025-03-27 22:14:47 +01:00
890d46dcdd added image of lars 2025-03-24 21:45:40 +01:00
b26b014225 added lars 2025-03-23 22:44:35 +01:00
2b2246f2de start booking with time now 2025-03-23 22:32:26 +01:00
92970d8c63 src/main/resources/templates/fragments/camplist.html aktualisiert
added registration start time info
2025-03-23 08:21:24 +01:00
be4b75eef4 merged progress 2024-11-30 17:35:31 +01:00
31727e23ac removed ok button on revoked, see #9 2024-11-30 17:33:50 +01:00
2abb937725 confirmation accepts deletion of revoked registrations 2024-10-26 16:44:26 +02:00
b5403ae20c still buggy on rejecting people and loading old bookings 2024-10-23 22:42:15 +02:00
ae9e2018a8 download of outlays 2024-10-12 23:19:17 +02:00
32ef8a67d9 added outlay 2024-08-19 17:23:41 +02:00
b10765fe89 fixed registration bugs 2024-05-28 23:24:45 +02:00
8522def65c added new main site with currently buggy layout 2024-05-28 18:29:26 +02:00
81d6f79857 added Linda 2024-05-28 17:51:27 +02:00
fbfccd0dfc added text anna 2024-05-28 17:15:32 +02:00
0e57c57ccc forbid spaces in login field, see #16 2024-05-04 14:09:35 +02:00
f0d30ec6ed fixed registration failure checks 2024-04-01 18:04:42 +02:00
7ab500e510 fixed correction of registrations 2024-04-01 15:33:03 +02:00
a373f5e758 finetuning 2024-03-18 19:45:46 +01:00
f577164781 added image of simeon 2024-03-18 19:39:56 +01:00
03eb781a98 added start_booking, see #14 2024-03-16 22:40:36 +01:00
ce819f80de finetuning 2024-03-14 09:28:36 +01:00
1c226caa48 added image of Jörg 2024-03-14 09:25:05 +01:00
1580369794 added about of Jörg 2024-03-14 09:15:47 +01:00
39805aec20 added Simeon about text 2024-03-14 09:02:51 +01:00
0eb90092e7 finetuning 2024-02-24 17:45:50 +01:00
fe8100c59e removed false corrections 2024-02-23 15:38:21 +01:00
e20c24d006 added required price, see #6 2024-02-23 15:36:37 +01:00
72952b9c7b finetuning in layout 2024-02-23 11:50:33 +01:00
8f69320505 show free beds, see #2 2024-02-23 01:24:53 +01:00
5a365b1a37 code cleanup 2024-02-10 11:50:37 +01:00
1d14a13aa6 code cleanup 2023-12-27 13:57:57 +01:00
8e790a7660 corrected privileges, see #11 2023-12-27 11:01:46 +01:00
0d476c6f91 hotfix: corrected consent url 2023-10-26 11:01:59 +02:00
11abda3575 register already known persons 2023-10-25 10:15:23 +02:00
453105419f register already known persons 2023-10-25 10:14:26 +02:00
d4ae63f975 german decimal separator forced 2023-10-21 21:51:26 +02:00
3dd39751af export optimization 2023-10-21 21:46:22 +02:00
e0e972cfe8 added download csv file feature 2023-10-21 18:53:14 +02:00
b3a089d6b3 corrected ant matchers 2023-10-21 13:37:59 +02:00
3147007632 display camplists 2023-10-21 01:24:52 +02:00
5f78b87a87 corrected password url 2023-10-07 11:12:21 +02:00
5f6d71890e corrected link url 2023-10-07 10:56:42 +02:00
f21c7584bd added year to selection of camp in role management 2023-09-28 21:41:37 +02:00
12a325ee03 corrected username check and dropdown size, see #57 2023-09-21 21:32:18 +02:00
497a4dfcf9 registration screen optimized, see #58 2023-09-21 19:54:23 +02:00
f31c433c80 bugfix: allow spaces after user names on login from old registrations 2023-08-27 21:58:40 +02:00
7732d6da25 corrected keycloak urls 2023-08-06 16:05:18 +02:00
b07de9f2bc determine mail correctly 2023-08-06 15:43:44 +02:00
e8354c3f6e jakartarized 2023-08-06 00:10:01 +02:00
4a2d743a23 version display improved 2023-07-29 17:48:41 +02:00
89cfbc6741 see #48 2023-05-13 12:29:25 +02:00
5b861f730f added filter to privilege dropdowns 2023-05-06 20:39:34 +02:00
d1ee923f0a see #45 2023-05-06 17:44:14 +02:00
167 changed files with 5361 additions and 1600 deletions

View File

@ -6,13 +6,6 @@
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>camporganizer2</name>
<name>CampOrganizer2</name>
<comment></comment>
<projects>
</projects>
@ -25,6 +25,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>

View File

@ -1,2 +1,13 @@
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

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@ -1,25 +1,20 @@
buildscript {
ext {
springBootVersion = '2.7.4'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
plugins {
id 'org.springframework.boot' version '3.3.4'
id "io.spring.dependency-management" version "1.1.4"
id 'java'
id 'war'
id 'eclipse'
id 'application'
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'
apply plugin: 'application'
group = 'de.jottyfan.camporganizer'
version = '0.5.0'
version = '0.9.7'
description = """CampOrganizer2"""
sourceCompatibility = 17
targetCompatibility = 17
mainClassName = "de.jottyfan.camporganizer.Main"
repositories {
@ -27,64 +22,78 @@ repositories {
maven {
url "https://www.jottyfan.de/libs/"
}
}
ext {
set('keycloakVersion', '21.1.1')
maven {
url "https://repo.maven.apache.org/maven2"
}
}
war {
doFirst {
manifest {
attributes("Implementation-Version": version)
attributes("Implementation-Title": project.name,
"Implementation-Version": version,
"Implementation-Timestamp": new Date())
}
archiveName = 'CampOrganizer2.war'
}
version = version
archiveFileName = 'CampOrganizer2.war'
}
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.20.0'
implementation 'org.jooq:jooq:3.19.14'
implementation 'de.jottyfan:COJooq:2024.10.24'
implementation 'org.webjars:bootstrap:5.2.3'
implementation 'org.webjars:font-awesome:5.15.4'
implementation 'org.webjars:jquery:3.6.4'
implementation 'org.webjars:popper.js:2.9.3'
implementation 'org.webjars:datatables:1.13.2'
implementation 'org.apache.logging.log4j:log4j-api:2.24.1'
implementation 'org.apache.logging.log4j:log4j-core:2.24.1'
implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.24.1'
implementation 'org.webjars:bootstrap:5.3.3'
implementation 'org.webjars:font-awesome:6.5.2'
implementation 'org.webjars:jquery:3.7.1'
implementation 'org.webjars:popper.js:2.11.7'
implementation 'org.webjars:datatables:1.13.5'
implementation 'org.webjars:select2:4.0.13'
implementation 'org.webjars.npm:fancyapps__fancybox:3.5.7'
implementation 'net.sf.biweekly:biweekly:0.6.6'
implementation 'org.keycloak:keycloak-spring-boot-starter'
implementation 'net.sf.biweekly:biweekly:0.6.7'
// for using the keycloak rest interface
implementation 'org.keycloak:keycloak-admin-client:21.1.1'
implementation 'org.jboss.resteasy:resteasy-client:5.0.0.Final'
implementation 'org.keycloak:keycloak-server-spi:24.0.1'
implementation 'org.keycloak:keycloak-admin-client:24.0.1'
implementation 'org.jboss.resteasy:resteasy-client:6.2.6.Final'
// backward compatibility until the complete registration is converted to keycloak
implementation 'org.jasypt:jasypt:1.9.3'
// rss support
implementation 'com.rometools:rome:1.18.0'
implementation 'com.rometools:rome:2.1.0'
// mail support
implementation 'commons-validator:commons-validator:1.7'
implementation 'commons-validator:commons-validator:1.8.0'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-jooq'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation "org.springframework.boot:spring-boot-starter-oauth2-client"
implementation 'org.springframework.security:spring-security-oauth2-authorization-server:1.3.3'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
implementation 'de.jottyfan:COJooq:2023.03'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.0.0'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.4.0'
implementation 'commons-io:commons-io:2.15.1'
runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
dependencyManagement {
imports {
mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keycloakVersion}"
}
test {
useJUnitPlatform()
}
// add version to manifest
springBoot {
buildInfo()
}

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

55
gradlew vendored
View File

@ -1,21 +1,5 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@ -44,7 +28,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@ -72,7 +56,7 @@ case "`uname`" in
Darwin* )
darwin=true
;;
MSYS* | MINGW* )
MINGW* )
msys=true
;;
NONSTOP* )
@ -82,7 +66,6 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -126,11 +109,10 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@ -156,19 +138,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
i=$((i+1))
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@ -177,9 +159,14 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
rootProject.name = 'CampOrganizer2'

View File

@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class Main extends SpringBootServletInitializer {
private static final Logger LOGGER = LogManager.getLogger(Main.class);
public static final Logger LOGGER = LogManager.getLogger(Main.class);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
@ -31,7 +31,7 @@ public class Main extends SpringBootServletInitializer {
Path path = Paths.get("");
String p = path.toAbsolutePath().toString();
p = p.substring(p.lastIndexOf("/") + 1);
LOGGER.info("running in {}", p);
LOGGER.debug("running in {}", p);
// TODO: put p + "properties" somehow into consideration to load the application.properties
SpringApplication.run(Main.class, args);
}

View File

@ -0,0 +1,78 @@
package de.jottyfan.camporganizer.config;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
/**
*
* @author jotty
*
*/
@Configuration
public class AuthorizationConfiguration {
private static final String REALM_ACCESS_CLAIM = "realm_access";
private static final String ROLES_CLAIM = "roles";
private static final String RESOURCE_ACCESS_CLAIM = "resource_access";
@Value("${spring.security.oauth2.client.registration.keycloak.client-id}")
private String clientId;
@Bean
GrantedAuthoritiesMapper userAuthoritiesMapperForKeycloak() {
return authorities -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
var authority = authorities.iterator().next();
boolean isOidc = authority instanceof OidcUserAuthority;
if (isOidc) {
var oidcUserAuthority = (OidcUserAuthority) authority;
var userInfo = oidcUserAuthority.getUserInfo();
if (userInfo.hasClaim(REALM_ACCESS_CLAIM)) {
var realmAccess = userInfo.getClaimAsMap(REALM_ACCESS_CLAIM);
@SuppressWarnings("unchecked")
var roles = (Collection<String>) realmAccess.get(ROLES_CLAIM);
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
}
if (userInfo.hasClaim(RESOURCE_ACCESS_CLAIM)) {
var resourceAccess = userInfo.getClaimAsMap(RESOURCE_ACCESS_CLAIM);
if (resourceAccess.containsKey(clientId)) {
@SuppressWarnings("unchecked")
var roles = (Collection<String>) ((Map<?, ?>) resourceAccess.get(clientId)).get(ROLES_CLAIM);
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
}
}
} else {
var oauth2UserAuthority = (OAuth2UserAuthority) authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
if (userAttributes.containsKey(REALM_ACCESS_CLAIM)) {
@SuppressWarnings("unchecked")
var realmAccess = (Map<String, Object>) userAttributes.get(REALM_ACCESS_CLAIM);
@SuppressWarnings("unchecked")
var roles = (Collection<String>) realmAccess.get(ROLES_CLAIM);
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
}
}
return mappedAuthorities;
};
}
private Collection<GrantedAuthority> generateAuthoritiesFromClaim(Collection<String> roles) {
return roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toList());
}
}

View File

@ -1,66 +0,0 @@
package de.jottyfan.camporganizer.config;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
/**
*
* @author jotty
*
*/
@KeycloakConfiguration
@ComponentScan(basePackageClasses = KeycloakSpringBootConfigResolver.class)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
@ConditionalOnMissingBean(HttpSessionManager.class)
protected HttpSessionManager httpSessionManager() {
return new HttpSessionManager();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
// @formatter:off
.antMatchers("/dashboard/**", "/business/**", "/confirmation/**").authenticated()
.anyRequest().permitAll();
// @formatter:on
// http.anonymous().disable();
http.csrf().disable();
}
}

View File

@ -0,0 +1,50 @@
package de.jottyfan.camporganizer.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
/**
*
* @author jotty
*
*/
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfiguration {
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity sec, InMemoryClientRegistrationRepository crr)
throws Exception {
sec.csrf(o -> o.disable()).anonymous(o -> o.disable())
// @formatter:off
.oauth2Login(o -> o.defaultSuccessUrl("/"))
.logout(o -> o.logoutSuccessHandler(new OidcClientInitiatedLogoutSuccessHandler(crr)))
.authorizeHttpRequests(o -> o.requestMatchers(
AntPathRequestMatcher.antMatcher("/dashboard/**"),
AntPathRequestMatcher.antMatcher("/business/**"),
AntPathRequestMatcher.antMatcher("/confirmation/**"),
AntPathRequestMatcher.antMatcher("/userlogin/**")
).authenticated()
.anyRequest().permitAll())
.oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
.sessionManagement(o -> o.init(sec));
// @formatter:on
return sec.build();
}
}

View File

@ -1,7 +1,6 @@
package de.jottyfan.camporganizer.module.admin;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.security.Principal;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -17,8 +16,13 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import de.jottyfan.camporganizer.module.mail.MailBean;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
/**
*
@ -37,10 +41,10 @@ public class AdminController extends CommonController {
private String from;
@GetMapping("/admin/mail")
public String getMail(Model model, HttpServletRequest request) {
public String getMail(Model model, Principal principal) {
MailBean mailBean = new MailBean();
mailBean.setFrom(from);
mailBean.getTo().add(getCurrentEmail(request));
mailBean.getTo().add(getCurrentEmail(principal));
model.addAttribute("bean", mailBean);
return "/admin/mail";
}
@ -70,7 +74,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/document/edit/{id}")
public String prepareAddDocument(@PathVariable Integer id, Model model, HttpServletRequest request) {
public String prepareAddDocument(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
model.addAttribute("bean", service.getDocument(id));
return "/admin/document_edit";
}
@ -88,7 +92,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/document/delete/{id}")
public String deleteDocument(@PathVariable Integer id, Model model, HttpServletRequest request) {
public String deleteDocument(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
service.deleteDocument(id);
return "redirect:/admin/document";
}
@ -107,7 +111,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/location/edit/{id}")
public String prepareAddLocation(@PathVariable Integer id, Model model, HttpServletRequest request) {
public String prepareAddLocation(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
model.addAttribute("bean", service.getLocation(id));
model.addAttribute("documents", service.getLocationDocuments());
return "/admin/location_edit";
@ -128,7 +132,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/location/delete/{id}")
public String deleteLocation(@PathVariable Integer id, Model model, HttpServletRequest request) {
public String deleteLocation(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
service.deleteLocation(id);
return "redirect:/admin/location";
}
@ -150,7 +154,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/camp/edit/{id}")
public String prepareEditCamp(@PathVariable Integer id, Model model, HttpServletRequest request) {
public String prepareEditCamp(@PathVariable("id") Integer id, Model model, HttpServletRequest request) {
model.addAttribute("bean", service.getCamp(id));
model.addAttribute("documents", service.getCampDocuments());
model.addAttribute("locations", service.getLocations());
@ -182,7 +186,7 @@ public class AdminController extends CommonController {
}
@GetMapping("/admin/camp/delete/{id}")
public String deleteCamp(@PathVariable Integer id, Model model, HttpServletRequest request,
public String deleteCamp(@PathVariable("id") Integer id, Model model, HttpServletRequest request,
RedirectAttributes redirect) {
String error = service.deleteCamp(id);
redirect.addAttribute("error", error);

View File

@ -0,0 +1,125 @@
package de.jottyfan.camporganizer.module.admin;
import java.util.List;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.CampProfileBean;
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
/**
*
* @author jotty
*
*/
@Controller
public class AdminPrivilegesController extends CommonController {
@Autowired
private AdminPrivilegesService service;
@GetMapping("/admin/privileges/userbased")
public String getUserbased(Model model) {
model.addAttribute("list", service.getProfiles());
return "/admin/privileges/userbased";
}
@GetMapping("/admin/privileges/rolebased")
public String getRolebased(Model model) {
model.addAttribute("list", service.getAllModules());
return "/admin/privileges/rolebased";
}
@GetMapping("/admin/privileges/campbased")
public String getCampbased(Model model) {
model.addAttribute("list", service.getAllCamps());
return "/admin/privileges/campbased";
}
@GetMapping("/admin/privileges/rolebased/{role}")
public String getRolebased(@PathVariable("role") String role, Model model) {
model.addAttribute("list", service.getAllModules());
model.addAttribute("selected", role);
model.addAttribute("container", service.getPersonCampMappingByModule(EnumModule.valueOf(role)));
model.addAttribute("pagedest", "_admin_privileges_rolebased_" + role);
return "/admin/privileges/rolebased";
}
@GetMapping("/admin/privileges/campbased/{campid}")
public String getCampbased(@PathVariable("campid") Integer campid, Model model) {
List<CampBean> list = service.getAllCamps();
model.addAttribute("list", list);
String campname = "?";
for (CampBean p : list) {
if (p.getPk().equals(campid)) {
campname = p.getFullname();
}
}
model.addAttribute("selected", campname);
model.addAttribute("container", service.getPersonModuleMappingByCamp(campid));
model.addAttribute("pagedest", "_admin_privileges_campbased_" + campid);
return "/admin/privileges/campbased";
}
@GetMapping("/admin/privileges/userbased/{userid}")
public String getUserbased(@PathVariable("userid") Integer userid, Model model) {
List<ProfileBean> list = service.getProfiles();
model.addAttribute("list", list);
String selected = "?";
for (ProfileBean p : list) {
if (p.getPk().equals(userid)) {
selected = p.getFullname();
}
}
model.addAttribute("selected", selected);
model.addAttribute("container", service.getModuleCampMappingByPerson(userid));
model.addAttribute("pagedest", "_admin_privileges_userbased_" + userid);
return "/admin/privileges/userbased";
}
@GetMapping("/admin/privileges/delete/{id}/{pagedest}")
public String deleteFromCampProfile(@PathVariable("id") Integer id, @PathVariable("pagedest") String pagedest) {
service.deleteFromCampProfile(id);
return "redirect:" + pagedest.replace("_", "/");
}
@GetMapping("/admin/privileges/add/{pagedest}")
public String prepareAdd(Model model, @PathVariable("pagedest") String pagedest) {
model.addAttribute("pagedest", pagedest);
model.addAttribute("bean", new CampProfileBean());
model.addAttribute("profiles", service.getProfiles());
model.addAttribute("camps", service.getAllCamps());
model.addAttribute("modules", service.getAllModules());
return "/admin/privileges/add";
}
@PostMapping("/admin/privileges/insert/{pagedest}")
public String insertCampProfile(@Valid @ModelAttribute("bean") CampProfileBean bean, final BindingResult bindingResult, @PathVariable("pagedest") String pagedest, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("pagedest", pagedest);
model.addAttribute("profiles", service.getProfiles());
model.addAttribute("camps", service.getAllCamps());
model.addAttribute("modules", service.getAllModules());
return "/admin/privileges/add";
}
service.insertIntoCampProfile(bean);
return "redirect:" + pagedest.replace("_", "/");
}
@GetMapping("/admin/privileges/abortinsert/{pagedest}")
public String abortInsert(@PathVariable("pagedest") String pagedest) {
return "redirect:" + pagedest.replace("_", "/");
}
}

View File

@ -0,0 +1,100 @@
package de.jottyfan.camporganizer.module.admin;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.CampProfileBean;
import de.jottyfan.camporganizer.module.admin.model.PrivilegesContainerBean;
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
/**
*
* @author jotty
*
*/
@Service
public class AdminPrivilegesService {
@Autowired
private AdminRepository adminRepository;
/**
* get all camp beans from the database
*
* @return all camp beans; an empty list at least
*/
public List<CampBean> getAllCamps() {
return adminRepository.getAllCamps();
}
/**
* get all profiles from the db
*
* @return the profiles
*/
public List<ProfileBean> getProfiles() {
return adminRepository.getProfiles();
}
/**
* get all roles
*
* @return all roles
*/
public List<String> getAllModules() {
return adminRepository.getAllModules();
}
/**
* get the mapping that contains the form bean for a selected module
*
* @param module the module
* @return the container
*/
public PrivilegesContainerBean getPersonCampMappingByModule(EnumModule module) {
return adminRepository.getPersonCampMappingByModule(module);
}
/**
* get the mapping that contains the form bean for a selected camp
*
* @param camp the camp ID
* @return the container
*/
public PrivilegesContainerBean getPersonModuleMappingByCamp(Integer camp) {
return adminRepository.getPersonModuleMappingByCamp(camp);
}
/**
* get the mapping that contains the form bean for a selected user
*
* @param user the user ID
* @return the container
*/
public PrivilegesContainerBean getModuleCampMappingByPerson(Integer user) {
return adminRepository.getModuleCampMappingByPerson(user);
}
/**
* delete from camp profile
*
* @param id the ID
*/
public void deleteFromCampProfile(Integer id) {
adminRepository.deleteFromCampProfile(id);
}
/**
* add the camp profile to the database
*
* @param bean the bean
*/
public void insertIntoCampProfile(CampProfileBean bean) {
EnumModule m = bean.getModule() == null ? null : EnumModule.valueOf(bean.getModule());
adminRepository.addToCampProfile(bean.getFkCamp(), bean.getFkProfile(), m);
}
}

View File

@ -1,6 +1,7 @@
package de.jottyfan.camporganizer.module.admin;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENTROLE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
@ -12,11 +13,10 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.validation.Valid;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jooq.Condition;
@ -25,12 +25,13 @@ import org.jooq.DeleteConditionStep;
import org.jooq.Field;
import org.jooq.InsertResultStep;
import org.jooq.InsertReturningStep;
import org.jooq.InsertValuesStep11;
import org.jooq.InsertValuesStep16;
import org.jooq.InsertValuesStep3;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.jooq.SelectSeekStep2;
import org.jooq.SelectWhereStep;
import org.jooq.UpdateConditionStep;
import org.jooq.UpdateSetMoreStep;
@ -43,13 +44,22 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampprofileRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentroleRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TLocationRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
import de.jottyfan.camporganizer.module.admin.model.IntKeyValueBean;
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
import de.jottyfan.camporganizer.module.admin.model.PrivilegesContainerBean;
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
import jakarta.validation.Valid;
/**
*
@ -86,7 +96,7 @@ public class AdminRepository {
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
.orderBy(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r = sql.fetchOne();
if (r != null) {
DocumentBean bean = new DocumentBean();
@ -119,9 +129,11 @@ public class AdminRepository {
.groupBy(T_DOCUMENT.PK, T_DOCUMENT.NAME, T_DOCUMENT.DOCTYPE, T_DOCUMENT.FILETYPE)
.orderBy(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql.toString());
List<DocumentBean> list = new ArrayList<>();
for (Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r : sql.fetch()) {
Iterator<Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record5<Integer, String, EnumDocument, EnumFiletype, EnumCamprole[]> r = i.next();
DocumentBean bean = new DocumentBean();
bean.setPk(r.get(T_DOCUMENT.PK));
bean.setName(r.get(T_DOCUMENT.NAME));
@ -150,9 +162,11 @@ public class AdminRepository {
.from(T_DOCUMENT)
.where(condition);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<DocumentBean> list = new ArrayList<>();
for (Record4<Integer, String, EnumDocument, EnumFiletype> r : sql.fetch()) {
Iterator<Record4<Integer, String, EnumDocument, EnumFiletype>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, EnumDocument, EnumFiletype> r = i.next();
DocumentBean bean = new DocumentBean();
bean.setPk(r.get(T_DOCUMENT.PK));
bean.setName(r.get(T_DOCUMENT.NAME));
@ -188,7 +202,7 @@ public class AdminRepository {
.set(T_DOCUMENT.FILETYPE, bean.getFiletype())
.where(T_DOCUMENT.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
} else {
InsertResultStep<TDocumentRecord> sql = DSL.using(c)
@ -201,7 +215,7 @@ public class AdminRepository {
.values(bean.getName(), bean.getDoctype(), bean.getDocument(), bean.getFiletype())
.returning(T_DOCUMENT.PK);
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
pk = sql.fetchOne().get(T_DOCUMENT.PK);
lrw.add(1);
}
@ -219,7 +233,7 @@ public class AdminRepository {
.onConflict(T_DOCUMENTROLE.FK_DOCUMENT, T_DOCUMENTROLE.CAMPROLE)
.doNothing();
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
removeCandidates.remove(role);
} catch (IllegalArgumentException e) {
@ -232,7 +246,7 @@ public class AdminRepository {
.where(T_DOCUMENTROLE.FK_DOCUMENT.eq(pk))
.and(T_DOCUMENTROLE.CAMPROLE.in(removeCandidates));
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
});
return lrw.getCounter();
@ -254,7 +268,7 @@ public class AdminRepository {
.set(T_CAMP.FK_DOCUMENT, (Integer) null)
.where(T_CAMP.FK_DOCUMENT.eq(pk));
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
UpdateConditionStep<TLocationRecord> sql1 = DSL.using(t)
@ -263,7 +277,7 @@ public class AdminRepository {
.set(T_LOCATION.FK_DOCUMENT, (Integer) null)
.where(T_LOCATION.FK_DOCUMENT.eq(pk));
// @formatter:on
LOGGER.debug("{}", sql1.toString());
LOGGER.trace(sql1);
lrw.add(sql1.execute());
DeleteConditionStep<TDocumentroleRecord> sql2 = DSL.using(t)
@ -271,7 +285,7 @@ public class AdminRepository {
.deleteFrom(T_DOCUMENTROLE)
.where(T_DOCUMENTROLE.FK_DOCUMENT.eq(pk));
// @formatter:on
LOGGER.debug("{}", sql2.toString());
LOGGER.trace(sql2);
lrw.add(sql2.execute());
DeleteConditionStep<TDocumentRecord> sql3 = DSL.using(t)
@ -279,7 +293,7 @@ public class AdminRepository {
.deleteFrom(T_DOCUMENT)
.where(T_DOCUMENT.PK.eq(pk));
// @formatter:on
LOGGER.debug("{}", sql3.toString());
LOGGER.trace(sql3);
lrw.add(sql3.execute());
});
return lrw.getCounter();
@ -292,7 +306,7 @@ public class AdminRepository {
*/
public List<LocationBean> getLocations() {
SelectWhereStep<TLocationRecord> sql = jooq.selectFrom(T_LOCATION);
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<LocationBean> list = new ArrayList<>();
for (TLocationRecord r : sql.fetch()) {
list.add(LocationBean.of(r));
@ -308,7 +322,7 @@ public class AdminRepository {
*/
public LocationBean getLocation(Integer id) {
SelectConditionStep<TLocationRecord> sql = jooq.selectFrom(T_LOCATION).where(T_LOCATION.PK.eq(id));
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return LocationBean.of(sql.fetchOne());
}
@ -320,7 +334,7 @@ public class AdminRepository {
*/
public Integer deleteLocation(Integer id) {
DeleteConditionStep<TLocationRecord> sql = jooq.deleteFrom(T_LOCATION).where(T_LOCATION.PK.eq(id));
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.execute();
}
@ -342,7 +356,7 @@ public class AdminRepository {
T_LOCATION.URL)
.values(bean.getName(), bean.getFkDocument(), bean.getUrl());
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
} else {
UpdateConditionStep<TLocationRecord> sql = DSL.using(t)
@ -353,7 +367,7 @@ public class AdminRepository {
.set(T_LOCATION.URL, bean.getUrl())
.where(T_LOCATION.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
}
});
@ -367,7 +381,7 @@ public class AdminRepository {
*/
public List<CampBean> getAllCamps() {
SelectWhereStep<TCampRecord> sql = jooq.selectFrom(T_CAMP);
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<CampBean> list = new ArrayList<>();
for (TCampRecord r : sql.fetch()) {
list.add(CampBean.of(r));
@ -383,7 +397,7 @@ public class AdminRepository {
*/
public CampBean getCamp(Integer id) {
SelectConditionStep<TCampRecord> sql = jooq.selectFrom(T_CAMP).where(T_CAMP.PK.eq(id));
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return CampBean.of(sql.fetchOne());
}
@ -397,11 +411,11 @@ public class AdminRepository {
LambdaResultWrapper lrw = new LambdaResultWrapper();
jooq.transaction(t -> {
SelectConditionStep<TPersonRecord> sql1 = DSL.using(t).selectFrom(T_PERSON).where(T_PERSON.FK_CAMP.eq(id));
LOGGER.debug(sql1.toString());
LOGGER.trace(sql1);
Integer registrations = sql1.fetch().size();
if (registrations < 1) {
DeleteConditionStep<TCampRecord> sql2 = DSL.using(t).deleteFrom(T_CAMP).where(T_CAMP.PK.eq(id));
LOGGER.debug(sql2.toString());
LOGGER.trace(sql2);
sql2.execute();
} else {
lrw.putString("error", String
@ -424,7 +438,7 @@ public class AdminRepository {
LocalDateTime arrive = arriveDate == null ? null : arriveDate.atStartOfDay();
LocalDateTime depart = departDate == null ? null : departDate.atStartOfDay();
if (bean.getPk() == null) {
InsertValuesStep11<TCampRecord, LocalDateTime, String, LocalDateTime, Integer, Integer, Integer, Boolean, Integer, Integer, String, String> sql = DSL
InsertValuesStep16<TCampRecord, LocalDateTime, String, LocalDateTime, Integer, Integer, Integer, Boolean, Integer, Integer, String, String, Integer, Integer, Integer, Integer, LocalDateTime> sql = DSL
.using(t)
// @formatter:off
.insertInto(T_CAMP,
@ -438,11 +452,17 @@ public class AdminRepository {
T_CAMP.MAX_AGE,
T_CAMP.MIN_AGE,
T_CAMP.NAME,
T_CAMP.PRICE)
T_CAMP.PRICE,
T_CAMP.BEDS_FEMALE,
T_CAMP.BEDS_MALE,
T_CAMP.BLOCKED_BEDS_FEMALE,
T_CAMP.BLOCKED_BEDS_MALE,
T_CAMP.START_BOOKING)
.values(arrive, bean.getCountries(), depart, bean.getFkDocument(), bean.getFkLocation(), bean.getFkProfile(),
bean.getLockSales() != null ? bean.getLockSales() : false, bean.getMaxAge(), bean.getMinAge(), bean.getName(), bean.getPrice());
bean.getLockSales() != null ? bean.getLockSales() : false, bean.getMaxAge(), bean.getMinAge(), bean.getName(), bean.getPrice(),
bean.getBedsFemale(), bean.getBedsMale(), bean.getBlockedBedsFemale(), bean.getBlockedBedsMale(), bean.getStartBooking());
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
sql.execute();
} else {
UpdateConditionStep<TCampRecord> sql = DSL.using(t)
@ -459,9 +479,14 @@ public class AdminRepository {
.set(T_CAMP.MIN_AGE, bean.getMinAge())
.set(T_CAMP.NAME, bean.getName())
.set(T_CAMP.PRICE, bean.getPrice())
.set(T_CAMP.BEDS_FEMALE, bean.getBedsFemale())
.set(T_CAMP.BEDS_MALE, bean.getBedsMale())
.set(T_CAMP.BLOCKED_BEDS_FEMALE, bean.getBlockedBedsFemale())
.set(T_CAMP.BLOCKED_BEDS_MALE, bean.getBlockedBedsMale())
.set(T_CAMP.START_BOOKING, bean.getStartBooking())
.where(T_CAMP.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
sql.execute();
}
});
@ -475,11 +500,173 @@ public class AdminRepository {
*/
public List<ProfileBean> getProfiles() {
SelectWhereStep<TProfileRecord> sql = jooq.selectFrom(T_PROFILE);
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<ProfileBean> list = new ArrayList<>();
for (TProfileRecord r : sql.fetch()) {
list.add(ProfileBean.of(r));
}
return list;
}
/**
* get all modules
*
* @return all modules
*/
public List<String> getAllModules() {
List<String> list = new ArrayList<>();
for (EnumModule r : EnumModule.values()) {
list.add(r.getLiteral());
}
return list;
}
/**
* get the mapping that contains the form bean for a selected module
*
* @param module the module
* @return the container
*/
public PrivilegesContainerBean getPersonCampMappingByModule(EnumModule module) {
SelectSeekStep2<Record4<Integer, String, LocalDateTime, String>, LocalDateTime, Integer> sql = jooq
// @formatter:off
.select(T_CAMPPROFILE.PK,
T_CAMP.NAME,
T_CAMP.ARRIVE,
T_PROFILE.FORENAME.concat(" ").concat(T_PROFILE.SURNAME).as(T_PROFILE.USERNAME))
.from(T_CAMPPROFILE)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_CAMPPROFILE.MODULE.eq(module))
.orderBy(T_CAMP.ARRIVE, T_PROFILE.PK);
// @formatter:on
LOGGER.trace(sql);
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
Iterator<Record4<Integer, String, LocalDateTime, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, LocalDateTime, String> r = i.next();
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
String username = r.get(T_PROFILE.USERNAME);
String campname = r.get(T_CAMP.NAME);
LocalDateTime ldt = r.get(T_CAMP.ARRIVE);
String year = ldt != null ? String.valueOf(ldt.getYear()) : "?";
campname = campname == null ? year : campname.concat(" ").concat(year);
if (pcb.get(username) == null) {
pcb.addKey(username);
}
pcb.add(username, IntKeyValueBean.of(fkCampProfile, campname));
}
return pcb;
}
/**
* get the mapping that contains the form bean for a selected user
*
* @param user the user ID
* @return the container
*/
public PrivilegesContainerBean getModuleCampMappingByPerson(Integer user) {
SelectSeekStep1<Record4<Integer, String, LocalDateTime, EnumModule>, LocalDateTime> sql = jooq
// @formatter:off
.select(T_CAMPPROFILE.PK,
T_CAMP.NAME,
T_CAMP.ARRIVE,
T_CAMPPROFILE.MODULE)
.from(T_CAMPPROFILE)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
.where(T_CAMPPROFILE.FK_PROFILE.eq(user))
.orderBy(T_CAMP.ARRIVE);
// @formatter:on
LOGGER.trace(sql);
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
Iterator<Record4<Integer, String, LocalDateTime, EnumModule>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, LocalDateTime, EnumModule> r = i.next();
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
EnumModule moduleEnum = r.get(T_CAMPPROFILE.MODULE);
String module = moduleEnum == null ? null : moduleEnum.getLiteral();
String campname = r.get(T_CAMP.NAME);
LocalDateTime ldt = r.get(T_CAMP.ARRIVE);
String year = ldt != null ? String.valueOf(ldt.getYear()) : "?";
campname = campname == null ? year : campname.concat(" ").concat(year);
if (pcb.get(module) == null) {
pcb.addKey(module);
}
pcb.add(module, IntKeyValueBean.of(fkCampProfile, campname));
}
return pcb;
}
/**
* get the mapping that contains the form bean for a selected camp
*
* @param camp the camp ID
* @return the container
*/
public PrivilegesContainerBean getPersonModuleMappingByCamp(Integer camp) {
SelectSeekStep2<Record4<Integer, String, String, EnumModule>, String, String> sql = jooq
// @formatter:off
.select(T_CAMPPROFILE.PK,
T_PROFILE.FORENAME,
T_PROFILE.SURNAME,
T_CAMPPROFILE.MODULE)
.from(T_CAMPPROFILE)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_CAMPPROFILE.FK_CAMP.eq(camp))
.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME);
// @formatter:on
LOGGER.trace(sql);
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
Iterator<Record4<Integer, String, String, EnumModule>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, String, EnumModule> r = i.next();
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
EnumModule moduleEnum = r.get(T_CAMPPROFILE.MODULE);
String forename = r.get(T_PROFILE.FORENAME);
String surname = r.get(T_PROFILE.SURNAME);
String person = new StringBuilder().append(forename).append(" ").append(surname).toString();
String module = moduleEnum == null ? null : moduleEnum.getLiteral();
if (pcb.get(person) == null) {
pcb.addKey(person);
}
pcb.add(person, IntKeyValueBean.of(fkCampProfile, module));
}
return pcb;
}
/**
* delete entry from camp profile
*
* @param id the pk
*/
public void deleteFromCampProfile(Integer id) {
DeleteConditionStep<TCampprofileRecord> sql = jooq.deleteFrom(T_CAMPPROFILE).where(T_CAMPPROFILE.PK.eq(id));
LOGGER.trace(sql);
sql.execute();
}
/**
* add entry to database
*
* @param fkCamp the camp ID
* @param fkProfile the profile ID
* @param module the module
*/
public void addToCampProfile(Integer fkCamp, Integer fkProfile, EnumModule module) {
InsertReturningStep<TCampprofileRecord> sql = jooq
// @formatter:off
.insertInto(T_CAMPPROFILE,
T_CAMPPROFILE.FK_CAMP,
T_CAMPPROFILE.FK_PROFILE,
T_CAMPPROFILE.MODULE)
.values(fkCamp, fkProfile, module)
.onConflict(T_CAMPPROFILE.FK_CAMP,
T_CAMPPROFILE.FK_PROFILE,
T_CAMPPROFILE.MODULE)
.doNothing();
// @formatter:on
LOGGER.trace(sql);
sql.execute();
}
}

View File

@ -5,7 +5,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
import java.io.IOException;
import java.util.List;
import javax.validation.Valid;
import jakarta.validation.Valid;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -13,6 +13,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
import de.jottyfan.camporganizer.module.admin.model.CampBean;
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
import de.jottyfan.camporganizer.module.mail.MailBean;
import de.jottyfan.camporganizer.module.mail.MailRepository;

View File

@ -1,17 +1,18 @@
package de.jottyfan.camporganizer.module.admin;
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.springframework.format.annotation.DateTimeFormat;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
@ -44,6 +45,21 @@ public class CampBean implements Serializable {
private String countries;
@NotNull
private String price;
@NotNull
@Min(value = 0)
private Integer bedsFemale;
@NotNull
@Min(value = 0)
private Integer bedsMale;
@NotNull
@Min(value = 0)
private Integer blockedBedsFemale;
@NotNull
@Min(value = 0)
private Integer blockedBedsMale;
@NotNull
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime startBooking;
/**
* generate a camp bean out of r
@ -70,9 +86,18 @@ public class CampBean implements Serializable {
bean.setName(r.getName());
bean.setPk(r.getPk());
bean.setPrice(r.getPrice());
bean.setBedsFemale(r.getBedsFemale());
bean.setBedsMale(r.getBedsMale());
bean.setBlockedBedsFemale(r.getBlockedBedsFemale());
bean.setBlockedBedsMale(r.getBlockedBedsMale());
bean.setStartBooking(r.getStartBooking());
return bean;
}
public String getFullname() {
return new StringBuilder().append(name).append(" ").append(arrive == null ? "?" : arrive.format(DateTimeFormatter.ofPattern("yyyy"))).toString();
}
/**
* @return the pk
*/
@ -267,4 +292,74 @@ public class CampBean implements Serializable {
}
this.countries = buf.toString();
}
/**
* @return the bedsFemale
*/
public Integer getBedsFemale() {
return bedsFemale;
}
/**
* @param bedsFemale the bedsFemale to set
*/
public void setBedsFemale(Integer bedsFemale) {
this.bedsFemale = bedsFemale;
}
/**
* @return the bedsMale
*/
public Integer getBedsMale() {
return bedsMale;
}
/**
* @param bedsMale the bedsMale to set
*/
public void setBedsMale(Integer bedsMale) {
this.bedsMale = bedsMale;
}
/**
* @return the blockedBedsFemale
*/
public Integer getBlockedBedsFemale() {
return blockedBedsFemale;
}
/**
* @param blockedBedsFemale the blockedBedsFemale to set
*/
public void setBlockedBedsFemale(Integer blockedBedsFemale) {
this.blockedBedsFemale = blockedBedsFemale;
}
/**
* @return the blockedBedsMale
*/
public Integer getBlockedBedsMale() {
return blockedBedsMale;
}
/**
* @param blockedBedsMale the blockedBedsMale to set
*/
public void setBlockedBedsMale(Integer blockedBedsMale) {
this.blockedBedsMale = blockedBedsMale;
}
/**
* @return the startBooking
*/
public LocalDateTime getStartBooking() {
return startBooking;
}
/**
* @param startBooking the startBooking to set
*/
public void setStartBooking(LocalDateTime startBooking) {
this.startBooking = startBooking;
}
}

View File

@ -0,0 +1,80 @@
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
* @author jotty
*
*/
public class CampProfileBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer pk;
@NotNull
private Integer fkCamp;
@NotNull
private Integer fkProfile;
@NotBlank
private String module;
/**
* @return the pk
*/
public Integer getPk() {
return pk;
}
/**
* @param pk the pk to set
*/
public void setPk(Integer pk) {
this.pk = pk;
}
/**
* @return the fkCamp
*/
public Integer getFkCamp() {
return fkCamp;
}
/**
* @param fkCamp the fkCamp to set
*/
public void setFkCamp(Integer fkCamp) {
this.fkCamp = fkCamp;
}
/**
* @return the fkProfile
*/
public Integer getFkProfile() {
return fkProfile;
}
/**
* @param fkProfile the fkProfile to set
*/
public void setFkProfile(Integer fkProfile) {
this.fkProfile = fkProfile;
}
/**
* @return the module
*/
public String getModule() {
return module;
}
/**
* @param module the module to set
*/
public void setModule(String module) {
this.module = module;
}
}

View File

@ -1,12 +1,12 @@
package de.jottyfan.camporganizer.module.admin;
package de.jottyfan.camporganizer.module.admin.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Base64;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;

View File

@ -0,0 +1,50 @@
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class IntKeyValueBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer key;
private String value;
public static final IntKeyValueBean of(Integer key, String value) {
IntKeyValueBean bean = new IntKeyValueBean();
bean.setKey(key);
bean.setValue(value);
return bean;
}
/**
* @return the key
*/
public Integer getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(Integer key) {
this.key = key;
}
/**
* @return the value
*/
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
}

View File

@ -1,9 +1,9 @@
package de.jottyfan.camporganizer.module.admin;
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import de.jottyfan.camporganizer.db.jooq.tables.records.TLocationRecord;

View File

@ -0,0 +1,62 @@
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author jotty
*
*/
public class PrivilegesContainerBean implements Serializable {
private static final long serialVersionUID = 1L;
private Map<String, List<IntKeyValueBean>> map;
public PrivilegesContainerBean() {
map = new HashMap<>();
}
/**
* get the content of key
*
* @param key the key
* @return the value
*/
public List<IntKeyValueBean> get(String key) {
return map == null ? null : map.get(key);
}
/**
* add the value to the key
*
* @param key the key
* @param value the value
*/
public void add(String key, IntKeyValueBean value) {
if (get(key) != null) {
map.get(key).add(value);
} else {
throw new NullPointerException("key not found");
}
}
/**
* add the key to this map
*
* @param key
*/
public void addKey(String key) {
map.put(key, new ArrayList<>());
}
/**
* @return the map
*/
public Map<String, List<IntKeyValueBean>> getMap() {
return map;
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.admin;
package de.jottyfan.camporganizer.module.admin.model;
import java.io.Serializable;
@ -27,6 +27,10 @@ public class ProfileBean implements Serializable {
return bean;
}
public String getFullname() {
return new StringBuilder().append(forename).append(" ").append(surname).toString();
}
/**
* @return the pk
*/

View File

@ -1,6 +1,6 @@
package de.jottyfan.camporganizer.module.business.bookings;
import javax.annotation.security.RolesAllowed;
import jakarta.annotation.security.RolesAllowed;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import de.jottyfan.camporganizer.module.business.bookings.impl.AddPaymentBean;
import de.jottyfan.camporganizer.module.business.bookings.impl.BookerBean;
import de.jottyfan.camporganizer.module.business.bookings.model.AddPaymentBean;
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
/**
@ -27,7 +27,7 @@ public class BookingsController extends CommonController {
private static final Logger LOGGER = LogManager.getLogger(BookingsController.class);
@Autowired
private IBookingsService bookingsService;
private BookingsService bookingsService;
@GetMapping("/business/bookings")
@RolesAllowed({"business_booking"})
@ -39,7 +39,7 @@ public class BookingsController extends CommonController {
@GetMapping("/business/bookings/{id}")
@RolesAllowed({"business_booking"})
public String getBooking(Model model, @PathVariable Integer id) {
public String getBooking(Model model, @PathVariable("id") Integer id) {
BookerBean bean = bookingsService.getBooker(id, getCurrentUser());
model.addAttribute("booker", bean);
model.addAttribute("addBean", new AddPaymentBean());
@ -48,7 +48,7 @@ public class BookingsController extends CommonController {
@PostMapping("/business/bookings/payment/{id}")
@RolesAllowed({"business_booking"})
public String addPayment(Model model, @ModelAttribute AddPaymentBean bean, @PathVariable Integer id) {
public String addPayment(Model model, @ModelAttribute("bean") AddPaymentBean bean, @PathVariable("id") Integer id) {
Double payment = bean.getPayment();
bookingsService.addPayment(id, payment);
return getBooking(model, id);
@ -56,7 +56,7 @@ public class BookingsController extends CommonController {
@PostMapping("/business/bookings/listpayment/{id}")
@RolesAllowed({"business_booking"})
public String addListPayment(Model model, @ModelAttribute AddPaymentBean bean, @PathVariable Integer id, @RequestParam(defaultValue = "") String search) {
public String addListPayment(Model model, @ModelAttribute("bean") AddPaymentBean bean, @PathVariable("id") Integer id, @RequestParam(defaultValue = "") String search) {
Double payment = bean.getPayment();
bookingsService.addPayment(id, payment);
LOGGER.debug("search is {}", search);

View File

@ -1,13 +1,14 @@
package de.jottyfan.camporganizer.module.business.bookings.impl;
package de.jottyfan.camporganizer.module.business.bookings;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.Iterator;
import java.util.List;
import org.apache.logging.log4j.LogManager;
@ -25,8 +26,11 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.EnumConverter;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
/**
*
@ -49,23 +53,26 @@ public class BookingsRepository {
* @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
SelectSeekStep4<Record10<Integer, EnumProgress, 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)
.select(T_PERSON.PK, T_PERSON.PROGRESS, 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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.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());
LOGGER.trace(sql);
List<BookerBean> list = new ArrayList<>();
for (Record r : sql.fetch()) {
Iterator<Record10<Integer, EnumProgress, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, String, Double>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record10<Integer, EnumProgress, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, String, Double> r = i.next();
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);
EnumProgress progress = r.get(T_PERSON.PROGRESS);
String campName = r.get(V_CAMP.NAME);
Double campYear = r.get(V_CAMP.YEAR);
BookerBean bean = new BookerBean();
@ -74,7 +81,7 @@ public class BookingsRepository {
bean.setRole(EnumConverter.role2GermanNames(role));
bean.setSex(EnumConverter.sex2GermanNames(sex));
bean.setBookingDate(r.get(T_PERSON.CREATED));
bean.setAccept(r.get(T_PERSON.ACCEPT));
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setPaid(r.get(T_PERSON.PAID));
bean.setCamp(String.format("%s %4.0f", campName, campYear));
list.add(bean);
@ -90,10 +97,10 @@ public class BookingsRepository {
* @return the booker bean or null
*/
public BookerBean getBooking(Integer id, String username) {
SelectConditionStep<Record13<Integer, Boolean, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, BigDecimal, String, Double, String, Integer>> sql = jooq
SelectConditionStep<Record13<Integer, EnumProgress, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime, BigDecimal, String, Double, String, Integer>> sql = jooq
// @formatter:off
.select(T_PERSON.PK,
T_PERSON.ACCEPT,
T_PERSON.PROGRESS,
T_PERSON.PAID,
T_PERSON.FORENAME,
T_PERSON.SURNAME,
@ -107,12 +114,12 @@ public class BookingsRepository {
V_CAMP.PK)
.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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_PROFILE.USERNAME.eq(username))
.and(T_PERSON.PK.eq(id));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
Record r = sql.fetchOne();
if (r == null) {
return null;
@ -121,6 +128,7 @@ public class BookingsRepository {
String surname = r.get(T_PERSON.SURNAME);
EnumCamprole role = r.get(T_PERSON.CAMPROLE);
EnumSex sex = r.get(T_PERSON.SEX);
EnumProgress progress = r.get(T_PERSON.PROGRESS);
BigDecimal requiredPrice = r.get(T_PERSON.REQUIRED_PRICE);
String campName = r.get(V_CAMP.NAME);
Double campYear = r.get(V_CAMP.YEAR);
@ -131,7 +139,7 @@ public class BookingsRepository {
bean.setRole(EnumConverter.role2GermanNames(role));
bean.setSex(EnumConverter.sex2GermanNames(sex));
bean.setBookingDate(r.get(T_PERSON.CREATED));
bean.setAccept(r.get(T_PERSON.ACCEPT));
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setPaid(r.get(T_PERSON.PAID));
bean.setCamp(String.format("%s %4.0f", campName, campYear));
bean.setCampId(campId);
@ -157,7 +165,7 @@ public class BookingsRepository {
.set(T_PERSON.PAID, value)
.where(T_PERSON.PK.eq(pk));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.execute();
}
}

View File

@ -1,11 +1,11 @@
package de.jottyfan.camporganizer.module.business.bookings.impl;
package de.jottyfan.camporganizer.module.business.bookings;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
/**
*
@ -13,24 +13,20 @@ import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
*
*/
@Service
public class BookingsService implements IBookingsService {
public class BookingsService {
@Autowired
private BookingsRepository 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);
}
}

View File

@ -1,38 +0,0 @@
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);
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.bookings.impl;
package de.jottyfan.camporganizer.module.business.bookings.model;
import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.bookings.impl;
package de.jottyfan.camporganizer.module.business.bookings.model;
import java.io.Serializable;
import java.math.BigDecimal;
@ -10,13 +10,13 @@ import java.time.LocalDateTime;
*
*/
public class BookerBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 2L;
private Integer pk;
private String name;
private String role;
private String sex;
private Boolean accept;
private String progress;
private LocalDateTime bookingDate;
private BigDecimal paid;
private String camp;
@ -24,20 +24,6 @@ public class BookerBean implements Serializable {
private Integer campId;
private BigDecimal requiredPrice;
/**
* @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
*/
@ -141,4 +127,18 @@ public class BookerBean implements Serializable {
public void setRequiredPrice(BigDecimal requiredPrice) {
this.requiredPrice = requiredPrice;
}
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -1,7 +1,5 @@
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;
@ -18,15 +16,12 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
public class BusinessController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private IBusinessService indexService;
private BusinessService service;
@GetMapping("/business")
public String getIndex(Model model) {
String username = indexService.getCurrentUser(request);
model.addAttribute("campBudgets", indexService.getCampBudgets(username));
String username = super.getCurrentUser();
model.addAttribute("campBudgets", service.getCampBudgets(username));
return "business/business";
}
}

View File

@ -1,20 +1,22 @@
package de.jottyfan.camporganizer.module.business.business.impl;
package de.jottyfan.camporganizer.module.business.business;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.Iterator;
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.Record4;
import org.jooq.Record9;
import org.jooq.SelectConditionStep;
@ -24,7 +26,10 @@ 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.EnumModule;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.module.business.business.model.BusinessBean;
import de.jottyfan.camporganizer.module.business.business.model.CampBudgetBean;
/**
*
@ -55,14 +60,16 @@ public class BusinessRepository {
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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(V_CAMP_BUDGET.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_PROFILE.USERNAME.eq(username))
.orderBy(T_CAMP.ARRIVE);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<CampBudgetBean> list = new ArrayList<>();
for (Record4<BigDecimal, String, Double, Integer> r : sql.fetch()) {
Iterator<Record4<BigDecimal, String, Double, Integer>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record r = i.next();
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);
@ -94,13 +101,15 @@ public class BusinessRepository {
.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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_CAMP.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_PROFILE.USERNAME.eq(username));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<BusinessBean> list = new ArrayList<>();
for (Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal> r : sql.fetch()) {
Iterator<Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record9<Integer, String, String, String, String, LocalDateTime, String, BigDecimal, BigDecimal> r = i.next();
Integer fkPerson = r.get(T_PERSON.PK);
String forename = r.get(T_PERSON.FORENAME);
String surname = r.get(T_PERSON.SURNAME);
@ -131,7 +140,7 @@ public class BusinessRepository {
.set(T_PERSON.PAID, bean.getPaid())
.where(T_PERSON.PK.eq(bean.getFkPerson()));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
count += sql.execute();
}
}

View File

@ -0,0 +1,24 @@
package de.jottyfan.camporganizer.module.business.business;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.business.business.model.CampBudgetBean;
/**
*
* @author jotty
*
*/
@Service
public class BusinessService {
@Autowired
private BusinessRepository gateway;
public List<CampBudgetBean> getCampBudgets(String username) {
return gateway.getCampBudgets(username);
}
}

View File

@ -1,30 +0,0 @@
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);
}

View File

@ -1,38 +0,0 @@
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 BusinessRepository 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);
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.business.impl;
package de.jottyfan.camporganizer.module.business.business.model;
import java.io.Serializable;
import java.math.BigDecimal;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.business.impl;
package de.jottyfan.camporganizer.module.business.business.model;
import java.io.Serializable;
import java.math.BigDecimal;

View File

@ -1,38 +1,29 @@
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;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import jakarta.annotation.security.RolesAllowed;
/**
*
* @author jotty
*
*/
*
* @author jotty
*
*/
@Controller
public class CampController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private IBusinessService indexService;
@Autowired
private ICampService campService;
private CampService campService;
@GetMapping("/business/camp/{id}")
@RolesAllowed({"business"})
public String getCamp(Model model, @PathVariable Integer id) {
String username = indexService.getCurrentUser(request);
@RolesAllowed({ "business" })
public String getCamp(Model model, @PathVariable("id") Integer id) {
String username = super.getCurrentUser();
model.addAttribute("currentUser", username);
model.addAttribute("campId", id);
model.addAttribute("camp", campService.getCamp(id, username));

View File

@ -1,19 +1,19 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.Iterator;
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;
@ -24,7 +24,11 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.EnumConverter;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
import de.jottyfan.camporganizer.module.business.camp.model.PersonBean;
/**
*
@ -52,14 +56,16 @@ public class CampRepository {
// @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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(V_CAMP.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(V_CAMP.PK.eq(pk))
.and(T_PROFILE.USERNAME.eq(username));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
CampBean bean = new CampBean();
for (Record6<String, Double, LocalDateTime, LocalDateTime, String, String> r : sql.fetch()) {
Iterator<Record6<String, Double, LocalDateTime, LocalDateTime, String, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record6<String, Double, LocalDateTime, LocalDateTime, String, String> r = i.next();
bean.setName(r.get(V_CAMP.NAME));
bean.setYear(r.get(V_CAMP.YEAR));
bean.setArrive(r.get(V_CAMP.ARRIVE));
@ -79,30 +85,33 @@ public class CampRepository {
* @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
SelectSeekStep4<Record8<Integer, EnumProgress, 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)
.select(T_PERSON.PK, T_PERSON.PROGRESS, 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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.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());
LOGGER.trace(sql);
List<PersonBean> list = new ArrayList<>();
for (Record r : sql.fetch()) {
Iterator<Record8<Integer, EnumProgress, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record8<Integer, EnumProgress, BigDecimal, String, String, EnumCamprole, EnumSex, LocalDateTime> r = i.next();
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);
EnumProgress progress = r.get(T_PERSON.PROGRESS);
PersonBean bean = new PersonBean();
bean.setPk(r.get(T_PERSON.PK));
bean.setName(String.format("%s %s", forename, surname));
bean.setRole(EnumConverter.role2GermanNames(role));
bean.setSex(EnumConverter.sex2GermanNames(sex));
bean.setBookingDate(r.get(T_PERSON.CREATED));
bean.setAccept(r.get(T_PERSON.ACCEPT));
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setPaid(r.get(T_PERSON.PAID));
list.add(bean);
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp;
import java.math.BigDecimal;
import java.util.List;
@ -6,7 +6,10 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.business.camp.ICampService;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.module.business.camp.model.BookingBean;
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
import de.jottyfan.camporganizer.module.business.camp.model.PersonBean;
/**
*
@ -14,30 +17,28 @@ import de.jottyfan.camporganizer.module.business.camp.ICampService;
*
*/
@Service
public class CampService implements ICampService {
public class CampService {
@Autowired
private CampRepository 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) {
String progress = p.getProgress();
if (EnumProgress.requested.getLiteral().equals(progress)) {
open += 1;
} else if (acceptence) {
approved +=1;
} else {
rejected +=1;
} else if (EnumProgress.approved.getLiteral().equals(progress)) {
approved += 1;
} else if (EnumProgress.rejected.getLiteral().equals(progress)) {
rejected += 1;
}
paid = paid.add(p.getPaid() == null ? new BigDecimal(0) : p.getPaid());
}
@ -49,9 +50,7 @@ public class CampService implements ICampService {
return bean;
}
@Override
public List<PersonBean> getBookers(Integer id, String username) {
return campGateway.getBookings(id, username);
}
}

View File

@ -1,43 +0,0 @@
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);
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp.model;
import java.io.Serializable;
import java.math.BigDecimal;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp.model;
import java.io.Serializable;
import java.math.BigDecimal;

View File

@ -1,11 +1,11 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp.model;
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;
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
/**
*

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.camp.impl;
package de.jottyfan.camporganizer.module.business.camp.model;
import java.io.Serializable;
import java.math.BigDecimal;
@ -16,24 +16,10 @@ public class PersonBean implements Serializable {
private String name;
private String role;
private String sex;
private Boolean accept;
private String progress;
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
*/
@ -99,4 +85,18 @@ public class PersonBean implements Serializable {
public void setBookingDate(LocalDateTime bookingDate) {
this.bookingDate = bookingDate;
}
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -0,0 +1,87 @@
package de.jottyfan.camporganizer.module.business.outlay;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
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.outlay.model.OutlayBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.Valid;
import jakarta.ws.rs.core.HttpHeaders;
/**
*
* @author jotty
*
*/
@Controller
@RolesAllowed({ "business_outlay" })
public class OutlayController extends CommonController {
@Autowired
private OutlayService service;
@GetMapping("/business/outlay")
public String getOutlayDashboard(Model model, Principal principal) {
model.addAttribute("list", service.getListOf(super.getCurrentUser(principal), null));
model.addAttribute("camps", service.getAllCamps());
return "/business/outlay/list";
}
@GetMapping("/business/outlay/add")
public String loadAddMask(Model model, Principal principal) {
model.addAttribute("bean", new OutlayBean().withUser(super.getCurrentUser(principal)));
model.addAttribute("camps", service.getAllCamps());
return "/business/outlay/editor";
}
@GetMapping("/business/outlay/edit/{id}")
public String loadAddMask(@PathVariable("id") Integer id, Model model, Principal principal) {
model.addAttribute("bean", service.getBeanIfAllowedFor(super.getCurrentUser(principal), id));
model.addAttribute("camps", service.getAllCamps());
return "/business/outlay/editor";
}
@PostMapping("/business/outlay/save")
public String save(@Valid @ModelAttribute("bean") OutlayBean bean, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("camps", service.getAllCamps());
return "/business/outlay/editor";
}
service.save(bean);
return "redirect:/business/outlay";
}
@GetMapping("/business/outlay/delete/{id}")
public String delete(@PathVariable("id") Integer id, Principal principal) {
service.deleteIfAllowedFor(super.getCurrentUser(principal), id);
return "redirect:/business/outlay";
}
@GetMapping("/business/outlay/summary/{campid}")
public String getSummaryOfCamp(@PathVariable("campid") Integer campId, Model model, Principal principal) {
model.addAttribute("campid", campId);
model.addAttribute("list", service.getListOf(null, campId));
return "/business/outlay/summary";
}
@GetMapping("/business/outlay/download/{campid}")
public ResponseEntity<Resource> generateCsv(@PathVariable("campid") Integer campId) {
String filename = String.format("rechnung_camp_%d.csv", campId);
InputStreamResource file = new InputStreamResource(service.getCsv(campId));
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
.contentType(MediaType.parseMediaType("application/csv")).body(file);
}
}

View File

@ -0,0 +1,201 @@
package de.jottyfan.camporganizer.module.business.outlay;
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_SALES;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
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.InsertValuesStep8;
import org.jooq.Record10;
import org.jooq.Record11;
import org.jooq.Record4;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.jooq.UpdateConditionStep;
import org.jooq.impl.DSL;
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.TSalesRecord;
import de.jottyfan.camporganizer.module.business.outlay.model.CampBean;
import de.jottyfan.camporganizer.module.business.outlay.model.OutlayBean;
import jakarta.validation.Valid;
/**
*
* @author jotty
*
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class OutlayRepository {
private static final Logger LOGGER = LogManager.getLogger(OutlayRepository.class);
@Autowired
private DSLContext jooq;
/**
* get all camps from the database
*
* @return a list of camps; an empty list at least
*/
public List<CampBean> getAllCamps() {
SelectSeekStep1<Record4<Integer, String, LocalDateTime, String>, LocalDateTime> sql = jooq
// @formatter:off
.select(T_CAMP.PK, T_CAMP.NAME, T_CAMP.ARRIVE, T_LOCATION.NAME)
.from(T_CAMP)
.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION))
.orderBy(T_CAMP.ARRIVE.desc());
// @formatter:on
LOGGER.trace(sql.toString());
List<CampBean> list = new ArrayList<>();
Iterator<Record4<Integer, String, LocalDateTime, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, LocalDateTime, String> r = i.next();
String name = String
.format("%s %s %d", r.get(T_CAMP.NAME), r.get(T_LOCATION.NAME), r.get(T_CAMP.ARRIVE).getYear()).trim();
list.add(CampBean.of(r.get(T_CAMP.PK)).withCampname(name));
}
return list;
}
public List<OutlayBean> getListOf(String username, Integer campId) {
SelectConditionStep<Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String>> sql = jooq
// @formatter:off
.select(T_SALES.PK,
T_SALES.TRADER,
T_CAMP.NAME,
T_CAMP.ARRIVE,
T_LOCATION.NAME,
T_SALES.CASH,
T_SALES.BUYDATE,
T_SALES.PROVIDER,
T_SALES.RECIPENUMBER,
T_SALES.INCREDIENTS,
T_SALES.RECIPENOTE)
.from(T_SALES)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_SALES.FK_CAMP))
.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION))
.where(username == null ? DSL.trueCondition() : T_SALES.PROVIDER.eq(username))
.and(campId == null ? DSL.trueCondition() : T_SALES.FK_CAMP.eq(campId));
// @formatter:on
LOGGER.trace(sql);
List<OutlayBean> list = new ArrayList<>();
Iterator<Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String>> i = sql.fetch()
.iterator();
while (i.hasNext()) {
Record11<Integer, String, String, LocalDateTime, String, BigDecimal, LocalDateTime, String, String, String, String> r = i.next();
String campname = String
.format("%s %s %d", r.get(T_CAMP.NAME), r.get(T_LOCATION.NAME), r.get(T_CAMP.ARRIVE).getYear()).trim();
OutlayBean bean = new OutlayBean();
bean.setId(r.get(T_SALES.PK));
bean.setTrader(r.get(T_SALES.TRADER));
bean.setCampname(campname);
bean.setProvider(r.get(T_SALES.PROVIDER));
bean.setCash(r.get(T_SALES.CASH));
bean.setBuydate(r.get(T_SALES.BUYDATE));
bean.setRecipenumber(r.get(T_SALES.RECIPENUMBER));
bean.setIngredients(r.get(T_SALES.INCREDIENTS));
bean.setRecipenote(r.get(T_SALES.RECIPENOTE));
list.add(bean);
}
return list;
}
public void addBean(@Valid OutlayBean bean) {
InsertValuesStep8<TSalesRecord, LocalDateTime, BigDecimal, Integer, String, String, String, String, String> sql = jooq
// @formatter:off
.insertInto(T_SALES,
T_SALES.BUYDATE,
T_SALES.CASH,
T_SALES.FK_CAMP,
T_SALES.INCREDIENTS,
T_SALES.PROVIDER,
T_SALES.RECIPENOTE,
T_SALES.RECIPENUMBER,
T_SALES.TRADER)
.values(bean.getBuydate(), bean.getCash(), bean.getFkCamp(), bean.getIngredients(), bean.getProvider(), bean.getRecipenote(), bean.getRecipenumber(), bean.getTrader());
// @formatter:on
LOGGER.trace(sql);
sql.execute();
}
public void updateBean(@Valid OutlayBean bean) {
UpdateConditionStep<TSalesRecord> sql = jooq
// @formatter:off
.update(T_SALES)
.set(T_SALES.BUYDATE, bean.getBuydate())
.set(T_SALES.CASH, bean.getCash())
.set(T_SALES.FK_CAMP, bean.getFkCamp())
.set(T_SALES.INCREDIENTS, bean.getIngredients())
.set(T_SALES.PROVIDER, bean.getProvider())
.set(T_SALES.RECIPENOTE, bean.getRecipenote())
.set(T_SALES.RECIPENUMBER, bean.getRecipenumber())
.set(T_SALES.TRADER, bean.getTrader())
.where(T_SALES.PK.eq(bean.getId()));
// @formatter:on
LOGGER.trace(sql);
sql.execute();
}
public OutlayBean getBeanIfAllowedFor(String username, Integer id) {
SelectConditionStep<Record10<Integer, String, Integer, BigDecimal, LocalDateTime, String, String, String, String, String>> sql = jooq
// @formatter:off
.select(T_SALES.PK,
T_SALES.TRADER,
T_SALES.FK_CAMP,
T_SALES.CASH,
T_SALES.BUYDATE,
T_SALES.INCREDIENTS,
T_SALES.PROVIDER,
T_SALES.RECIPENOTE,
T_SALES.RECIPENUMBER,
T_SALES.TRADER)
.from(T_SALES)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_SALES.FK_CAMP))
.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION))
.where(T_SALES.PROVIDER.eq(username))
.and(T_SALES.PK.eq(id));
// @formatter:on
LOGGER.trace(sql);
Record10<Integer, String, Integer, BigDecimal, LocalDateTime, String, String, String, String, String> r = sql
.fetchOne();
if (r == null) {
return null;
} else {
OutlayBean bean = new OutlayBean();
bean.setId(r.get(T_SALES.PK));
bean.setBuydate(r.get(T_SALES.BUYDATE));
bean.setCash(r.get(T_SALES.CASH));
bean.setFkCamp(r.get(T_SALES.FK_CAMP));
bean.setIngredients(r.get(T_SALES.INCREDIENTS));
bean.setProvider(r.get(T_SALES.PROVIDER));
bean.setRecipenote(r.get(T_SALES.RECIPENOTE));
bean.setRecipenumber(r.get(T_SALES.RECIPENUMBER));
bean.setTrader(r.get(T_SALES.TRADER));
return bean;
}
}
public void deleteBeanIfAllowedFor(String username, Integer id) {
DeleteConditionStep<TSalesRecord> sql = jooq
// @formatter:off
.deleteFrom(T_SALES)
.where(T_SALES.PROVIDER.eq(username))
.and(T_SALES.PK.eq(id));
// @formatter:off
LOGGER.trace(sql);
sql.execute();
}
}

View File

@ -0,0 +1,57 @@
package de.jottyfan.camporganizer.module.business.outlay;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.business.outlay.model.CampBean;
import de.jottyfan.camporganizer.module.business.outlay.model.OutlayBean;
import jakarta.validation.Valid;
/**
*
* @author jotty
*
*/
@Service
public class OutlayService {
@Autowired
private OutlayRepository repository;
public List<OutlayBean> getListOf(String username, Integer campId) {
return repository.getListOf(username, campId);
}
public List<CampBean> getAllCamps() {
return repository.getAllCamps();
}
public void save(@Valid OutlayBean bean) {
if (bean.getId() != null) {
repository.updateBean(bean);
} else {
repository.addBean(bean);
}
}
public OutlayBean getBeanIfAllowedFor(String username, Integer id) {
return repository.getBeanIfAllowedFor(username, id);
}
public void deleteIfAllowedFor(String username, Integer id) {
repository.deleteBeanIfAllowedFor(username, id);
}
public InputStream getCsv(Integer campId) {
List<OutlayBean> list = repository.getListOf(null, campId);
StringBuilder buf = new StringBuilder("Beleg-Nummer;Einkauf bei;Freizeit;bezahlt von;Betrag;Bestandteile;Rechnungsdatum\n");
for (OutlayBean bean : list) {
buf.append(bean.toCsvLine());
}
return new ByteArrayInputStream(buf.toString().getBytes());
}
}

View File

@ -0,0 +1,51 @@
package de.jottyfan.camporganizer.module.business.outlay.model;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class CampBean implements Serializable {
private static final long serialVersionUID = 1L;
private final Integer id;
private String campname;
private CampBean(Integer id) {
super();
this.id = id;
}
public static final CampBean of(Integer id) {
return new CampBean(id);
}
public CampBean withCampname(String campname) {
this.campname = campname;
return this;
}
/**
* @return the campname
*/
public String getCampname() {
return campname;
}
/**
* @param campname the campname to set
*/
public void setCampname(String campname) {
this.campname = campname;
}
/**
* @return the id
*/
public Integer getId() {
return id;
}
}

View File

@ -0,0 +1,202 @@
package de.jottyfan.camporganizer.module.business.outlay.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.time.LocalDateTime;
import java.util.Locale;
import org.springframework.format.annotation.DateTimeFormat;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
*
* @author jotty
*
*/
public class OutlayBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
@NotBlank
private String trader;
@NotNull
private Integer fkCamp;
private String campname;
private String provider;
@NotNull
private BigDecimal cash;
@DateTimeFormat(pattern = "yyyy-MM-dd'T'hh:mm:ss")
private LocalDateTime buydate;
private String recipenumber;
private String recipenote;
private String ingredients;
public OutlayBean withUser(String provider) {
this.provider = provider;
return this;
}
private static final String quoted(String s) {
return s == null ? "" : String.format("\"%s\"", s.replace("\"", "'"));
}
private static final String cashed(BigDecimal money) {
return money == null ? "" : String.format("%s €", NumberFormat.getNumberInstance(Locale.GERMAN).format(money));
}
public String toCsvLine() {
StringBuilder buf = new StringBuilder();
buf.append(recipenumber).append(";");
buf.append(quoted(trader)).append(";");
buf.append(quoted(campname)).append(";");
buf.append(quoted(provider)).append(";");
buf.append(cashed(cash)).append(";");
buf.append(quoted(ingredients)).append(";");
buf.append(buydate).append("\n");
return buf.toString();
}
/**
* @return the id
*/
public Integer getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Integer id) {
this.id = id;
}
/**
* @return the trader
*/
public String getTrader() {
return trader;
}
/**
* @param trader the trader to set
*/
public void setTrader(String trader) {
this.trader = trader;
}
/**
* @return the campname
*/
public String getCampname() {
return campname;
}
/**
* @param campname the campname to set
*/
public void setCampname(String campname) {
this.campname = campname;
}
/**
* @return the cash
*/
public BigDecimal getCash() {
return cash;
}
/**
* @param cash the cash to set
*/
public void setCash(BigDecimal cash) {
this.cash = cash;
}
/**
* @return the buydate
*/
public LocalDateTime getBuydate() {
return buydate;
}
/**
* @param buydate the buydate to set
*/
public void setBuydate(LocalDateTime buydate) {
this.buydate = buydate;
}
/**
* @return the provider
*/
public String getProvider() {
return provider;
}
/**
* @param provider the provider to set
*/
public void setProvider(String provider) {
this.provider = provider;
}
/**
* @return the recipenumber
*/
public String getRecipenumber() {
return recipenumber;
}
/**
* @param recipenumber the recipenumber to set
*/
public void setRecipenumber(String recipenumber) {
this.recipenumber = recipenumber;
}
/**
* @return the recipenote
*/
public String getRecipenote() {
return recipenote;
}
/**
* @param recipenote the recipenote to set
*/
public void setRecipenote(String recipenote) {
this.recipenote = recipenote;
}
/**
* @return the ingredients
*/
public String getIngredients() {
return ingredients;
}
/**
* @param ingredients the ingredients to set
*/
public void setIngredients(String ingredients) {
this.ingredients = ingredients;
}
/**
* @return the fkCamp
*/
public Integer getFkCamp() {
return fkCamp;
}
/**
* @param fkCamp the fkCamp to set
*/
public void setFkCamp(Integer fkCamp) {
this.fkCamp = fkCamp;
}
}

View File

@ -0,0 +1,64 @@
package de.jottyfan.camporganizer.module.business.privileges;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.module.business.privileges.model.BusinessPrivilegesBean;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.Valid;
/**
*
* @author jotty
*
*/
@Controller
public class BusinessPrivilegesController extends CommonController {
@Autowired
private BusinessPrivilegesService service;
@GetMapping("/business/privileges")
@RolesAllowed({ "admin" })
public String getIndex(Model model) {
String username = super.getCurrentUser();
model.addAttribute("currentUser", username);
model.addAttribute("privileges", service.getPrivileges());
model.addAttribute("profiles", service.getProfiles(EnumCamprole.director, EnumCamprole.teacher));
model.addAttribute("bean", new BusinessPrivilegesBean());
return "business/privileges";
}
@PostMapping("/business/privileges/add")
@RolesAllowed({ "admin" })
public String getAdd(@Valid @ModelAttribute("bean") BusinessPrivilegesBean bean, BindingResult br, Model model) {
if (br.hasErrors()) {
String username = super.getCurrentUser();
model.addAttribute("currentUser", username);
model.addAttribute("privileges", service.getPrivileges());
model.addAttribute("profiles", service.getProfiles(EnumCamprole.director, EnumCamprole.teacher));
return "business/privileges";
}
service.add(bean);
return "redirect:/business/privileges";
}
@GetMapping("/business/privileges/delete")
@RolesAllowed({ "admin" })
public String getDelete(@RequestParam("fkCamp") Integer fkCamp, @RequestParam("fkProfile") Integer fkProfile,
Model model) {
BusinessPrivilegesBean bean = new BusinessPrivilegesBean();
bean.setFkCamp(fkCamp);
bean.setFkProfile(fkProfile);
service.remove(bean, super.getCurrentUser());
return "redirect:/business/privileges";
}
}

View File

@ -1,8 +1,8 @@
package de.jottyfan.camporganizer.module.business.privileges.impl;
package de.jottyfan.camporganizer.module.business.privileges;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.time.LocalDateTime;
@ -23,7 +23,10 @@ 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;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampprofileRecord;
import de.jottyfan.camporganizer.module.business.privileges.model.BusinessPrivilegesBean;
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
/**
*
@ -32,25 +35,25 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class PrivilegesRepository {
private static final Logger LOGGER = LogManager.getLogger(PrivilegesRepository.class);
public class BusinessPrivilegesRepository {
private static final Logger LOGGER = LogManager.getLogger(BusinessPrivilegesRepository.class);
@Autowired
private DSLContext jooq;
public List<PrivilegesBean> getPrivileges() {
public List<BusinessPrivilegesBean> 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))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(V_CAMP.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.orderBy(V_CAMP.ARRIVE, T_PROFILE.SURNAME, T_PROFILE.FORENAME);
// @formatter:on
LOGGER.debug(sql.toString());
List<PrivilegesBean> list = new ArrayList<>();
LOGGER.trace(sql);
List<BusinessPrivilegesBean> list = new ArrayList<>();
for (Record8<String, String, LocalDateTime, String, Integer, Integer, String, Double> r : sql.fetch()) {
PrivilegesBean bean = new PrivilegesBean();
BusinessPrivilegesBean bean = new BusinessPrivilegesBean();
bean.setCampName(r.get(V_CAMP.NAME));
bean.setCampYear(r.get(V_CAMP.YEAR));
bean.setFkCamp(r.get(V_CAMP.PK));
@ -77,7 +80,7 @@ public class PrivilegesRepository {
.where((allowed == null || allowed.size() < 1) ? DSL.trueCondition() : T_PERSON.CAMPROLE.in(allowed))
.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME, T_PROFILE.DUEDATE);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<ProfileBean> list = new ArrayList<>();
for (Record5<Integer, String, String, LocalDateTime, String> r : sql.fetch()) {
ProfileBean bean = new ProfileBean();
@ -91,30 +94,31 @@ public class PrivilegesRepository {
return list;
}
public Integer add(PrivilegesBean bean) {
InsertReturningStep<TSalesprofileRecord> sql = jooq
public Integer add(BusinessPrivilegesBean bean) {
InsertReturningStep<TCampprofileRecord> 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)
.insertInto(T_CAMPPROFILE, T_CAMPPROFILE.FK_CAMP, T_CAMPPROFILE.FK_PROFILE, T_CAMPPROFILE.MODULE)
.values(bean.getFkCamp(), bean.getFkProfile(), EnumModule.business)
.onConflict(T_CAMPPROFILE.FK_CAMP, T_CAMPPROFILE.FK_PROFILE, T_CAMPPROFILE.MODULE)
.doNothing();
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.execute();
}
public Integer remove(PrivilegesBean bean, String currentUser) {
DeleteConditionStep<TSalesprofileRecord> sql = jooq
public Integer remove(BusinessPrivilegesBean bean, String currentUser) {
DeleteConditionStep<TCampprofileRecord> 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
.deleteFrom(T_CAMPPROFILE)
.where(T_CAMPPROFILE.MODULE.eq(EnumModule.business))
.and(T_CAMPPROFILE.FK_CAMP.eq(bean.getFkCamp()))
.and(T_CAMPPROFILE.FK_PROFILE.eq(bean.getFkProfile()))
.and(T_CAMPPROFILE.FK_PROFILE.notIn(jooq
.select(T_PROFILE.PK)
.from(T_PROFILE)
.where(T_PROFILE.USERNAME.eq(currentUser))));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.execute();
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.privileges.impl;
package de.jottyfan.camporganizer.module.business.privileges;
import java.util.HashMap;
import java.util.HashSet;
@ -10,7 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.module.business.camp.impl.CampBean;
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
import de.jottyfan.camporganizer.module.business.privileges.model.BusinessPrivilegesBean;
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
/**
*
@ -18,14 +20,14 @@ import de.jottyfan.camporganizer.module.business.camp.impl.CampBean;
*
*/
@Service
public class PrivilegesService {
public class BusinessPrivilegesService {
@Autowired
private PrivilegesRepository gateway;
private BusinessPrivilegesRepository gateway;
public Map<Integer, CampBean> getPrivileges() {
List<PrivilegesBean> list = gateway.getPrivileges();
List<BusinessPrivilegesBean> list = gateway.getPrivileges();
Map<Integer, CampBean> camps = new HashMap<>();
for (PrivilegesBean bean : list) {
for (BusinessPrivilegesBean bean : list) {
CampBean campBean = camps.get(bean.getFkCamp());
if (campBean == null) {
campBean = new CampBean();
@ -53,11 +55,11 @@ public class PrivilegesService {
return gateway.getProfiles(allowed == null ? null : set);
}
public void add(PrivilegesBean bean) {
public void add(BusinessPrivilegesBean bean) {
gateway.add(bean);
}
public void remove(PrivilegesBean bean, String currentUser) {
public void remove(BusinessPrivilegesBean bean, String currentUser) {
gateway.remove(bean, currentUser);
}
}

View File

@ -1,65 +0,0 @@
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.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.module.business.business.IBusinessService;
import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesBean;
import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesService;
import de.jottyfan.camporganizer.module.camplist.CommonController;
/**
*
* @author jotty
*
*/
@Controller
public class PrivilegesController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private PrivilegesService 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(EnumCamprole.director, EnumCamprole.teacher));
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);
}
}

View File

@ -1,21 +1,25 @@
package de.jottyfan.camporganizer.module.business.privileges.impl;
package de.jottyfan.camporganizer.module.business.privileges.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import jakarta.validation.constraints.NotNull;
/**
*
* @author jotty
*
*/
public class PrivilegesBean implements Serializable {
public class BusinessPrivilegesBean implements Serializable {
private static final long serialVersionUID = 1L;
private String forename;
private String surname;
private String username;
private LocalDateTime duedate;
@NotNull
private Integer fkProfile;
@NotNull
private Integer fkCamp;
private String campName;
private Double campYear;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.business.privileges.impl;
package de.jottyfan.camporganizer.module.business.privileges.model;
import java.io.Serializable;
import java.time.LocalDateTime;

View File

@ -1,7 +1,6 @@
package de.jottyfan.camporganizer.module.camplist;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -12,7 +11,9 @@ 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.registration.KeycloakRepository;
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
/**
*
@ -23,32 +24,25 @@ import de.jottyfan.camporganizer.module.registration.KeycloakRepository;
public class CamplistController extends CommonController {
private static final Logger LOGGER = LogManager.getLogger(CamplistController.class);
@Autowired
private HttpServletRequest request;
@Autowired
private KeycloakRepository keycloak;
@Autowired
private CamplistService service;
@GetMapping("/camplist")
public String index(Model model) {
public String index(Model model, Principal principal) {
model.addAttribute("camps", service.getAllCamps(true));
return super.isLoggedIn(request) ? dashboard(model) : "/camplist";
return super.isLoggedIn(principal) ? dashboard(model) : "/camplist";
}
@GetMapping("/dashboard")
public String dashboard(Model model) {
model.addAttribute("mybookings", service.getBookingsOf(super.getCurrentUser(request)));
model.addAttribute("mybookings", service.getBookingsOf(super.getCurrentUser()));
model.addAttribute("bookingBean", new BookingBean());
model.addAttribute("keycloakProfileUrl", keycloak.getUserClientUrl());
model.addAttribute("camps", service.getAllCamps(true));
return "/dashboard";
}
@PostMapping("/dashboard/update")
public String updateBooking(Model model, @ModelAttribute BookingBean bean) {
public String updateBooking(Model model, @ModelAttribute("b") BookingBean bean) {
service.update(bean);
return dashboard(model);
}

View File

@ -12,6 +12,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -26,14 +27,18 @@ import org.jooq.Record2;
import org.jooq.SelectOrderByStep;
import org.jooq.SelectSeekStep1;
import org.jooq.SelectSeekStep2;
import org.jooq.impl.DSL;
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.EnumDocument;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.tables.TProfile;
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
import de.jottyfan.camporganizer.module.camplist.model.DocumentBean;
/**
*
@ -42,15 +47,15 @@ import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
*/
@Repository
@Transactional(transactionManager = "transactionManager")
public class CamplistGateway {
private static final Logger LOGGER = LogManager.getLogger(CamplistGateway.class);
public class CamplistRepository {
private static final Logger LOGGER = LogManager.getLogger(CamplistRepository.class);
@Autowired
private DSLContext jooq;
public Stream<VCampRecord> getAllCamps(Condition condition) {
SelectSeekStep1<VCampRecord, LocalDateTime> sql = jooq.selectFrom(V_CAMP).where(condition).orderBy(V_CAMP.ARRIVE);
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.fetchStream();
}
@ -72,7 +77,7 @@ public class CamplistGateway {
T_PERSON.CREATED,
T_PERSON.EMAIL,
T_PERSON.SEX,
T_PERSON.ACCEPT,
T_PERSON.PROGRESS,
T_PERSON.FK_CAMP,
T_PROFILE.FORENAME,
T_PROFILE.SURNAME,
@ -91,15 +96,19 @@ public class CamplistGateway {
.leftJoin(T_PERSON).on(T_PERSON.FK_PROFILE.eq(T_PROFILE.PK))
.leftJoin(REGISTRATOR).on(REGISTRATOR.PK.eq(T_PERSON.FK_REGISTRATOR))
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP))
.where(T_PROFILE.USERNAME.eq(username))
.where(DSL.trim(T_PROFILE.USERNAME).eq(username == null ? null : username.trim()))
.and(T_PERSON.PK.isNotNull())
.orderBy(V_CAMP.ARRIVE.desc(), T_PERSON.CREATED);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<BookingBean> list = new ArrayList<>();
for (Record r : sql.fetch()) {
Iterator<Record> i = sql.fetch().iterator();
while (i.hasNext()) {
Record r = i.next();
Integer fkCamp = r.get(T_PERSON.FK_CAMP);
BookingBean bean = new BookingBean();
EnumProgress progress = r.get(T_PERSON.PROGRESS);
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setPk(r.get(T_PERSON.PK));
bean.setForename(r.get(T_PERSON.FORENAME));
bean.setSurname(r.get(T_PERSON.SURNAME));
@ -123,7 +132,6 @@ public class CamplistGateway {
bean.setUrl(r.get(V_CAMP.URL));
bean.setIsOver(r.get(V_CAMP.IS_OVER));
bean.setCampName(r.get(V_CAMP.NAME));
bean.setAccept(r.get(T_PERSON.ACCEPT));
StringBuilder buf = new StringBuilder();
String forename = r.get(REGISTRATOR.FORENAME);
String surname = r.get(REGISTRATOR.SURNAME);
@ -179,9 +187,11 @@ public class CamplistGateway {
.from(T_DOCUMENT)
.where(T_DOCUMENT.DOCTYPE.eq(EnumDocument.camppass)));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
Map<Integer, String> map = new HashMap<>(); // no duplicate on using a map
for (Record r : sql.fetch()) {
Iterator<Record2<String, Integer>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record2<String, Integer> r = i.next();
map.put(r.get(T_DOCUMENT.PK), r.get(T_DOCUMENT.NAME));
}
List<DocumentBean> list = new ArrayList<>();

View File

@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
import de.jottyfan.camporganizer.module.dashboard.DashboardRepository;
/**
@ -24,7 +25,7 @@ import de.jottyfan.camporganizer.module.dashboard.DashboardRepository;
public class CamplistService {
@Autowired
private CamplistGateway gateway;
private CamplistRepository gateway;
@Autowired
private DashboardRepository dashboardGateway;

View File

@ -1,57 +1,92 @@
package de.jottyfan.camporganizer.module.camplist;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import org.keycloak.KeycloakSecurityContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.ModelAttribute;
import de.jottyfan.camporganizer.module.registration.KeycloakRepository;
/**
*
* @author jotty
*
*/
public abstract class CommonController {
private static final Logger LOGGER = LogManager.getLogger();
@Autowired
private HttpServletRequest request;
private KeycloakRepository keycloak;
/**
* try to get current keycloak user
*
* @param request the request
* @param principal the principal
* @return the preferred username or null
*/
public String getCurrentUser(HttpServletRequest request) {
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
.getAttribute(KeycloakSecurityContext.class.getName());
return ksc == null ? null : ksc.getIdToken().getPreferredUsername();
public String getCurrentUser(Principal principal) {
return principal == null ? null : principal.getName();
}
/**
* try to get th currnt keycloak email
*
* @param request the request
* @param principal the principal
* @return the email or null
*/
public String getCurrentEmail(HttpServletRequest request) {
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
.getAttribute(KeycloakSecurityContext.class.getName());
return ksc == null ? null : ksc.getIdToken().getEmail();
public String getCurrentEmail(Principal principal) {
if (principal instanceof OAuth2AuthenticationToken) {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
if (token != null) {
OAuth2User user = token.getPrincipal();
if (user != null) {
return user.getAttribute("email");
}
}
} else {
LOGGER.error("could not find email for {}", principal);
}
return null;
}
@ModelAttribute("currentUser")
public String getCurrentUser() {
return getCurrentUser(request);
SecurityContext context = SecurityContextHolder.getContext();
if (context != null) {
Authentication authentication = context.getAuthentication();
if (authentication != null) {
DefaultOidcUser dou = (DefaultOidcUser) authentication.getPrincipal();
return dou == null ? null : dou.getName();
}
}
return null;
}
@ModelAttribute("keycloakProfileUrl")
public String getKeycloakProfileUrl() {
return keycloak.getUserClientUrl();
}
@ModelAttribute("keycloakPasswordUrl")
public String getKeycloakPasswordUrl() {
return keycloak.getPasswordClientUrl();
}
/**
* return true if the user has a valid keycloak session token
*
* @param request the request
* @param principal the principal
* @return true or false
*/
public boolean isLoggedIn(HttpServletRequest request) {
return getCurrentUser(request) != null;
public boolean isLoggedIn(Principal principal) {
return getCurrentUser(principal) != null;
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.camplist;
package de.jottyfan.camporganizer.module.camplist.model;
import java.io.Serializable;
import java.time.LocalDate;
@ -41,7 +41,7 @@ public class BookingBean implements Serializable {
private Boolean isOver;
private String campName;
private String registrator;
private Boolean accept;
private String progress;
private String subscriber;
private List<DocumentBean> documents;
@ -396,14 +396,6 @@ public class BookingBean implements Serializable {
this.registrator = registrator;
}
public Boolean getAccept() {
return accept;
}
public void setAccept(Boolean accept) {
this.accept = accept;
}
public String getSubscriber() {
return subscriber;
}
@ -416,4 +408,18 @@ public class BookingBean implements Serializable {
return documents;
}
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.camplist;
package de.jottyfan.camporganizer.module.camplist.model;
import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.camplist;
package de.jottyfan.camporganizer.module.camplist.model;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.camplist;
package de.jottyfan.camporganizer.module.camplist.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;

View File

@ -0,0 +1,52 @@
package de.jottyfan.camporganizer.module.confirmation.board;
import java.io.IOException;
import java.security.Principal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
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.camplist.CommonController;
import jakarta.servlet.http.HttpServletResponse;
/**
*
* @author jotty
*
*/
@Controller
public class ConfirmationBoardController extends CommonController {
@Autowired
private ConfirmationBoardService service;
@GetMapping("/confirmation/board")
public String getBoard(Model model, Principal principal) {
model.addAttribute("camps", service.loadCampList(super.getCurrentUser(principal)));
return "/confirmation/board";
}
@GetMapping("/confirmation/board/camp/{id}")
public String getCamplist(Model model, @PathVariable("id") Integer id, Principal principal) {
model.addAttribute("campId", id);
model.addAttribute("campStartDate", service.getCampStartDate(super.getCurrentUser(principal), id));
model.addAttribute("persons", service.loadPersonList(super.getCurrentUser(principal), id));
return "/confirmation/camplist";
}
@GetMapping("/confirmation/board/download/{id}")
public void getCsvOfAll(@PathVariable("id") Integer id, Principal principal, HttpServletResponse response)
throws IOException {
response.setContentType("text/csv");
String filename = String.format("camplist_%d_%s.csv", id,
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")));
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
response.getWriter().write(service.getDownloadCsvOfAll(super.getCurrentUser(principal), id));
response.flushBuffer();
}
}

View File

@ -0,0 +1,142 @@
package de.jottyfan.camporganizer.module.confirmation.board;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
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.V_CAMP;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
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.Record2;
import org.jooq.Record6;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import de.jottyfan.camporganizer.module.confirmation.board.model.CampBean;
import de.jottyfan.camporganizer.module.confirmation.board.model.PersonBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.ConfirmationRepository;
/**
*
* @author jotty
*
*/
@Repository
public class ConfirmationBoardRepository {
private static final Logger LOGGER = LogManager.getLogger(ConfirmationRepository.class);
@Autowired
private DSLContext jooq;
/**
* get a list of camps that the user has access to
*
* @param username the username
* @return the list of camps; might be an empty list
*/
public List<CampBean> getCamps(String username) {
SelectSeekStep1<Record6<String, Double, Boolean, String, Integer, LocalDateTime>, LocalDateTime> sql = jooq
// @formatter:off
.select(V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.IS_OVER, V_CAMP.LOCATION_NAME, V_CAMP.PK, V_CAMP.ARRIVE)
.from(T_PROFILE)
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_PROFILE.eq(T_PROFILE.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
.where(T_PROFILE.USERNAME.eq(username))
.orderBy(V_CAMP.ARRIVE);
// @formatter:on
LOGGER.trace(sql);
List<CampBean> list = new ArrayList<>();
Iterator<Record6<String, Double, Boolean, String, Integer, LocalDateTime>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record6<String, Double, Boolean, String, Integer, LocalDateTime> r = i.next();
CampBean bean = new CampBean();
bean.setPkCamp(r.get(V_CAMP.PK));
bean.setName(r.get(V_CAMP.NAME));
bean.setYear(r.get(V_CAMP.YEAR));
bean.setLocationName(r.get(V_CAMP.LOCATION_NAME));
bean.setIsOver(r.get(V_CAMP.IS_OVER));
list.add(bean);
}
return list;
}
/**
* get the list of persons for this camp; restrict by the user privilege
*
* @param username the user that needs access to this data
* @param campId the ID of the camp
* @return the list of persons; an empty list at least
*/
public List<PersonBean> getPersons(String username, Integer campId) {
SelectConditionStep<Record> sql = jooq
// @formatter:off
.select(T_PERSON.fields())
.from(T_PERSON)
.innerJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.innerJoin(T_PROFILE).on(T_PROFILE.USERNAME.eq(username)).and(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
.where(T_PERSON.FK_CAMP.eq(campId));
// @formatter:on
LOGGER.trace(sql);
List<PersonBean> list = new ArrayList<>();
Iterator<Record> i = sql.fetch().iterator();
while (i.hasNext()) {
Record r = i.next();
PersonBean bean = new PersonBean();
EnumProgress progress = r.get(T_PERSON.PROGRESS);
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setBirthDate(r.get(T_PERSON.BIRTHDATE));
bean.setCamprole(r.get(T_PERSON.CAMPROLE) == null ? null : r.get(T_PERSON.CAMPROLE).getLiteral());
bean.setCity(r.get(T_PERSON.CITY));
bean.setComment(r.get(T_PERSON.COMMENT));
bean.setConsentCatalogPhoto(r.get(T_PERSON.CONSENT_CATALOG_PHOTO));
bean.setCreated(r.get(T_PERSON.CREATED));
bean.setEmail(r.get(T_PERSON.EMAIL));
bean.setForename(r.get(T_PERSON.FORENAME));
bean.setPaid(r.get(T_PERSON.PAID) == null ? null : r.get(T_PERSON.PAID).doubleValue());
bean.setPhone(r.get(T_PERSON.PHONE));
bean.setSex(r.get(T_PERSON.SEX) == null ? null : (r.get(T_PERSON.SEX).equals(EnumSex.male) ? "männlich" : "weiblich"));
bean.setStreet(r.get(T_PERSON.STREET));
bean.setSurname(r.get(T_PERSON.SURNAME));
bean.setZip(r.get(T_PERSON.ZIP));
list.add(bean);
}
return list;
}
/**
* get the camp start date of campId if username is allowed to
*
* @param username the user
* @param campId the ID of the camp
* @return the camp start time or null
*/
public LocalDateTime getCampStartDate(String username, Integer campId) {
SelectConditionStep<Record2<String, LocalDateTime>> sql = jooq
// @formatter:off
.select(V_CAMP.NAME, V_CAMP.ARRIVE)
.from(T_PROFILE)
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_PROFILE.eq(T_PROFILE.PK)).and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
.where(T_PROFILE.USERNAME.eq(username))
.and(V_CAMP.PK.eq(campId));
// @formatter:on
LOGGER.trace(sql);
Iterator<Record2<String, LocalDateTime>> i = sql.fetch().iterator();
while (i.hasNext()) {
return i.next().get(V_CAMP.ARRIVE);
}
return null;
}
}

View File

@ -0,0 +1,41 @@
package de.jottyfan.camporganizer.module.confirmation.board;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.confirmation.board.model.CampBean;
import de.jottyfan.camporganizer.module.confirmation.board.model.PersonBean;
/**
*
* @author jotty
*
*/
@Service
public class ConfirmationBoardService {
@Autowired
private ConfirmationBoardRepository repository;
@Autowired
private List2CSVService csvService;
public List<CampBean> loadCampList(String username) {
return repository.getCamps(username);
}
public List<PersonBean> loadPersonList(String username, Integer campId) {
return repository.getPersons(username, campId);
}
public String getDownloadCsvOfAll(String username, Integer campId) {
List<PersonBean> list = repository.getPersons(username, campId);
return csvService.toCsv(list);
}
public Object getCampStartDate(String username, Integer campId) {
return repository.getCampStartDate(username, campId);
}
}

View File

@ -0,0 +1,73 @@
package de.jottyfan.camporganizer.module.confirmation.board;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.module.confirmation.board.model.PersonBean;
/**
*
* @author jotty
*
*/
@Service
public class List2CSVService {
private static final String QUOTE = "\"";
private static final String SEP = ";";
private StringBuilder append(StringBuilder buf, String s) {
return buf.append(s == null || s.isEmpty() ? SEP : String.format("%s%s%s%s", QUOTE, s, QUOTE, SEP));
}
private StringBuilder append(StringBuilder buf, Double d) {
return buf.append(d == null ? SEP : new Formatter(Locale.GERMAN).format("%.2f%s", d, SEP));
}
private StringBuilder append(StringBuilder buf, Boolean b) {
return buf.append(b == null ? SEP : String.format("%s%s%s%s", QUOTE, b ? "ja" : "nein", QUOTE, SEP));
}
private StringBuilder append(StringBuilder buf, LocalDateTime l) {
return buf.append(l == null ? SEP
: String.format("%s%s%s%s", QUOTE, l.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")), QUOTE, SEP));
}
private StringBuilder append(StringBuilder buf, LocalDate l) {
return buf.append(l == null ? SEP
: String.format("%s%s%s%s", QUOTE, l.format(DateTimeFormatter.ofPattern("dd.MM.yyyy")), QUOTE, SEP));
}
public String toCsv(List<PersonBean> list) {
StringBuilder buf = new StringBuilder();
String title = String.format(
"Bezahlt%sVorname%sNachname%sStrasse%sPLZ%sOrt%sTelefon%sEmail%sGeschlecht%sRolle%sGeburtsdatum%sAnmeldestatus%sAnmeldedatum%sFotoeinverständnis%sKommentar\n",
SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP, SEP);
buf.append(title);
for (PersonBean bean : list) {
append(buf, bean.getPaid());
append(buf, bean.getForename());
append(buf, bean.getSurname());
append(buf, bean.getStreet());
append(buf, bean.getZip());
append(buf, bean.getCity());
append(buf, bean.getPhone());
append(buf, bean.getEmail());
append(buf, bean.getSex());
append(buf, bean.getCamprolle());
append(buf, bean.getBirthDate());
append(buf, bean.getProgress());
append(buf, bean.getCreated());
append(buf, bean.getConsentCatalogPhoto());
append(buf, bean.getComment());
buf.append("\n");
}
return buf.toString();
}
}

View File

@ -0,0 +1,91 @@
package de.jottyfan.camporganizer.module.confirmation.board.model;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class CampBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer pkCamp;
private String name;
private Double year;
private String locationName;
private Boolean isOver;
public String getTitle() {
return String.format("%s %4.0f", name, year);
}
/**
* @return the pkCamp
*/
public Integer getPkCamp() {
return pkCamp;
}
/**
* @param pkCamp the pkCamp to set
*/
public void setPkCamp(Integer pkCamp) {
this.pkCamp = pkCamp;
}
/**
* @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 locationName
*/
public String getLocationName() {
return locationName;
}
/**
* @param locationName the locationName to set
*/
public void setLocationName(String locationName) {
this.locationName = locationName;
}
/**
* @return the isOver
*/
public Boolean getIsOver() {
return isOver;
}
/**
* @param isOver the isOver to set
*/
public void setIsOver(Boolean isOver) {
this.isOver = isOver;
}
}

View File

@ -0,0 +1,267 @@
package de.jottyfan.camporganizer.module.confirmation.board.model;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
/**
*
* @author jotty
*
*/
public class PersonBean implements Serializable {
private static final long serialVersionUID = 1L;
private String forename;
private String surname;
private String street;
private String zip;
private String city;
private String phone;
private String email;
private LocalDate birthDate;
private String camprole;
private String progress;
private LocalDateTime created;
private String sex;
private Double paid;
private String comment;
private Boolean consentCatalogPhoto;
public String getAge(LocalDate relation) {
if (relation == null) {
return "?";
} else {
Period period = Period.between(birthDate, relation);
Integer years = period == null ? null : period.getYears();
return years == null ? "?" : years.toString();
}
}
public String getCamprolle() {
if ("student".equals(camprole)) {
return "Teilnehmer";
} else if ("teacher".equals(camprole)) {
return "Mitarbeiter";
} else if ("director".equals(camprole)) {
return "Leitung";
} else if ("feeder".equals(camprole)) {
return "Küche";
} else if ("observer".equals(camprole)) {
return "Mitarbeiterkind";
} else {
return null;
}
}
/**
* @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 street
*/
public String getStreet() {
return street;
}
/**
* @param street the street to set
*/
public void setStreet(String street) {
this.street = street;
}
/**
* @return the zip
*/
public String getZip() {
return zip;
}
/**
* @param zip the zip to set
*/
public void setZip(String zip) {
this.zip = zip;
}
/**
* @return the city
*/
public String getCity() {
return city;
}
/**
* @param city the city to set
*/
public void setCity(String city) {
this.city = city;
}
/**
* @return the phone
*/
public String getPhone() {
return phone;
}
/**
* @param phone the phone to set
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* @return the birthDate
*/
public LocalDate getBirthDate() {
return birthDate;
}
/**
* @param birthDate the birthDate to set
*/
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
/**
* @return the camprole
*/
public String getCamprole() {
return camprole;
}
/**
* @param camprole the camprole to set
*/
public void setCamprole(String camprole) {
this.camprole = camprole;
}
/**
* @return the created
*/
public LocalDateTime getCreated() {
return created;
}
/**
* @param created the created to set
*/
public void setCreated(LocalDateTime created) {
this.created = created;
}
/**
* @return the sex
*/
public String getSex() {
return sex;
}
/**
* @param sex the sex to set
*/
public void setSex(String sex) {
this.sex = sex;
}
/**
* @return the paid
*/
public Double getPaid() {
return paid;
}
/**
* @param paid the paid to set
*/
public void setPaid(Double paid) {
this.paid = paid;
}
/**
* @return the comment
*/
public String getComment() {
return comment;
}
/**
* @param comment the comment to set
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* @return the consentCatalogPhoto
*/
public Boolean getConsentCatalogPhoto() {
return consentCatalogPhoto;
}
/**
* @param consentCatalogPhoto the consentCatalogPhoto to set
*/
public void setConsentCatalogPhoto(Boolean consentCatalogPhoto) {
this.consentCatalogPhoto = consentCatalogPhoto;
}
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -3,15 +3,14 @@ package de.jottyfan.camporganizer.module.confirmation.confirmation;
import java.time.LocalDate;
import java.util.List;
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.camplist.CommonController;
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverviewBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
/**
*
@ -22,25 +21,32 @@ import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverv
public class ConfirmationController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private IConfirmationService indexService;
private ConfirmationService service;
@GetMapping("/confirmation")
public String getIndex(Model model) {
List<CampOverviewBean> campoverview = indexService.getCampOverview(request);
List<CampOverviewBean> campoverview = service.getCampOverview(super.getCurrentUser());
CampOverviewBean campoverviewsummary = new CampOverviewBean(LocalDate.now(), "summary");
for (CampOverviewBean bean : campoverview) {
campoverviewsummary.setApproved(bean.getApproved() + campoverviewsummary.getApproved());
campoverviewsummary.setRejected(bean.getRejected() + campoverviewsummary.getRejected());
campoverviewsummary.setUntouched(bean.getUntouched() + campoverviewsummary.getUntouched());
campoverviewsummary.setRevoked(bean.getRevoked() + campoverviewsummary.getRevoked());
}
model.addAttribute("campoverview", campoverview);
model.addAttribute("campoverviewsummary", campoverviewsummary);
model.addAttribute("untouched", indexService.getUntouched(request));
model.addAttribute("approved", indexService.getApproved(request));
model.addAttribute("rejected", indexService.getRejected(request));
model.addAttribute("untouched", service.getUntouched(super.getCurrentUser()));
model.addAttribute("approved", service.getApproved(super.getCurrentUser()));
model.addAttribute("rejected", service.getRejected(super.getCurrentUser()));
model.addAttribute("revoked", service.getRevoked(super.getCurrentUser()));
return "confirmation/confirmation";
}
@GetMapping("/registration/remove/{id}")
public String revoke(@PathVariable("id") Integer id, final Model model) {
service.removeBooking(id);
return "redirect:/confirmation";
}
}

View File

@ -1,15 +1,19 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
package de.jottyfan.camporganizer.module.confirmation.confirmation;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSONDOCUMENT;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_RSS;
import static de.jottyfan.camporganizer.db.jooq.Tables.V_CAMP;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -17,12 +21,17 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jooq.Condition;
import org.jooq.DSLContext;
import org.jooq.DeleteConditionStep;
import org.jooq.InsertValuesStep2;
import org.jooq.Name;
import org.jooq.Record4;
import org.jooq.Record5;
import org.jooq.Record7;
import org.jooq.Record8;
import org.jooq.SelectConditionStep;
import org.jooq.SelectHavingStep;
import org.jooq.SelectSeekStep1;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@ -30,6 +39,13 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersondocumentRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord;
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.BookingBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
/**
*
@ -52,10 +68,10 @@ public class ConfirmationRepository {
*/
public List<CampOverviewBean> getCampOverviewBeans(String currentUser) {
Name COUNT = DSL.name("count");
SelectHavingStep<Record4<Integer, Boolean, String, LocalDateTime>> sql = jooq
SelectHavingStep<Record4<Integer, EnumProgress, String, LocalDateTime>> sql = jooq
// @formatter:off
.select(DSL.count(T_PERSON.PK).as(COUNT),
T_PERSON.ACCEPT,
T_PERSON.PROGRESS,
T_CAMP.NAME,
T_CAMP.ARRIVE)
.from(T_PERSON)
@ -65,13 +81,15 @@ public class ConfirmationRepository {
.where(T_CAMP.ARRIVE.isNotNull())
.and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.and(T_PROFILE.USERNAME.eq(currentUser))
.groupBy(T_CAMP.NAME, T_CAMP.ARRIVE, T_PERSON.ACCEPT);
.groupBy(T_CAMP.NAME, T_CAMP.ARRIVE, T_PERSON.PROGRESS);
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
Map<LocalDateTime, CampOverviewBean> map = new HashMap<>();
for (Record4<Integer, Boolean, String, LocalDateTime> r : sql.fetch()) {
Iterator<Record4<Integer, EnumProgress, String, LocalDateTime>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, EnumProgress, String, LocalDateTime> r = i.next();
Integer count = r.get(COUNT, Integer.class);
Boolean accept = r.get(T_PERSON.ACCEPT);
EnumProgress progress = r.get(T_PERSON.PROGRESS);
String campname = r.get(T_CAMP.NAME);
LocalDateTime arrive = r.get(T_CAMP.ARRIVE);
CampOverviewBean bean = map.get(arrive);
@ -79,12 +97,14 @@ public class ConfirmationRepository {
bean = new CampOverviewBean(arrive.toLocalDate(), campname);
map.put(arrive, bean);
}
if (accept == null) {
if (progress == null || EnumProgress.requested.equals(progress)) {
bean.setUntouched(count);
} else if (accept) {
} else if (EnumProgress.approved.equals(progress)) {
bean.setApproved(count);
} else {
} else if (EnumProgress.rejected.equals(progress)) {
bean.setRejected(count);
} else if (EnumProgress.revoked.equals(progress)) {
bean.setRevoked(count);
}
}
List<CampOverviewBean> list = new ArrayList<>(map.values());
@ -112,9 +132,11 @@ public class ConfirmationRepository {
.and(T_PROFILE.USERNAME.eq(currentUser))
.orderBy(T_PERSON.CREATED.desc());
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<BookingBean> list = new ArrayList<>();
for (Record7<Integer, String, String, String, LocalDateTime, EnumCamprole, LocalDateTime> r : sql.fetch()) {
Iterator<Record7<Integer, String, String, String, LocalDateTime, EnumCamprole, LocalDateTime>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record7<Integer, String, String, String, LocalDateTime, EnumCamprole, LocalDateTime> r = i.next();
String forename = r.get(T_PERSON.FORENAME);
String surname = r.get(T_PERSON.SURNAME);
String campname = r.get(T_CAMP.NAME);
@ -138,7 +160,7 @@ public class ConfirmationRepository {
* @return a list of booking beans; an empty one at least
*/
public List<BookingBean> getUntouched(String currentUser) {
return getListWithCondition(currentUser, T_PERSON.ACCEPT.isNull());
return getListWithCondition(currentUser, T_PERSON.PROGRESS.eq(EnumProgress.requested));
}
/**
@ -148,7 +170,7 @@ public class ConfirmationRepository {
* @return a list of booking beans; an empty one at least
*/
public List<BookingBean> getApproved(String currentUser) {
return getListWithCondition(currentUser, T_PERSON.ACCEPT.isTrue());
return getListWithCondition(currentUser, T_PERSON.PROGRESS.eq(EnumProgress.approved));
}
/**
@ -158,7 +180,17 @@ public class ConfirmationRepository {
* @return a list of booking beans; an empty one at least
*/
public List<BookingBean> getRejected(String currentUser) {
return getListWithCondition(currentUser, T_PERSON.ACCEPT.isFalse());
return getListWithCondition(currentUser, T_PERSON.PROGRESS.eq(EnumProgress.rejected));
}
/**
* get all revoked bookings that this user can manage
*
* @param currentUser the current user
* @return a list of booking beans; an empty one at least
*/
public List<BookingBean> getRevoked(String currentUser) {
return getListWithCondition(currentUser, T_PERSON.PROGRESS.eq(EnumProgress.revoked));
}
/**
@ -176,9 +208,9 @@ public class ConfirmationRepository {
.or(V_CAMP.YEAR.cast(String.class).containsIgnoreCase(needle));
// @formatter:on
SelectSeekStep1<Record8<Integer, String, String, EnumCamprole, String, Double, String, Boolean>, LocalDateTime> sql = jooq
SelectSeekStep1<Record8<Integer, String, String, EnumCamprole, String, Double, String, EnumProgress>, LocalDateTime> sql = jooq
// @formatter:off
.select(T_PERSON.PK, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.LOCATION_NAME, T_PERSON.ACCEPT)
.select(T_PERSON.PK, T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.CAMPROLE, V_CAMP.NAME, V_CAMP.YEAR, V_CAMP.LOCATION_NAME, T_PERSON.PROGRESS)
.from(T_PERSON)
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP))
.leftJoin(T_CAMPPROFILE).on(T_CAMPPROFILE.FK_CAMP.eq(T_PERSON.FK_CAMP))
@ -188,22 +220,82 @@ public class ConfirmationRepository {
.and(T_PROFILE.USERNAME.eq(currentUser))
.orderBy(T_PERSON.CREATED.desc());
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<BookingBean> list = new ArrayList<>();
for (Record8<Integer, String, String, EnumCamprole, String, Double, String, Boolean> r : sql.fetch()) {
Iterator<Record8<Integer, String, String, EnumCamprole, String, Double, String, EnumProgress>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record8<Integer, String, String, EnumCamprole, String, Double, String, EnumProgress> r = i.next();
Integer pkPerson = r.get(T_PERSON.PK);
String forename = r.get(T_PERSON.FORENAME);
String surname = r.get(T_PERSON.SURNAME);
EnumCamprole role = r.get(T_PERSON.CAMPROLE);
String campname = r.get(V_CAMP.NAME);
Double year = r.get(V_CAMP.YEAR);
Boolean accept = r.get(T_PERSON.ACCEPT);
EnumProgress progress = r.get(T_PERSON.PROGRESS);
BookingBean bean = new BookingBean(pkPerson, null, String.format("%s %4.0f", campname, year));
bean.setRole(role == null ? null : role.getLiteral());
bean.setFullname(new StringBuilder().append(forename).append(" ").append(surname).toString());
bean.setAccept(accept);
bean.setProgress(progress == null ? null : progress.getLiteral());
list.add(bean);
}
return list;
}
/**
* remove the booking and all of its dependencies
*
* @param id the pk of t_person
* @return number of affected database rows, should be 1
*/
public Integer removeBooking(Integer id) {
LambdaResultWrapper lrw = new LambdaResultWrapper();
jooq.transaction(t -> {
SelectConditionStep<Record5<String, String, String, String, LocalDateTime>> sql0 = DSL.using(t)
// @formatter:off
.select(T_PROFILE.USERNAME, T_PERSON.FORENAME, T_PERSON.SURNAME, T_CAMP.NAME, T_CAMP.ARRIVE)
.from(T_PERSON)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP))
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_PERSON.FK_PROFILE))
.where(T_PERSON.PK.eq(id));
// @formatter:on
LOGGER.trace(sql0.toString());
Record5<String, String, String, String, LocalDateTime> r = sql0.fetchOne();
if (r == null) {
throw new DataAccessException("no such entry in t_person with id = " + id);
}
String username = r.get(T_PROFILE.USERNAME);
String forename = r.get(T_PERSON.FORENAME);
String surname = r.get(T_PERSON.SURNAME);
String campname = r.get(T_CAMP.NAME);
LocalDateTime arrive = r.get(T_CAMP.ARRIVE);
StringBuilder rssMessage = new StringBuilder(username);
rssMessage.append(" hat die Stornierung der Buchung von ");
rssMessage.append(forename).append(" ").append(surname);
rssMessage.append(" an ");
rssMessage.append(campname).append(" ")
.append(arrive == null ? "" : arrive.format(DateTimeFormatter.ofPattern("YYYY")));
rssMessage.append(" bestätigt und den Datensatz gelöscht.");
DeleteConditionStep<TPersondocumentRecord> sql1 = DSL.using(t).deleteFrom(T_PERSONDOCUMENT)
.where(T_PERSONDOCUMENT.FK_PERSON.eq(id));
LOGGER.trace(sql1.toString());
sql1.execute();
DeleteConditionStep<TPersonRecord> sql2 = DSL.using(t).deleteFrom(T_PERSON).where(T_PERSON.PK.eq(id));
LOGGER.trace(sql2.toString());
lrw.add(sql2.execute());
InsertValuesStep2<TRssRecord, String, String> sql3 = DSL.using(t)
// @formatter:off
.insertInto(T_RSS,
T_RSS.MSG,
T_RSS.RECIPIENT)
.values(rssMessage.toString(), "registrator");
// @formatter:on
LOGGER.trace("{}", sql3.toString());
sql3.execute();
});
return lrw.getCounter();
}
}

View File

@ -0,0 +1,72 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.BookingBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
/**
*
* @author jotty
*
*/
@Service
public class ConfirmationService {
@Autowired
private ConfirmationRepository repository;
public List<CampOverviewBean> getCampOverview(String currentUser) {
return repository.getCampOverviewBeans(currentUser);
}
public List<BookingBean> getUntouched(String currentUser) {
return repository.getUntouched(currentUser);
}
public List<BookingBean> getApproved(String currentUser) {
return repository.getApproved(currentUser);
}
public List<BookingBean> getRejected(String currentUser) {
return repository.getRejected(currentUser);
}
public List<BookingBean> getRevoked(String currentUser) {
return repository.getRevoked(currentUser);
}
public String search(String needle, String linkURL, String currentUser) {
StringBuilder buf = new StringBuilder(
"<table class=\"table table-striped\"><thead><tr><th>Dabei</th><th>Name</th><th>Freizeit</th><th>Rolle</th></tr><tbody>");
for (BookingBean bean : repository.getSearchResult(needle, currentUser)) {
String acceptHtml = "";
if (EnumProgress.requested.equals(bean.getProgress())) {
acceptHtml = "<i class=\"fas fa-question framed framed-orange\"></i>";
} else if (EnumProgress.approved.equals(bean.getProgress())) {
acceptHtml = "<i class=\"fas fa-check framed framed-green\"></i>";
} else if (EnumProgress.rejected.equals(bean.getProgress())) {
acceptHtml = "<i class=\"fas fa-ban framed framed-red\"></i>";
} else if (EnumProgress.revoked.equals(bean.getProgress())) {
acceptHtml = "<i class=\"fas fa-skull framed framed-pink\"></i>";
}
buf.append(String.format("<tr><td>%s</td><td><a href=\"%s/%d\">%s</a></td><td>%s</td><td>%s</td></tr>",
acceptHtml, linkURL, bean.getPkPerson(), bean.getFullname(), bean.getCamp(), bean.getRolename()));
}
buf.append("</tbody></table>");
return buf.toString();
}
/**
* remove the booking and all of its dependencies
*
* @param id the id of the booking (t_person.pk)
*/
public Boolean removeBooking(Integer id) {
return repository.removeBooking(id) > 0;
}
}

View File

@ -1,65 +0,0 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.BookingBean;
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverviewBean;
/**
*
* @author jotty
*
*/
public interface IConfirmationService {
/**
* 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 the camps and its booking status
*
* @param request the request
* @return the camp overview beans
*/
public List<CampOverviewBean> getCampOverview(HttpServletRequest request);
/**
* get a list of bookings that have not yet been worked on
*
* @param request the request
* @return the list of untouched bookings
*/
public List<BookingBean> getUntouched(HttpServletRequest request);
/**
* get a list of approved bookings
*
* @param request the request
* @return the list of approved bookings
*/
public List<BookingBean> getApproved(HttpServletRequest request);
/**
* get a list of rejected bookings
*
* @param request the request
* @return the list of rejected bookings
*/
public List<BookingBean> getRejected(HttpServletRequest request);
/**
* get the result of a search for needle in the database
*
* @param needle the needle; may be a name of anything
* @param linkURL the URL of the link for clicking on the found entity
* @param request the request
* @return the result in html format (for now)
*/
public String search(String needle, String linkURL, HttpServletRequest request);
}

View File

@ -1,31 +1,32 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import de.jottyfan.camporganizer.module.camplist.CommonController;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* @author jotty
*
*/
@Controller
public class SearchController {
public class SearchController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private IConfirmationService service;
private ConfirmationService service;
@GetMapping("/confirmation/search")
@ResponseBody
public String search(@PathParam(value = "needle") String needle, Model model) {
return service.search(needle, request.getRequestURI().replace("search", "person"), request);
public String search(@RequestParam("needle") String needle, Model model) {
return service.search(needle, request.getRequestURI().replace("search", "person"), super.getCurrentUser());
}
}

View File

@ -1,73 +0,0 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.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.confirmation.confirmation.IConfirmationService;
/**
*
* @author jotty
*
*/
@Service
public class ConfirmationService implements IConfirmationService {
@Autowired
private ConfirmationRepository 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<CampOverviewBean> getCampOverview(HttpServletRequest request) {
return gateway.getCampOverviewBeans(getCurrentUser(request));
}
@Override
public List<BookingBean> getUntouched(HttpServletRequest request) {
return gateway.getUntouched(getCurrentUser(request));
}
@Override
public List<BookingBean> getApproved(HttpServletRequest request) {
return gateway.getApproved(getCurrentUser(request));
}
@Override
public List<BookingBean> getRejected(HttpServletRequest request) {
return gateway.getRejected(getCurrentUser(request));
}
@Override
public String search(String needle, String linkURL, HttpServletRequest request) {
StringBuilder buf = new StringBuilder(
"<table class=\"table table-striped\"><thead><tr><th>Dabei</th><th>Name</th><th>Freizeit</th><th>Rolle</th></tr><tbody>");
for (BookingBean bean : gateway.getSearchResult(needle, getCurrentUser(request))) {
String acceptHtml = "";
if (bean.getAccept() == null) {
acceptHtml = "<i class=\"fas fa-question framed framed-orange\"></i>";
} else if (bean.getAccept()) {
acceptHtml = "<i class=\"fas fa-check framed framed-green\"></i>";
} else {
acceptHtml = "<i class=\"fas fa-ban framed framed-red\"></i>";
}
buf.append(String.format("<tr><td>%s</td><td><a href=\"%s/%d\">%s</a></td><td>%s</td><td>%s</td></tr>",
acceptHtml, linkURL, bean.getPkPerson(), bean.getFullname(), bean.getCamp(), bean.getRolename()));
}
buf.append("</tbody></table>");
return buf.toString();
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
import java.io.Serializable;
import java.time.LocalDate;
@ -20,7 +20,7 @@ public class BookingBean implements Serializable, Comparable<BookingBean> {
private String fullname;
private String role;
private LocalDateTime registered;
private Boolean accept;
private String progress;
public BookingBean(Integer pkPerson, LocalDate date, String camp) {
this.pkPerson = pkPerson;
@ -114,11 +114,17 @@ public class BookingBean implements Serializable, Comparable<BookingBean> {
return pkPerson;
}
public Boolean getAccept() {
return accept;
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
public void setAccept(Boolean accept) {
this.accept = accept;
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
import java.io.Serializable;
import java.time.LocalDate;
@ -16,6 +16,7 @@ public class CampOverviewBean implements Serializable, Comparable<CampOverviewBe
private Integer approved;
private Integer rejected;
private Integer untouched;
private Integer revoked;
public CampOverviewBean(LocalDate date, String camp) {
this.date = date;
@ -23,6 +24,7 @@ public class CampOverviewBean implements Serializable, Comparable<CampOverviewBe
this.approved = 0;
this.rejected = 0;
this.untouched = 0;
this.revoked = 0;
}
@Override
@ -85,4 +87,18 @@ public class CampOverviewBean implements Serializable, Comparable<CampOverviewBe
public LocalDate getDate() {
return date;
}
/**
* @return the revoked
*/
public Integer getRevoked() {
return revoked;
}
/**
* @param revoked the revoked to set
*/
public void setRevoked(Integer revoked) {
this.revoked = revoked;
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
import java.io.Serializable;

View File

@ -1,19 +1,17 @@
package de.jottyfan.camporganizer.module.confirmation.person;
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.validation.BindingResult;
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.camplist.CommonController;
import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationService;
import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonBean;
import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonService;
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
import jakarta.validation.Valid;
/**
*
@ -23,28 +21,32 @@ import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonService;
@Controller
public class PersonController extends CommonController {
@Autowired
private HttpServletRequest request;
@Autowired
private IConfirmationService confirmationService;
@Autowired
private PersonService personService;
@GetMapping("/confirmation/person/{pk}")
public String getIndex(Model model, @PathVariable Integer pk) {
String username = confirmationService.getCurrentUser(request);
public String getIndex(Model model, @PathVariable("pk") Integer pk) {
String username = super.getCurrentUser();
model.addAttribute("currentUser", username);
model.addAttribute("person", personService.getPerson(username, pk));
model.addAttribute("camps", personService.getCamps(username));
model.addAttribute("annotations", personService.getAnnotations(pk));
model.addAttribute("campPrice", personService.getCampPrice(pk));
model.addAttribute("progresses", personService.getProgresses());
return "confirmation/person";
}
@PostMapping("/confirmation/person/update")
public String doUpdate(@ModelAttribute PersonBean bean, Model model) {
String username = confirmationService.getCurrentUser(request);
public String doUpdate(@Valid @ModelAttribute("person") PersonBean bean, BindingResult bindingResult, Model model) {
String username = super.getCurrentUser();
if (bindingResult.hasErrors()) {
model.addAttribute("currentUser", username);
model.addAttribute("camps", personService.getCamps(username));
model.addAttribute("annotations", personService.getAnnotations(bean.getPk()));
model.addAttribute("campPrice", personService.getCampPrice(bean.getPk()));
model.addAttribute("progresses", personService.getProgresses());
return "confirmation/person";
}
personService.updatePerson(bean, username);
return "redirect:/confirmation";
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.confirmation.person.impl;
package de.jottyfan.camporganizer.module.confirmation.person;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
@ -12,6 +12,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.logging.log4j.LogManager;
@ -19,6 +20,7 @@ import org.apache.logging.log4j.Logger;
import org.jooq.DSLContext;
import org.jooq.InsertValuesStep2;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Record11;
import org.jooq.Record4;
import org.jooq.SelectConditionStep;
@ -31,12 +33,15 @@ import org.springframework.transaction.annotation.Transactional;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.db.jooq.tables.TProfile;
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord;
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.confirmation.person.model.CampBean;
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
import de.jottyfan.camporganizer.module.mail.MailBean;
import de.jottyfan.camporganizer.module.mail.MailRepository;
@ -74,9 +79,11 @@ public class PersonRepository {
.and(T_PROFILE.USERNAME.eq(username))
.orderBy(T_CAMP.ARRIVE.desc());
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
List<CampBean> list = new ArrayList<>();
for (Record r : sql.fetch()) {
Iterator<Record4<Integer, String, LocalDateTime, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, LocalDateTime, String> r = i.next();
CampBean bean = new CampBean();
bean.setPk(r.get(T_CAMP.PK));
bean.setName(r.get(T_CAMP.NAME));
@ -106,11 +113,14 @@ public class PersonRepository {
.and(T_CAMPPROFILE.MODULE.eq(EnumModule.registration))
.and(T_PROFILE.USERNAME.eq(username));
// @formatter:on
LOGGER.debug(sql.toString());
for (Record r : sql.fetch()) {
LOGGER.trace(sql);
Iterator<Record> i = sql.fetch().iterator();
while (i.hasNext()) {
Record r = i.next();
PersonBean bean = new PersonBean();
bean.setPk(pk);
bean.setAccept(r.get(T_PERSON.ACCEPT));
EnumProgress progress = r.get(T_PERSON.PROGRESS);
bean.setProgress(progress == null ? null : progress.getLiteral());
bean.setBirthdate(r.get(T_PERSON.BIRTHDATE));
bean.setCamprole(r.get(T_PERSON.CAMPROLE));
bean.setCity(r.get(T_PERSON.CITY));
@ -126,6 +136,7 @@ public class PersonRepository {
bean.setSex(r.get(T_PERSON.SEX));
bean.setStreet(r.get(T_PERSON.STREET));
bean.setZip(r.get(T_PERSON.ZIP));
bean.setRequiredPrice(r.get(T_PERSON.REQUIRED_PRICE));
return bean;
}
return null;
@ -142,21 +153,21 @@ public class PersonRepository {
jooq.transaction(t -> {
SelectConditionStep<TProfileRecord> sql0 = jooq.selectFrom(T_PROFILE).where(T_PROFILE.USERNAME.eq(registrator));
LOGGER.debug(sql0.toString());
LOGGER.trace(sql0);
Integer fkRegistrator = sql0.fetchOne(T_PROFILE.PK);
// get old accept value for comparison
SelectConditionStep<TPersonRecord> sql1 = jooq.selectFrom(T_PERSON).where(T_PERSON.PK.eq(bean.getPk()));
LOGGER.debug(sql1.toString());
LOGGER.trace(sql1);
TPersonRecord r = sql1.fetchOne();
lrw.putBoolean("acceptOld", r == null ? null : r.getAccept());
lrw.putBoolean("acceptNew", bean.getAccept());
lrw.putBoolean("acceptOld", r == null ? null : EnumProgress.approved.equals(r.getProgress()));
lrw.putBoolean("acceptNew", EnumProgress.approved.getLiteral().equals(bean.getProgress()));
Integer fkCamp = r == null ? null : r.getFkCamp();
String email = r.getEmail(); // use the old one, too
lrw.putString("oldEmail", email);
SelectConditionStep<TCampRecord> sql2 = jooq.selectFrom(T_CAMP).where(T_CAMP.PK.eq(fkCamp));
LOGGER.debug(sql2.toString());
LOGGER.trace(sql2);
TCampRecord rc = sql2.fetchOne();
String campName = rc == null ? null : rc.getName();
LocalDateTime arrive = rc == null ? null : rc.getArrive();
@ -177,12 +188,13 @@ public class PersonRepository {
.set(T_PERSON.PHONE, bean.getPhone())
.set(T_PERSON.EMAIL, bean.getEmail())
.set(T_PERSON.COMMENT, bean.getComment())
.set(T_PERSON.ACCEPT, bean.getAccept())
.set(T_PERSON.PROGRESS, EnumProgress.lookupLiteral(bean.getProgress()))
.set(T_PERSON.CAMPROLE, bean.getCamprole())
.set(T_PERSON.FK_REGISTRATOR, fkRegistrator)
.set(T_PERSON.REQUIRED_PRICE, bean.getRequiredPrice())
.where(T_PERSON.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug(sql3.toString());
LOGGER.trace(sql3);
lrw.add(sql3.execute());
// always
@ -198,7 +210,7 @@ public class PersonRepository {
T_RSS.RECIPIENT)
.values(buf.toString(), "registrator");
// @formatter:on
LOGGER.debug("{}", sql4.toString());
LOGGER.trace(sql4);
sql4.execute();
});
@ -291,9 +303,13 @@ public class PersonRepository {
.leftJoin(REGISTRATOR).on(REGISTRATOR.PK.eq(T_PERSON.FK_REGISTRATOR))
.where(T_PERSON.PK.eq(pk));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
StringBuilder buf = new StringBuilder();
for (Record r : sql.fetch()) {
Iterator<Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String>> i = sql
.fetch().iterator();
while (i.hasNext()) {
Record11<LocalDate, LocalDateTime, EnumCamprole, LocalDateTime, LocalDateTime, Integer, Integer, String, String, String, String> r = i
.next();
LocalDate birthdate = r.get(T_PERSON.BIRTHDATE);
LocalDateTime arrive = r.get(T_CAMP.ARRIVE);
LocalDateTime depart = r.get(T_CAMP.DEPART);
@ -330,4 +346,22 @@ public class PersonRepository {
}
return buf.toString();
}
/**
* get the price information of the camp that the person is registered for
*
* @param pkPerson the ID of the person
* @return the camp price information
*/
public String getCampprice(Integer pkPerson) {
SelectConditionStep<Record1<String>> sql = jooq
// @formatter:off
.select(T_CAMP.PRICE)
.from(T_PERSON)
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP))
.where(T_PERSON.PK.eq(pkPerson));
// @formatter:on
LOGGER.trace(sql);
return sql.fetchOne(T_CAMP.PRICE);
}
}

View File

@ -0,0 +1,56 @@
package de.jottyfan.camporganizer.module.confirmation.person;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import de.jottyfan.camporganizer.db.jooq.enums.EnumProgress;
import de.jottyfan.camporganizer.module.confirmation.person.model.CampBean;
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
/**
*
* @author jotty
*
*/
@Service
public class PersonService {
@Autowired
private PersonRepository gateway;
public PersonBean getPerson(String username, Integer pk) {
return gateway.getPerson(username, pk);
}
public Integer updatePerson(PersonBean bean, String worker) {
return gateway.updatePerson(bean, worker);
}
public List<CampBean> getCamps(String username) {
return gateway.getCamps(username);
}
public String getAnnotations(Integer pk) {
return gateway.getAnnotations(pk);
}
/**
* get the price of the camp
*
* @param pk the ID of the person, not the camp
* @return the camp price
*/
public String getCampPrice(Integer pk) {
return gateway.getCampprice(pk);
}
public List<String> getProgresses() {
List<String> list = new ArrayList<>();
for (EnumProgress p : EnumProgress.values()) {
list.add(p.getLiteral());
}
return list;
}
}

View File

@ -1,33 +0,0 @@
package de.jottyfan.camporganizer.module.confirmation.person.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* @author jotty
*
*/
@Service
public class PersonService {
@Autowired
private PersonRepository gateway;
public PersonBean getPerson(String username, Integer pk) {
return gateway.getPerson(username, pk);
}
public Integer updatePerson(PersonBean bean, String worker) {
return gateway.updatePerson(bean, worker);
}
public List<CampBean> getCamps(String username) {
return gateway.getCamps(username);
}
public String getAnnotations(Integer pk) {
return gateway.getAnnotations(pk);
}
}

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.confirmation.person.impl;
package de.jottyfan.camporganizer.module.confirmation.person.model;
import java.io.Serializable;
import java.time.LocalDateTime;

View File

@ -1,6 +1,7 @@
package de.jottyfan.camporganizer.module.confirmation.person.impl;
package de.jottyfan.camporganizer.module.confirmation.person.model;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -8,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
import jakarta.validation.constraints.DecimalMin;
/**
*
@ -15,7 +17,7 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
*
*/
public class PersonBean implements Serializable {
private static final long serialVersionUID = 2L;
private static final long serialVersionUID = 3L;
private Integer pk;
private String forename;
@ -30,11 +32,13 @@ public class PersonBean implements Serializable {
private String email;
private Integer fkCamp;
private Integer fkProfile;
private Boolean accept;
private String progress;
private LocalDateTime created;
private EnumSex sex;
private Integer fkRegistrator;
private String comment;
@DecimalMin(value = "0")
private BigDecimal requiredPrice;
/**
* @return the forename
@ -190,20 +194,6 @@ public class PersonBean implements Serializable {
this.fkProfile = fkProfile;
}
/**
* @return the accept
*/
public Boolean getAccept() {
return accept;
}
/**
* @param accept the accept to set
*/
public void setAccept(Boolean accept) {
this.accept = accept;
}
/**
* @return the created
*/
@ -273,4 +263,32 @@ public class PersonBean implements Serializable {
public void setPk(Integer pk) {
this.pk = pk;
}
/**
* @return the requiredPrice
*/
public BigDecimal getRequiredPrice() {
return requiredPrice;
}
/**
* @param requiredPrice the requiredPrice to set
*/
public void setRequiredPrice(BigDecimal requiredPrice) {
this.requiredPrice = requiredPrice;
}
/**
* @return the progress
*/
public String getProgress() {
return progress;
}
/**
* @param progress the progress to set
*/
public void setProgress(String progress) {
this.progress = progress;
}
}

View File

@ -21,8 +21,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersondocumentRecord;
import de.jottyfan.camporganizer.db.jooq.tables.records.TRssRecord;
import de.jottyfan.camporganizer.module.camplist.BookingBean;
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
/**
*
@ -57,7 +57,7 @@ public class DashboardRepository {
.set(T_PERSON.COMMENT, bean.getComment())
.where(T_PERSON.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql.toString());
return sql.execute();
}
@ -79,7 +79,7 @@ public class DashboardRepository {
.deleteFrom(T_PERSONDOCUMENT)
.where(T_PERSONDOCUMENT.PK.eq(bean.getPk()));
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
lrw.add(sql.execute());
StringBuilder buf = new StringBuilder("Dokument ");
@ -92,7 +92,7 @@ public class DashboardRepository {
T_RSS.RECIPIENT)
.values(buf.toString(), "registrator");
// @formatter:on
LOGGER.debug("{}", sql2.toString());
LOGGER.trace(sql);
sql2.execute();
});
return lrw.getCounter();
@ -117,7 +117,7 @@ public class DashboardRepository {
)
.values(bean.getName(), bean.getFiletype(), bean.getFkPerson(), bean.getDocument());
// @formatter:on
LOGGER.debug("{}", sql.toString());
LOGGER.trace(sql);
sql.execute();
StringBuilder buf = new StringBuilder("Dokument ");
@ -130,7 +130,7 @@ public class DashboardRepository {
T_RSS.RECIPIENT)
.values(buf.toString(), "registrator");
// @formatter:on
LOGGER.debug("{}", sql2.toString());
LOGGER.trace(sql2);
sql2.execute();
});
}

View File

@ -4,7 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import javax.servlet.http.Part;
import jakarta.servlet.http.Part;
import org.apache.commons.io.IOUtils;

View File

@ -2,7 +2,7 @@ package de.jottyfan.camporganizer.module.document;
import java.util.Base64;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
@ -10,9 +10,8 @@ import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import de.jottyfan.camporganizer.module.camplist.CommonController;
@ -28,8 +27,8 @@ public class DocumentController extends CommonController {
@Autowired
private DocumentService service;
@RequestMapping(path = "/document/{id}", method = RequestMethod.GET)
public ResponseEntity<Resource> getDocument(@PathVariable Integer id, HttpServletResponse response) {
@GetMapping("/document/{id}")
public ResponseEntity<Resource> getDocument(@PathVariable("id") Integer id, HttpServletResponse response) {
DownloadBean bean = service.getDocument(id);
if (bean != null) {
byte[] decoded = Base64.getDecoder().decode(bean.getContent());

View File

@ -37,7 +37,7 @@ public class DocumentRepository {
.selectFrom(T_DOCUMENT)
.where(T_DOCUMENT.PK.eq(id));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
TDocumentRecord r = sql.fetchOne();
if (r == null) {
return null;

View File

@ -2,7 +2,7 @@ package de.jottyfan.camporganizer.module.ical;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
public class ICalController extends CommonController {
@Autowired
private IICalService service;
private ICalService service;
/**
* generate the ical response stream

View File

@ -1,4 +1,4 @@
package de.jottyfan.camporganizer.module.ical.impl;
package de.jottyfan.camporganizer.module.ical;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
@ -6,6 +6,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
import org.apache.logging.log4j.LogManager;
@ -53,10 +54,12 @@ public class ICalRepository {
.from(T_CAMP)
.leftJoin(T_LOCATION).on(T_LOCATION.PK.eq(T_CAMP.FK_LOCATION));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
ICalendar ical = new ICalendar();
ical.getTimezoneInfo().setDefaultTimezone(TimezoneAssignment.download(TimeZone.getTimeZone("Europe/Berlin"), false));
for (Record5<String, LocalDateTime, LocalDateTime, String, String> r : sql.fetch()) {
Iterator<Record5<String, LocalDateTime, LocalDateTime, String, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record5<String, LocalDateTime, LocalDateTime, String, String> r = i.next();
VEvent event = new VEvent();
Summary summary = event.setSummary(r.get(T_CAMP.NAME));
summary.setLanguage("de");

View File

@ -1,15 +1,13 @@
package de.jottyfan.camporganizer.module.ical.impl;
package de.jottyfan.camporganizer.module.ical;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import biweekly.Biweekly;
import biweekly.ICalendar;
import de.jottyfan.camporganizer.module.ical.IICalService;
import jakarta.servlet.http.HttpServletResponse;
/**
*
@ -17,12 +15,11 @@ import de.jottyfan.camporganizer.module.ical.IICalService;
*
*/
@Service
public class ICalService implements IICalService {
public class ICalService {
@Autowired
private ICalRepository gateway;
@Override
public Boolean generate(HttpServletResponse response) throws IOException {
ICalendar ical = gateway.getIcal();
String content = Biweekly.write(ical).go();
@ -37,5 +34,4 @@ public class ICalService implements IICalService {
return true;
}
}

View File

@ -1,23 +0,0 @@
package de.jottyfan.camporganizer.module.ical;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author jotty
*
*/
public interface IICalService {
/**
* generate the ical
*
* @param response the response for the output stream
*
* @return true if successful, false otherwise
* @throws IOException on io errors
*/
public Boolean generate(HttpServletResponse response) throws IOException;
}

View File

@ -5,8 +5,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
/**
*

View File

@ -3,8 +3,8 @@ package de.jottyfan.camporganizer.module.mail;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

View File

@ -2,8 +2,8 @@ package de.jottyfan.camporganizer.module.migration;
import java.io.Serializable;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.util.password.StrongPasswordEncryptor;

View File

@ -1,6 +1,6 @@
package de.jottyfan.camporganizer.module.migration;
import javax.validation.Valid;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

View File

@ -37,7 +37,7 @@ public class MigrationRepository {
.from(T_PROFILE)
.where(T_PROFILE.USERNAME.eq(username));
// @formatter:on
LOGGER.debug(sql.toString());
LOGGER.trace(sql);
return sql.fetchOne(T_PROFILE.PASSWORD);
}
}

View File

@ -1,6 +1,6 @@
package de.jottyfan.camporganizer.module.migration;
import javax.validation.Valid;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

Some files were not shown because too many files have changed in this diff Show More