Compare commits
1 Commits
develop
...
feature/we
| Author | SHA1 | Date | |
|---|---|---|---|
| dc9d5ff8eb |
186
.github/workflows/deploy-docker-to-ont.yml
vendored
Normal file
186
.github/workflows/deploy-docker-to-ont.yml
vendored
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
name: Docker Image CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- feature/**
|
||||||
|
tags:
|
||||||
|
- "docker-build-*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Stap 1: Code ophalen
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Stap 2: Versienummer ophalen uit pom.xml en opslaan als artifact
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
|
||||||
|
- name: Setup Maven + Java
|
||||||
|
uses: s4u/setup-maven-action@v1.6.0
|
||||||
|
with:
|
||||||
|
java-version: '21'
|
||||||
|
maven-version: '3.9.5'
|
||||||
|
|
||||||
|
- name: Extract Quarkus version from pom.xml
|
||||||
|
run: |
|
||||||
|
VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
|
||||||
|
echo $VERSION > version.txt
|
||||||
|
|
||||||
|
- name: Inject private key into resources
|
||||||
|
run: |
|
||||||
|
mkdir -p src/main/resources
|
||||||
|
echo "${{ secrets.PRIVATE_KEY }}" > src/main/resources/privateKey.pem
|
||||||
|
chmod 600 src/main/resources/privateKey.pem
|
||||||
|
|
||||||
|
- name: Decode keystore
|
||||||
|
run: |
|
||||||
|
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > src/main/resources/keystore.jks
|
||||||
|
chmod 600 src/main/resources/keystore.jks
|
||||||
|
|
||||||
|
- name: Inject public key into resources
|
||||||
|
run: |
|
||||||
|
mkdir -p src/main/resources
|
||||||
|
echo "${{ secrets.PUBLIC_KEY }}" > src/main/resources/publicKey.pem
|
||||||
|
chmod 600 src/main/resources/publicKey.pem
|
||||||
|
|
||||||
|
- name: Save version as artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: version
|
||||||
|
path: version.txt
|
||||||
|
|
||||||
|
# Stap 3: Notify Mattermost via Bot (Build gestart)
|
||||||
|
- name: Notify Mattermost via Bot
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.VERSION }}
|
||||||
|
REPO: ${{ gitea.repository }}
|
||||||
|
BRANCH: ${{ gitea.ref }}
|
||||||
|
MATTERMOST_BOT_TOKEN: ${{ secrets.MATTERMOST_BOT_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl --fail -X POST -H "Authorization: Bearer $MATTERMOST_BOT_TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{
|
||||||
|
"channel_id": "wgcfotx7x3bipcwchzn45tuxxr",
|
||||||
|
"message": "🚀 *Build gestart!* Een nieuwe build is begonnen voor de repository *'"$REPO"'* op branch *'"$BRANCH"'*."
|
||||||
|
}' \
|
||||||
|
https://mattermost.melvanveen.nl/api/v4/posts
|
||||||
|
|
||||||
|
# Stap 4: Inloggen bij Docker Hub
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
# Stap 5: Quarkus JAR bouwen (via Maven) en Docker-image bouwen
|
||||||
|
- name: Build the Quarkus JAR and Docker image
|
||||||
|
run: |
|
||||||
|
VERSION=$(cat version.txt)
|
||||||
|
mvn clean package -DskipTests -Dquarkus.profile=test
|
||||||
|
docker buildx build . --file Dockerfile-tst --tag veenm/paypoint-backend-jvm:$VERSION --platform linux/amd64
|
||||||
|
|
||||||
|
# Stap 6: Docker-image pushen naar Docker Hub (huidige versie tag)
|
||||||
|
- name: Push the Docker image (version)
|
||||||
|
run: |
|
||||||
|
VERSION=$(cat version.txt)
|
||||||
|
docker push veenm/paypoint-backend-jvm:$VERSION
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build-and-push
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Stap 1: Artifact ophalen
|
||||||
|
- name: Download version artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: version
|
||||||
|
|
||||||
|
# Stap 2: Lees versie uit het artifact
|
||||||
|
- name: Read version
|
||||||
|
id: read_version
|
||||||
|
run: echo "VERSION=$(cat version.txt)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: SSH into Alpine and update Docker container
|
||||||
|
uses: appleboy/ssh-action@v0.1.10
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.ALPINE_HOST_ONT }}
|
||||||
|
username: root
|
||||||
|
key: ${{ secrets.ALPINE_SSH_KEY }}
|
||||||
|
envs: VERSION,DB_HOST,DB_PORT,DB_USERNAME,DB_PASSWORD,CORS_ORIGINS,MAILER_FROM,MAILER_HOST,MAILER_PORT,MAILER_USERNAME,MAILER_PASSWORD
|
||||||
|
script: |
|
||||||
|
echo "Gekozen versie: $VERSION"
|
||||||
|
|
||||||
|
docker stop paypoint-backend || true
|
||||||
|
docker rm paypoint-backend || true
|
||||||
|
|
||||||
|
docker pull veenm/paypoint-backend-jvm:$VERSION
|
||||||
|
|
||||||
|
docker run -d --name paypoint-backend --restart unless-stopped -p 15001:8080 \
|
||||||
|
-e DB_HOST="$DB_HOST" \
|
||||||
|
-e DB_PORT="$DB_PORT" \
|
||||||
|
-e DB_USERNAME="$DB_USERNAME" \
|
||||||
|
-e DB_PASSWORD="$DB_PASSWORD" \
|
||||||
|
-e CORS_ORIGINS="$CORS_ORIGINS" \
|
||||||
|
-e MAILER_FROM="$MAILER_FROM" \
|
||||||
|
-e MAILER_HOST="$MAILER_HOST" \
|
||||||
|
-e MAILER_PORT="$MAILER_PORT" \
|
||||||
|
-e MAILER_USERNAME="$MAILER_USERNAME" \
|
||||||
|
-e MAILER_PASSWORD="$MAILER_PASSWORD" \
|
||||||
|
veenm/paypoint-backend-jvm:$VERSION
|
||||||
|
|
||||||
|
docker image prune -f
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.VERSION }}
|
||||||
|
DB_HOST: ${{ secrets.ALPINE_HOST_ONT }}
|
||||||
|
DB_PORT: ${{ secrets.DB_PORT_TEST }}
|
||||||
|
DB_USERNAME: ${{ secrets.DB_USERNAME_TEST }}
|
||||||
|
DB_PASSWORD: ${{ secrets.DB_PASSWORD_TEST }}
|
||||||
|
CORS_ORIGINS: ${{ secrets.CORS_ORIGINS_TEST }}
|
||||||
|
MAILER_FROM: ${{ secrets.MAILER_FROM }}
|
||||||
|
MAILER_HOST: ${{ secrets.MAILER_HOST }}
|
||||||
|
MAILER_PORT: ${{ secrets.MAILER_PORT }}
|
||||||
|
MAILER_USERNAME: ${{ secrets.MAILER_USERNAME }}
|
||||||
|
MAILER_PASSWORD: ${{ secrets.MAILER_PASSWORD }}
|
||||||
|
|
||||||
|
|
||||||
|
# Stap 4: Notify Mattermost via Bot (Build is geslaagd)
|
||||||
|
- name: Notify Mattermost via Bot
|
||||||
|
env:
|
||||||
|
MATTERMOST_BOT_TOKEN: ${{ secrets.MATTERMOST_BOT_TOKEN }}
|
||||||
|
VERSION: ${{ env.VERSION }}
|
||||||
|
run: |
|
||||||
|
curl --fail -X POST -H "Authorization: Bearer $MATTERMOST_BOT_TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{
|
||||||
|
"channel_id": "wgcfotx7x3bipcwchzn45tuxxr",
|
||||||
|
"message": "*Build is geslaagd!* Versie '"$VERSION"' van de backend staat klaar op ontwikkel!"
|
||||||
|
}' \
|
||||||
|
https://mattermost.melvanveen.nl/api/v4/posts
|
||||||
|
|
||||||
|
notify-failure:
|
||||||
|
needs: [ build-and-push, deploy ]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: failure()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Notify Mattermost via Bot on failure
|
||||||
|
env:
|
||||||
|
MATTERMOST_BOT_TOKEN: ${{ secrets.MATTERMOST_BOT_TOKEN }}
|
||||||
|
REPO: ${{ gitea.repository }}
|
||||||
|
BRANCH: ${{ gitea.ref }}
|
||||||
|
run: |
|
||||||
|
curl --fail -X POST -H "Authorization: Bearer $MATTERMOST_BOT_TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{
|
||||||
|
"channel_id": "wgcfotx7x3bipcwchzn45tuxxr",
|
||||||
|
"message": "❌ *Build gefaald!* De pipeline is stukgelopen voor *'"$REPO"'* op branch *'"$BRANCH"'*."
|
||||||
|
}' \
|
||||||
|
https://mattermost.melvanveen.nl/api/v4/posts
|
||||||
90
.github/workflows/deploy-docker.yml
vendored
90
.github/workflows/deploy-docker.yml
vendored
@@ -1,90 +0,0 @@
|
|||||||
name: Docker Image CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
tags:
|
|
||||||
- "docker-build-*"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-push:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Stap 1: Code ophalen
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Stap 2: Versienummer ophalen uit package.json en opslaan als artifact
|
|
||||||
- name: Extract Angular version
|
|
||||||
run: |
|
|
||||||
echo "$(cat package.json | jq -r '.version')" > version.txt
|
|
||||||
- name: Save version as artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: version
|
|
||||||
path: version.txt
|
|
||||||
|
|
||||||
# Stap 3: Inloggen bij Docker Hub
|
|
||||||
- name: Log in to Docker Hub
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
# Stap 4: Docker-image bouwen en taggen met Angular-versie
|
|
||||||
- name: Build the Docker image
|
|
||||||
run: |
|
|
||||||
VERSION=$(cat version.txt)
|
|
||||||
docker buildx build . --file Dockerfile --tag veenm/paypoint:$VERSION --tag veenm/paypoint:latest --platform linux/amd64
|
|
||||||
|
|
||||||
# Stap 5: Docker-image pushen naar Docker Hub (huidige versie tag)
|
|
||||||
- name: Push the Docker image (version)
|
|
||||||
run: |
|
|
||||||
VERSION=$(cat version.txt)
|
|
||||||
docker push veenm/paypoint:$VERSION
|
|
||||||
|
|
||||||
# Stap 6: Docker-image pushen naar Docker Hub (latest tag)
|
|
||||||
- name: Push the Docker image (latest)
|
|
||||||
run: docker push veenm/paypoint:latest
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
needs: build-and-push
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Stap 1: Artifact ophalen
|
|
||||||
- name: Download version artifact
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: version
|
|
||||||
|
|
||||||
# Stap 2: Lees versie uit het artifact
|
|
||||||
- name: Read version
|
|
||||||
id: read_version
|
|
||||||
run: echo "VERSION=$(cat version.txt)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Stap 3: Maak verbinding via SSH naar de TrueNAS SCALE server en update de container
|
|
||||||
- name: SSH into TrueNAS SCALE and update Docker container
|
|
||||||
uses: appleboy/ssh-action@v0.1.10
|
|
||||||
with:
|
|
||||||
host: ${{ secrets.TRUENAS_HOST }}
|
|
||||||
username: ${{ secrets.TRUENAS_USER }}
|
|
||||||
password: ${{ secrets.TRUENAS_PASSWORD }}
|
|
||||||
port: ${{ secrets.TRUENAS_PORT }}
|
|
||||||
script: |
|
|
||||||
VERSION=${{ env.VERSION }}
|
|
||||||
echo "Gekozen versie: $VERSION"
|
|
||||||
|
|
||||||
# Stop en verwijder de huidige container
|
|
||||||
docker stop paypoint || true
|
|
||||||
docker rm paypoint || true
|
|
||||||
|
|
||||||
# Haal de nieuwste image binnen
|
|
||||||
docker pull veenm/paypoint:$VERSION
|
|
||||||
|
|
||||||
# Start een nieuwe container
|
|
||||||
docker run -d --name paypoint --restart unless-stopped -p 15001:80 veenm/paypoint:$VERSION
|
|
||||||
|
|
||||||
# Opruimen oude images
|
|
||||||
docker image prune -f
|
|
||||||
44
.github/workflows/increase-version.yml
vendored
44
.github/workflows/increase-version.yml
vendored
@@ -1,44 +0,0 @@
|
|||||||
name: Increase Version
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main # Start bij commits op de main branch
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump-version:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Configure Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name "Gitea Actions"
|
|
||||||
git config --global user.email "actions@gitea.local"
|
|
||||||
|
|
||||||
- name: Bump version
|
|
||||||
run: |
|
|
||||||
npm version patch --no-git-tag-version
|
|
||||||
git add package.json package-lock.json
|
|
||||||
git commit -m "chore: bump version [skip ci]" || echo "No changes to commit"
|
|
||||||
|
|
||||||
# Pull the latest changes from the remote main branch before pushing
|
|
||||||
git pull origin main --rebase
|
|
||||||
|
|
||||||
# Push changes to remote main branch
|
|
||||||
git push origin main
|
|
||||||
|
|
||||||
trigger-pipeline-b:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Create and push tag
|
|
||||||
run: |
|
|
||||||
git config --global user.name "Gitea Actions"
|
|
||||||
git config --global user.email "actions@gitea.local"
|
|
||||||
git tag docker-build-$(date +%s)
|
|
||||||
git push --tags
|
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
FROM registry.access.redhat.com/ubi8/openjdk-21:1.20
|
FROM registry.access.redhat.com/ubi8/openjdk-21:1.20
|
||||||
|
|
||||||
ENV LANGUAGE='en_US:en'
|
ENV LANGUAGE='en_US:en'
|
||||||
ENV QUARKUS_PROFILE=test
|
|
||||||
|
|
||||||
# We make four distinct layers so if there are application changes the library layers can be re-used
|
# We make four distinct layers so if there are application changes the library layers can be re-used
|
||||||
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
|
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
|
||||||
@@ -90,7 +90,7 @@ COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
|
|||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
USER 185
|
USER 185
|
||||||
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Dquarkus.profile=prod -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||||
|
|
||||||
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
|
||||||
|
|||||||
7
pom.xml
7
pom.xml
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>nl.veenm</groupId>
|
<groupId>nl.veenm</groupId>
|
||||||
<artifactId>paypoint-backend</artifactId>
|
<artifactId>paypoint-backend</artifactId>
|
||||||
@@ -102,7 +101,6 @@
|
|||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>**/*</include>
|
<include>**/*</include>
|
||||||
<include>templates/agenda-invite.html</include>
|
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -153,8 +151,7 @@
|
|||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
|
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||||
</native.image.path>
|
|
||||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
<maven.home>${maven.home}</maven.home>
|
<maven.home>${maven.home}</maven.home>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
|
||||||
|
|
||||||
public enum AccessLevel {
|
|
||||||
READ_ONLY,
|
|
||||||
USER
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -17,8 +17,13 @@ public class AppUser {
|
|||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
@ManyToMany
|
||||||
private Set<UserCompany> userCompanies = new HashSet<>();
|
@JoinTable(
|
||||||
|
name = "user_company",
|
||||||
|
joinColumns = @JoinColumn(name = "user_id"),
|
||||||
|
inverseJoinColumns = @JoinColumn(name = "company_id")
|
||||||
|
)
|
||||||
|
private Set<Company> companies = new HashSet<>();
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
@@ -76,12 +81,12 @@ public class AppUser {
|
|||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<UserCompany> getUserCompanies() {
|
public Set<Company> getCompanies() {
|
||||||
return userCompanies;
|
return companies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserCompanies(Set<UserCompany> userCompanies) {
|
public void setCompanies(Set<Company> companies) {
|
||||||
this.userCompanies = userCompanies;
|
this.companies = companies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -3,17 +3,19 @@ package nl.veenm.paypoint.domain;
|
|||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class Appointment {
|
public class Appointment {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
private UUID id;
|
private Long id;
|
||||||
private String title;
|
private String title;
|
||||||
private String description;
|
private String description;
|
||||||
private LocalDateTime startDateTime;
|
private LocalDateTime startDate;
|
||||||
private LocalDateTime endDateTime;
|
private int startHour;
|
||||||
|
private int startMinute;
|
||||||
|
private int endHour;
|
||||||
|
private int endMinute;
|
||||||
private int durationInMinutes;
|
private int durationInMinutes;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@@ -22,15 +24,27 @@ public class Appointment {
|
|||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Company company;
|
private Company company;
|
||||||
|
|
||||||
|
public Appointment(Long id, String title, String description, LocalDateTime startDate, int startHour, int startMinute, int endHour, int endMinute, int durationInMinutes) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.description = description;
|
||||||
|
this.startDate = startDate;
|
||||||
|
this.startHour = startHour;
|
||||||
|
this.startMinute = startMinute;
|
||||||
|
this.endHour = endHour;
|
||||||
|
this.endMinute = endMinute;
|
||||||
|
this.durationInMinutes = durationInMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
public Appointment() {
|
public Appointment() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(UUID id) {
|
public void setId(Long id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,12 +64,44 @@ public class Appointment {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDateTime getStartDateTime() {
|
public LocalDateTime getStartDate() {
|
||||||
return startDateTime;
|
return startDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStartDateTime(LocalDateTime startDate) {
|
public void setStartDate(LocalDateTime startDate) {
|
||||||
this.startDateTime = startDate;
|
this.startDate = startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartHour() {
|
||||||
|
return startHour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartHour(int startHour) {
|
||||||
|
this.startHour = startHour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartMinute() {
|
||||||
|
return startMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartMinute(int startMinute) {
|
||||||
|
this.startMinute = startMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEndHour() {
|
||||||
|
return endHour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndHour(int endHour) {
|
||||||
|
this.endHour = endHour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEndMinute() {
|
||||||
|
return endMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndMinute(int endMinute) {
|
||||||
|
this.endMinute = endMinute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDurationInMinutes() {
|
public int getDurationInMinutes() {
|
||||||
@@ -78,14 +124,6 @@ public class Appointment {
|
|||||||
return company;
|
return company;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDateTime getEndDateTime() {
|
|
||||||
return endDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndDateTime(LocalDateTime end) {
|
|
||||||
this.endDateTime = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompany(Company company) {
|
public void setCompany(Company company) {
|
||||||
this.company = company;
|
this.company = company;
|
||||||
}
|
}
|
||||||
@@ -96,11 +134,13 @@ public class Appointment {
|
|||||||
"id=" + id +
|
"id=" + id +
|
||||||
", title='" + title + '\'' +
|
", title='" + title + '\'' +
|
||||||
", description='" + description + '\'' +
|
", description='" + description + '\'' +
|
||||||
", start=" + startDateTime +
|
", date=" + startDate +
|
||||||
", end=" + endDateTime +
|
", startHour=" + startHour +
|
||||||
|
", startMinute=" + startMinute +
|
||||||
|
", endHour=" + endHour +
|
||||||
|
", endMinute=" + endMinute +
|
||||||
", durationInMinutes=" + durationInMinutes +
|
", durationInMinutes=" + durationInMinutes +
|
||||||
", customer=" + customer +
|
", customer=" + customer +
|
||||||
", company=" + company +
|
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
package nl.veenm.paypoint.domain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -17,8 +18,9 @@ public class Company {
|
|||||||
private String postal_code;
|
private String postal_code;
|
||||||
private String city;
|
private String city;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true)
|
@ManyToMany(mappedBy = "companies")
|
||||||
private Set<UserCompany> userCompanies = new HashSet<>();
|
@JsonIgnore
|
||||||
|
private Set<AppUser> users = new HashSet<>();
|
||||||
|
|
||||||
public void setId(Long id) {
|
public void setId(Long id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -76,11 +78,11 @@ public class Company {
|
|||||||
this.city = city;
|
this.city = city;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<UserCompany> getUserCompanies() {
|
public Set<AppUser> getUsers() {
|
||||||
return userCompanies;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserCompanies(Set<UserCompany> userCompanies) {
|
public void setUsers(Set<AppUser> users) {
|
||||||
this.userCompanies = userCompanies;
|
this.users = users;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class InviteEntity {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
public UUID id;
|
|
||||||
public Long company_id;
|
|
||||||
public String email;
|
|
||||||
public String token;
|
|
||||||
public Instant expiresAt;
|
|
||||||
public boolean used;
|
|
||||||
public Instant createdAt;
|
|
||||||
|
|
||||||
public InviteEntity() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public InviteEntity(UUID id, Long company_id, String email, String token, Instant expiresAt, boolean used, Instant createdAt) {
|
|
||||||
this.id = id;
|
|
||||||
this.company_id = company_id;
|
|
||||||
this.email = email;
|
|
||||||
this.token = token;
|
|
||||||
this.expiresAt = expiresAt;
|
|
||||||
this.used = used;
|
|
||||||
this.createdAt = createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(UUID id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getCompany_id() {
|
|
||||||
return company_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompany_id(Long company_id) {
|
|
||||||
this.company_id = company_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instant getExpiresAt() {
|
|
||||||
return expiresAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpiresAt(Instant expires_at) {
|
|
||||||
this.expiresAt = expires_at;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUsed() {
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsed(boolean used) {
|
|
||||||
this.used = used;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Instant getCreatedAt() {
|
|
||||||
return createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreatedAt(Instant created_at) {
|
|
||||||
this.createdAt = created_at;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Kolom | Type | Beschrijving
|
|
||||||
//id | UUID (PK) | Uniek ID
|
|
||||||
//bedrijf_id | Long | ID van het bedrijf/agenda
|
|
||||||
//email | String | Ontvanger
|
|
||||||
//token | String (uniek) | Token (bijv. Base64 of UUID)
|
|
||||||
//expires_at | Timestamp | Expiratietijd (bijv. 24u geldig)
|
|
||||||
//used | Boolean | Of de uitnodiging al geaccepteerd is
|
|
||||||
//created_at | Timestamp | Voor logging/audit
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
|
||||||
|
|
||||||
public class InviteRequest {
|
|
||||||
public Long companyId;
|
|
||||||
public String email;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
|
||||||
|
|
||||||
public class UrlRequest {
|
|
||||||
public String url;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "user_company")
|
|
||||||
public class UserCompany {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
private UUID id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "user_id")
|
|
||||||
private AppUser user;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "company_id")
|
|
||||||
private Company company;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
@Column(name = "access_level")
|
|
||||||
private AccessLevel accessLevel;
|
|
||||||
|
|
||||||
|
|
||||||
public UUID getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(UUID id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AppUser getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUser(AppUser user) {
|
|
||||||
this.user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Company getCompany() {
|
|
||||||
return company;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompany(Company company) {
|
|
||||||
this.company = company;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccessLevel getAccessLevel() {
|
|
||||||
return accessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccessLevel(AccessLevel accessLevel) {
|
|
||||||
this.accessLevel = accessLevel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.dto;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class AppUserDTO {
|
|
||||||
private Long id;
|
|
||||||
private String username;
|
|
||||||
private String email;
|
|
||||||
private String firstName;
|
|
||||||
private String lastName;
|
|
||||||
private String role;
|
|
||||||
private String token;
|
|
||||||
private Set<UserCompanyDTO> companies;
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirstName(String firstName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRole(String role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<UserCompanyDTO> getCompanies() {
|
|
||||||
return companies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompanies(Set<UserCompanyDTO> companies) {
|
|
||||||
this.companies = companies;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.dto;
|
|
||||||
|
|
||||||
import nl.veenm.paypoint.domain.Customer;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class AppointmentDTO {
|
|
||||||
private UUID id;
|
|
||||||
private String title;
|
|
||||||
private String description;
|
|
||||||
private LocalDateTime startDateTime;
|
|
||||||
private LocalDateTime endDateTime;
|
|
||||||
private int durationInMinutes;
|
|
||||||
private Customer customer;
|
|
||||||
private CompanyDTO company;
|
|
||||||
|
|
||||||
public UUID getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(UUID id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDateTime getStartDateTime() {
|
|
||||||
return startDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStartDateTime(LocalDateTime startDateTime) {
|
|
||||||
this.startDateTime = startDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDateTime getEndDateTime() {
|
|
||||||
return endDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndDateTime(LocalDateTime endDateTime) {
|
|
||||||
this.endDateTime = endDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDurationInMinutes() {
|
|
||||||
return durationInMinutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDurationInMinutes(int durationInMinutes) {
|
|
||||||
this.durationInMinutes = durationInMinutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Customer getCustomer() {
|
|
||||||
return customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCustomer(Customer customer) {
|
|
||||||
this.customer = customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompanyDTO getCompany() {
|
|
||||||
return company;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompany(CompanyDTO company) {
|
|
||||||
this.company = company;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.dto;
|
|
||||||
|
|
||||||
public class CompanyDTO {
|
|
||||||
private Long id;
|
|
||||||
private String name;
|
|
||||||
private String email;
|
|
||||||
private String address;
|
|
||||||
private String postalCode;
|
|
||||||
private String city;
|
|
||||||
private String imgHref;
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddress(String address) {
|
|
||||||
this.address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPostalCode() {
|
|
||||||
return postalCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPostalCode(String postalCode) {
|
|
||||||
this.postalCode = postalCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCity() {
|
|
||||||
return city;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCity(String city) {
|
|
||||||
this.city = city;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getImgHref() {
|
|
||||||
return imgHref;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImgHref(String imgHref) {
|
|
||||||
this.imgHref = imgHref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.dto;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class UserCompanyDTO {
|
|
||||||
private UUID id;
|
|
||||||
private String accessLevel;
|
|
||||||
private CompanyDTO company;
|
|
||||||
|
|
||||||
public UUID getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(UUID id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccessLevel() {
|
|
||||||
return accessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccessLevel(String accessLevel) {
|
|
||||||
this.accessLevel = accessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompanyDTO getCompany() {
|
|
||||||
return company;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompany(CompanyDTO company) {
|
|
||||||
this.company = company;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.mapper;
|
|
||||||
|
|
||||||
import nl.veenm.paypoint.domain.AppUser;
|
|
||||||
import nl.veenm.paypoint.domain.Company;
|
|
||||||
import nl.veenm.paypoint.domain.UserCompany;
|
|
||||||
import nl.veenm.paypoint.domain.dto.AppUserDTO;
|
|
||||||
import nl.veenm.paypoint.domain.dto.CompanyDTO;
|
|
||||||
import nl.veenm.paypoint.domain.dto.UserCompanyDTO;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class AppUserMapper {
|
|
||||||
|
|
||||||
public static AppUserDTO toDTO(AppUser user, String token) {
|
|
||||||
AppUserDTO dto = toDTO(user);
|
|
||||||
dto.setToken(token);
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AppUserDTO toDTO(AppUser user) {
|
|
||||||
AppUserDTO dto = new AppUserDTO();
|
|
||||||
dto.setId(user.getId());
|
|
||||||
dto.setUsername(user.getUsername());
|
|
||||||
dto.setEmail(user.getEmail());
|
|
||||||
dto.setFirstName(user.getFirstName());
|
|
||||||
dto.setLastName(user.getLastName());
|
|
||||||
dto.setRole(user.getRole());
|
|
||||||
|
|
||||||
if (user.getUserCompanies() != null) {
|
|
||||||
Set<UserCompanyDTO> companyDTOs = user.getUserCompanies()
|
|
||||||
.stream()
|
|
||||||
.map(AppUserMapper::toUserCompanyDTO)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
dto.setCompanies(companyDTOs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UserCompanyDTO toUserCompanyDTO(UserCompany uc) {
|
|
||||||
UserCompanyDTO dto = new UserCompanyDTO();
|
|
||||||
dto.setId(uc.getId());
|
|
||||||
dto.setAccessLevel(uc.getAccessLevel().name());
|
|
||||||
|
|
||||||
Company company = uc.getCompany();
|
|
||||||
CompanyDTO companyDTO = CompanyMapper.toDto(company);
|
|
||||||
|
|
||||||
dto.setCompany(companyDTO);
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.mapper;
|
|
||||||
|
|
||||||
import nl.veenm.paypoint.domain.Appointment;
|
|
||||||
import nl.veenm.paypoint.domain.dto.AppointmentDTO;
|
|
||||||
|
|
||||||
public class AppointmentMapper {
|
|
||||||
|
|
||||||
public static AppointmentDTO toDto(Appointment appointment) {
|
|
||||||
if (appointment == null) return null;
|
|
||||||
|
|
||||||
AppointmentDTO dto = new AppointmentDTO();
|
|
||||||
dto.setId(appointment.getId());
|
|
||||||
dto.setTitle(appointment.getTitle());
|
|
||||||
dto.setDescription(appointment.getDescription());
|
|
||||||
dto.setStartDateTime(appointment.getStartDateTime());
|
|
||||||
dto.setEndDateTime(appointment.getEndDateTime());
|
|
||||||
dto.setDurationInMinutes(appointment.getDurationInMinutes());
|
|
||||||
dto.setCustomer(appointment.getCustomer());
|
|
||||||
dto.setCompany(CompanyMapper.toDto(appointment.getCompany()));
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package nl.veenm.paypoint.domain.mapper;
|
|
||||||
|
|
||||||
import nl.veenm.paypoint.domain.Company;
|
|
||||||
import nl.veenm.paypoint.domain.dto.CompanyDTO;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class CompanyMapper {
|
|
||||||
|
|
||||||
public static CompanyDTO toDto(Company company) {
|
|
||||||
if (company == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompanyDTO dto = new CompanyDTO();
|
|
||||||
dto.setId(company.getId());
|
|
||||||
dto.setName(company.getName());
|
|
||||||
dto.setEmail(company.getEmail());
|
|
||||||
dto.setAddress(company.getAddress());
|
|
||||||
dto.setPostalCode(company.getPostal_code());
|
|
||||||
dto.setCity(company.getCity());
|
|
||||||
dto.setImgHref(company.getImg_href());
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<CompanyDTO> toDtoList(Collection<Company> companies) {
|
|
||||||
if (companies == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return companies.stream()
|
|
||||||
.map(CompanyMapper::toDto)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -10,7 +10,6 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class AppointmentRepository implements PanacheRepository<Appointment> {
|
public class AppointmentRepository implements PanacheRepository<Appointment> {
|
||||||
@@ -23,23 +22,14 @@ public class AppointmentRepository implements PanacheRepository<Appointment> {
|
|||||||
.firstResultOptional();
|
.firstResultOptional();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Appointment findByUUID(UUID uuid) {
|
|
||||||
return find("id = ?1", uuid).firstResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Appointment> findMostRecentByCompanyId(Company company) {
|
public List<Appointment> findMostRecentByCompanyId(Company company) {
|
||||||
return find("company = ?1", company).list();
|
return find("company = ?1", company).list();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Appointment> findAppointmentsForCompaniesForDay(Set<Long> companyIds, LocalDateTime startDate, LocalDateTime endDate) {
|
public List<Appointment> findAppointmentsForCompanies(Set<Company> companies, LocalDateTime startDate, LocalDateTime endDate) {
|
||||||
return find("SELECT a FROM Appointment a WHERE a.company.id IN :companyIds AND a.startDateTime BETWEEN :start AND :end",
|
return find("SELECT a FROM Appointment a WHERE a.company IN :companies AND a.startDate BETWEEN :start AND :end",
|
||||||
Parameters.with("companyIds", companyIds).and("start", startDate).and("end", endDate))
|
Parameters.with("companies", companies).and("start", startDate).and("end", endDate))
|
||||||
.list();
|
.list();
|
||||||
}
|
|
||||||
|
|
||||||
public List<Appointment> findAppointmentsForCompaniesForWeek(Set<Long> companyIds, LocalDateTime startDate, LocalDateTime endDate) {
|
|
||||||
return find("SELECT a FROM Appointment a WHERE a.company.id IN :companyIds AND a.startDateTime BETWEEN :start AND :end",
|
|
||||||
Parameters.with("companyIds", companyIds).and("start", startDate).and("end", endDate))
|
|
||||||
.list();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package nl.veenm.paypoint.repository;
|
|
||||||
|
|
||||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
import nl.veenm.paypoint.domain.InviteEntity;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class InviteRepository implements PanacheRepository<InviteEntity> {
|
|
||||||
public InviteEntity findByToken(String token) {
|
|
||||||
return find("token", token).firstResult();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package nl.veenm.paypoint.repository;
|
|
||||||
|
|
||||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
import nl.veenm.paypoint.domain.AppUser;
|
|
||||||
import nl.veenm.paypoint.domain.UserCompany;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class UserCompanyRepository implements PanacheRepository<UserCompany> {
|
|
||||||
public List<UserCompany> getAllByUserId(AppUser user) {
|
|
||||||
return find("user", user).list();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package nl.veenm.paypoint.resource;
|
|
||||||
|
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import jakarta.ws.rs.*;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import nl.veenm.paypoint.domain.InviteEntity;
|
|
||||||
import nl.veenm.paypoint.domain.InviteRequest;
|
|
||||||
import nl.veenm.paypoint.domain.UrlRequest;
|
|
||||||
import nl.veenm.paypoint.service.AgendaService;
|
|
||||||
|
|
||||||
@Path("/agenda")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class AgendaResource {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AgendaService agendaService;
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/{email}")
|
|
||||||
public void sendInvite(@PathParam("email") String email, UrlRequest urlRequest) {
|
|
||||||
agendaService.sendInvite(email, urlRequest.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/verify")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Response verifyInvite(@QueryParam("token") String token) {
|
|
||||||
return agendaService.verifyInvite(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/createinvite")
|
|
||||||
public InviteEntity createInvite(InviteRequest inviteRequest) {
|
|
||||||
return agendaService.createInvite(inviteRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@ import jakarta.ws.rs.*;
|
|||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import nl.veenm.paypoint.domain.Appointment;
|
import nl.veenm.paypoint.domain.Appointment;
|
||||||
import nl.veenm.paypoint.domain.dto.AppointmentDTO;
|
|
||||||
import nl.veenm.paypoint.service.AppointmentService;
|
import nl.veenm.paypoint.service.AppointmentService;
|
||||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||||
|
|
||||||
@@ -31,20 +30,11 @@ public class AppointmentResource {
|
|||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/date")
|
@Path("/date")
|
||||||
public List<AppointmentDTO> getAppointmentsByDate(@QueryParam("start") String start) {
|
public List<Appointment> getAppointmentsByDate(@QueryParam("start") String start) {
|
||||||
String user = jwt.getClaim("username");
|
String user = jwt.getClaim("username");
|
||||||
return appointmentService.getAppointmentsByDate(start, user);
|
return appointmentService.getAppointmentsByDate(start, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("/date/week")
|
|
||||||
public List<AppointmentDTO> getAppointmentsByDateWeek(@QueryParam("start") String start, @QueryParam("end") String end) {
|
|
||||||
String user = jwt.getClaim("username");
|
|
||||||
System.out.println("user: " + user);
|
|
||||||
return appointmentService.getAppointmentsByWeek(start, end, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Deze werkend maken
|
//TODO: Deze werkend maken
|
||||||
|
|
||||||
// @GET
|
// @GET
|
||||||
@@ -57,7 +47,7 @@ public class AppointmentResource {
|
|||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
public AppointmentDTO getAppointmentById(@PathParam("id") Long id) {
|
public Appointment getAppointmentById(@PathParam("id") Long id) {
|
||||||
return appointmentService.getAppointment(id);
|
return appointmentService.getAppointment(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +68,7 @@ public class AppointmentResource {
|
|||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response updateAppointment(AppointmentDTO appointment) {
|
public Response updateAppointment(Appointment appointment) {
|
||||||
return Response.ok(appointmentService.update(appointment)).build();
|
return Response.ok(appointmentService.update(appointment)).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import jakarta.ws.rs.POST;
|
|||||||
import jakarta.ws.rs.Path;
|
import jakarta.ws.rs.Path;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import nl.veenm.paypoint.domain.AppUser;
|
import nl.veenm.paypoint.domain.AppUser;
|
||||||
import nl.veenm.paypoint.domain.dto.AppUserDTO;
|
import nl.veenm.paypoint.domain.UserDTO;
|
||||||
import nl.veenm.paypoint.domain.mapper.AppUserMapper;
|
|
||||||
import nl.veenm.paypoint.service.TokenService;
|
import nl.veenm.paypoint.service.TokenService;
|
||||||
import nl.veenm.paypoint.service.UserService;
|
import nl.veenm.paypoint.service.UserService;
|
||||||
|
|
||||||
@@ -26,15 +25,36 @@ public class AuthResource {
|
|||||||
return Response.ok().build();
|
return Response.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @POST
|
||||||
|
// @Path("/login")
|
||||||
|
// @PermitAll
|
||||||
|
// @Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
// public Response login(AuthDTO user) {
|
||||||
|
// System.out.println(user);
|
||||||
|
// System.out.println("admin".equals(user.getUsername()) && "password".equals(user.getPassword()));
|
||||||
|
// if ("admin".equals(user.getUsername()) && "password".equals(user.getPassword())) {
|
||||||
|
// UserDTO userDTO = new UserDTO();
|
||||||
|
// userDTO.setUsername(user.getUsername());
|
||||||
|
// userDTO.setEmail("vanveenmel11@gmail.com");
|
||||||
|
// userDTO.setFullName("Mel van Veen");
|
||||||
|
// userDTO.setToken(tokenService.generateToken(user.getUsername()));
|
||||||
|
// return Response.ok(userDTO).build();
|
||||||
|
// }
|
||||||
|
// return Response.status(Response.Status.UNAUTHORIZED).build();
|
||||||
|
// }
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/login")
|
@Path("/login")
|
||||||
public Response login(AppUser user) {
|
public Response login(AppUser user) {
|
||||||
System.out.println("login");
|
|
||||||
AppUser authenticated = userService.authenticate(user.getUsername(), user.getPassword());
|
AppUser authenticated = userService.authenticate(user.getUsername(), user.getPassword());
|
||||||
if (authenticated != null) {
|
if (authenticated != null) {
|
||||||
String token = tokenService.generateToken(authenticated);
|
String token = tokenService.generateToken(authenticated);
|
||||||
AppUserDTO authenticatedDTO = AppUserMapper.toDTO(authenticated, token);
|
UserDTO userDTO = new UserDTO();
|
||||||
return Response.ok(authenticatedDTO).build();
|
userDTO.setUsername(authenticated.getUsername());
|
||||||
|
userDTO.setEmail(authenticated.getEmail());
|
||||||
|
userDTO.setFullName(authenticated.getFirstName() + " " + authenticated.getLastName());
|
||||||
|
userDTO.setToken(token);
|
||||||
|
return Response.ok(userDTO).build();
|
||||||
} else {
|
} else {
|
||||||
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
|
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ package nl.veenm.paypoint.resource;
|
|||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.*;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import nl.veenm.paypoint.domain.UserCompany;
|
import nl.veenm.paypoint.domain.Company;
|
||||||
import nl.veenm.paypoint.domain.dto.CompanyDTO;
|
|
||||||
import nl.veenm.paypoint.service.CompanyService;
|
import nl.veenm.paypoint.service.CompanyService;
|
||||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
@Path("/company")
|
@Path("/company")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@@ -22,25 +21,14 @@ public class CompanyResource {
|
|||||||
JsonWebToken jwt;
|
JsonWebToken jwt;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
public List<UserCompany> getCompanies() {
|
public Set<Company> getCompanies() {
|
||||||
return this.companyService.getCompanies(this.jwt.getClaim("username"));
|
return this.companyService.getCompanies(this.jwt.getClaim("username"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}")
|
|
||||||
public CompanyDTO getCompanyById(@PathParam("id") Long id) {
|
|
||||||
return this.companyService.getCompanyById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/link")
|
public void linkCompany(@QueryParam("user") Long userId, @QueryParam("company") Long companyId) {
|
||||||
public void linkCompany(@QueryParam("user") Long userId, @QueryParam("token") String token) {
|
System.out.println(userId);
|
||||||
this.companyService.linkCompanyWithInvite(userId, token);
|
System.out.println(companyId);
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/link/noInvite")
|
|
||||||
public void linkCompanyToNewUser(@QueryParam("user") Long userId, @QueryParam("company") Long companyId) {
|
|
||||||
this.companyService.linkCompany(userId, companyId);
|
this.companyService.linkCompany(userId, companyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
package nl.veenm.paypoint.service;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
import nl.veenm.paypoint.domain.InviteEntity;
|
|
||||||
import nl.veenm.paypoint.domain.InviteRequest;
|
|
||||||
import nl.veenm.paypoint.repository.InviteRepository;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class AgendaService {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
EmailService emailService;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
InviteRepository inviteRepository;
|
|
||||||
|
|
||||||
public void sendInvite(String email, String url) {
|
|
||||||
this.emailService.stuurUitnodiging(email, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public InviteEntity createInvite(InviteRequest inviteRequest) {
|
|
||||||
String token = generateSecureToken(); // zoals eerder besproken
|
|
||||||
InviteEntity invite = new InviteEntity();
|
|
||||||
|
|
||||||
invite.setCompany_id(inviteRequest.companyId);
|
|
||||||
invite.setEmail(inviteRequest.email);
|
|
||||||
invite.setToken(token);
|
|
||||||
invite.setUsed(false);
|
|
||||||
invite.setCreatedAt(Instant.now());
|
|
||||||
invite.setExpiresAt(Instant.now().plus(1, ChronoUnit.HOURS)); // 1u geldig
|
|
||||||
|
|
||||||
inviteRepository.persist(invite);
|
|
||||||
|
|
||||||
return invite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateSecureToken() {
|
|
||||||
byte[] randomBytes = new byte[24];
|
|
||||||
new SecureRandom().nextBytes(randomBytes);
|
|
||||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response verifyInvite(String token) {
|
|
||||||
InviteEntity invite = inviteRepository.findByToken(token);
|
|
||||||
|
|
||||||
if (invite == null || invite.isUsed()) {
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity("Ongeldige of reeds gebruikte uitnodiging").build();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invite.getExpiresAt().isBefore(Instant.now())) {
|
|
||||||
return Response.status(Response.Status.GONE).entity("Deze uitnodiging is verlopen").build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response.ok(invite).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,12 +7,6 @@ import jakarta.transaction.Transactional;
|
|||||||
import nl.veenm.paypoint.domain.AppUser;
|
import nl.veenm.paypoint.domain.AppUser;
|
||||||
import nl.veenm.paypoint.domain.Appointment;
|
import nl.veenm.paypoint.domain.Appointment;
|
||||||
import nl.veenm.paypoint.domain.Company;
|
import nl.veenm.paypoint.domain.Company;
|
||||||
import nl.veenm.paypoint.domain.dto.AppUserDTO;
|
|
||||||
import nl.veenm.paypoint.domain.dto.AppointmentDTO;
|
|
||||||
import nl.veenm.paypoint.domain.dto.CompanyDTO;
|
|
||||||
import nl.veenm.paypoint.domain.dto.UserCompanyDTO;
|
|
||||||
import nl.veenm.paypoint.domain.mapper.AppUserMapper;
|
|
||||||
import nl.veenm.paypoint.domain.mapper.AppointmentMapper;
|
|
||||||
import nl.veenm.paypoint.repository.AppointmentRepository;
|
import nl.veenm.paypoint.repository.AppointmentRepository;
|
||||||
import nl.veenm.paypoint.repository.CompanyRepository;
|
import nl.veenm.paypoint.repository.CompanyRepository;
|
||||||
import nl.veenm.paypoint.repository.UserRepository;
|
import nl.veenm.paypoint.repository.UserRepository;
|
||||||
@@ -20,8 +14,6 @@ import nl.veenm.paypoint.repository.UserRepository;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class AppointmentService {
|
public class AppointmentService {
|
||||||
@@ -47,43 +39,25 @@ public class AppointmentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public AppointmentDTO add(Appointment appointment, Long companyId, String username) {
|
public Appointment add(Appointment appointment, Long companyId, String username) {
|
||||||
Company company = companyRepository.findById(companyId);
|
Company company = companyRepository.findById(companyId);
|
||||||
AppUser user = userRepository.findByUsername(username);
|
AppUser user = userRepository.findByUsername(username);
|
||||||
appointment.setCompany(company);
|
appointment.setCompany(company);
|
||||||
appointmentRepository.persist(appointment);
|
appointmentRepository.persist(appointment);
|
||||||
emailService.stuurBevestiging(appointment, user);
|
emailService.stuurBevestiging(appointment, user);
|
||||||
return AppointmentMapper.toDto(appointment);
|
return appointment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public List<AppointmentDTO> getAppointmentsByDate(String start, String username) {
|
public List<Appointment> getAppointmentsByDate(String start, String username) {
|
||||||
LocalDate date = LocalDate.parse(start);
|
LocalDate date = LocalDate.parse(start);
|
||||||
AppUser user = userRepository.findByUsername(username);
|
AppUser user = userRepository.findByUsername(username);
|
||||||
AppUserDTO appUserDTO = AppUserMapper.toDTO(user);
|
|
||||||
Set<Long> companies = appUserDTO.getCompanies().stream().map(UserCompanyDTO::getCompany).map(CompanyDTO::getId).collect(Collectors.toSet());
|
|
||||||
|
|
||||||
LocalDateTime startOfDay = date.atStartOfDay();
|
LocalDateTime startOfDay = date.atStartOfDay();
|
||||||
LocalDateTime endOfDay = date.atTime(23, 59, 59);
|
LocalDateTime endOfDay = date.atTime(23, 59, 59);
|
||||||
|
|
||||||
List<Appointment> appointmentsForCompanies = appointmentRepository.findAppointmentsForCompaniesForDay(companies, startOfDay, endOfDay);
|
return appointmentRepository.findAppointmentsForCompanies(user.getCompanies(), startOfDay, endOfDay);
|
||||||
return appointmentsForCompanies.stream().map(AppointmentMapper::toDto).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public List<AppointmentDTO> getAppointmentsByWeek(String start, String end, String username) {
|
|
||||||
LocalDate startDate = LocalDate.parse(start);
|
|
||||||
LocalDate endDate = LocalDate.parse(end);
|
|
||||||
AppUser user = userRepository.findByUsername(username);
|
|
||||||
AppUserDTO appUserDTO = AppUserMapper.toDTO(user);
|
|
||||||
Set<Long> companies = appUserDTO.getCompanies().stream().map(UserCompanyDTO::getCompany).map(CompanyDTO::getId).collect(Collectors.toSet());
|
|
||||||
|
|
||||||
LocalDateTime startOfStartDay = startDate.atStartOfDay();
|
|
||||||
LocalDateTime endOfEndDate = endDate.atTime(23, 59, 59);
|
|
||||||
|
|
||||||
List<Appointment> appointmentsForCompanies = appointmentRepository.findAppointmentsForCompaniesForWeek(companies, startOfStartDay, endOfEndDate);
|
|
||||||
System.out.println(appointmentsForCompanies.size());
|
|
||||||
return appointmentsForCompanies.stream().map(AppointmentMapper::toDto).toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -93,23 +67,25 @@ public class AppointmentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public AppointmentDTO update(AppointmentDTO appointment) {
|
public Appointment update(Appointment appointment) {
|
||||||
Appointment appointmentToUpdate = appointmentRepository.findByUUID(appointment.getId());
|
Appointment appointmentToUpdate = appointmentRepository.findById(appointment.getId());
|
||||||
appointmentToUpdate.setTitle(appointment.getTitle());
|
appointmentToUpdate.setTitle(appointment.getTitle());
|
||||||
appointmentToUpdate.setStartDateTime(appointment.getStartDateTime());
|
appointmentToUpdate.setStartDate(appointment.getStartDate());
|
||||||
appointmentToUpdate.setEndDateTime(appointment.getEndDateTime());
|
|
||||||
appointmentToUpdate.setDescription(appointment.getDescription());
|
appointmentToUpdate.setDescription(appointment.getDescription());
|
||||||
|
appointmentToUpdate.setStartHour(appointment.getStartHour());
|
||||||
|
appointmentToUpdate.setStartMinute(appointment.getStartMinute());
|
||||||
|
appointmentToUpdate.setEndHour(appointment.getEndHour());
|
||||||
|
appointmentToUpdate.setEndMinute(appointment.getEndMinute());
|
||||||
appointmentToUpdate.setCustomer(appointment.getCustomer());
|
appointmentToUpdate.setCustomer(appointment.getCustomer());
|
||||||
appointmentToUpdate.setDurationInMinutes(appointment.getDurationInMinutes());
|
appointmentToUpdate.setDurationInMinutes(appointment.getDurationInMinutes());
|
||||||
appointmentRepository.persist(appointmentToUpdate);
|
appointmentRepository.persist(appointmentToUpdate);
|
||||||
emailService.stuurBewerking(appointmentToUpdate);
|
emailService.stuurBewerking(appointmentToUpdate);
|
||||||
return AppointmentMapper.toDto(appointmentToUpdate);
|
return appointmentToUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public AppointmentDTO getAppointment(Long id) {
|
public Appointment getAppointment(Long id) {
|
||||||
Appointment byId = appointmentRepository.findById(id);
|
return appointmentRepository.findById(id);
|
||||||
return AppointmentMapper.toDto(byId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
@@ -3,57 +3,38 @@ package nl.veenm.paypoint.service;
|
|||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import nl.veenm.paypoint.domain.*;
|
import nl.veenm.paypoint.domain.AppUser;
|
||||||
import nl.veenm.paypoint.domain.dto.CompanyDTO;
|
import nl.veenm.paypoint.domain.Company;
|
||||||
import nl.veenm.paypoint.domain.mapper.CompanyMapper;
|
|
||||||
import nl.veenm.paypoint.repository.CompanyRepository;
|
import nl.veenm.paypoint.repository.CompanyRepository;
|
||||||
import nl.veenm.paypoint.repository.InviteRepository;
|
|
||||||
import nl.veenm.paypoint.repository.UserCompanyRepository;
|
|
||||||
import nl.veenm.paypoint.repository.UserRepository;
|
import nl.veenm.paypoint.repository.UserRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class CompanyService {
|
public class CompanyService {
|
||||||
@Inject
|
@Inject
|
||||||
CompanyRepository companyRepository;
|
CompanyRepository companyRepository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
UserCompanyRepository userCompanyRepository;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UserRepository userRepository;
|
UserRepository userRepository;
|
||||||
|
|
||||||
@Inject
|
public Set<Company> getCompanies(String username) {
|
||||||
InviteRepository inviteRepository;
|
AppUser user = this.userRepository.findByUsername(username);
|
||||||
|
return user.getCompanies();
|
||||||
public List<UserCompany> getCompanies(String username) {
|
|
||||||
AppUser user = userRepository.findByUsername(username);
|
|
||||||
return userCompanyRepository.getAllByUserId(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompanyDTO getCompanyById(Long id) {
|
|
||||||
return CompanyMapper.toDto(companyRepository.findById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void linkCompanyWithInvite(Long userId, String token) {
|
|
||||||
InviteEntity invite = inviteRepository.findByToken(token);
|
|
||||||
linkCompany(userId, invite.company_id);
|
|
||||||
|
|
||||||
invite.used = true;
|
|
||||||
inviteRepository.persist(invite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void linkCompany(Long userId, Long companyId) {
|
public void linkCompany(Long userId, Long companyId) {
|
||||||
AppUser user = userRepository.findById(userId);
|
AppUser user = this.userRepository.findById(userId);
|
||||||
Company company = companyRepository.findById(companyId);
|
Company company = this.companyRepository.findById(companyId);
|
||||||
|
|
||||||
UserCompany userCompany = new UserCompany();
|
System.out.println(user.getCompanies());
|
||||||
userCompany.setUser(user);
|
user.getCompanies().add(company);
|
||||||
userCompany.setCompany(company);
|
company.getUsers().add(user);
|
||||||
userCompany.setAccessLevel(AccessLevel.USER);
|
|
||||||
userCompanyRepository.persist(userCompany);
|
System.out.println(user.getCompanies());
|
||||||
|
|
||||||
|
userRepository.persist(user);
|
||||||
|
companyRepository.persist(company);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package nl.veenm.paypoint.service;
|
|||||||
import io.quarkus.mailer.Mail;
|
import io.quarkus.mailer.Mail;
|
||||||
import io.quarkus.mailer.Mailer;
|
import io.quarkus.mailer.Mailer;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import nl.veenm.paypoint.domain.AppUser;
|
import nl.veenm.paypoint.domain.AppUser;
|
||||||
import nl.veenm.paypoint.domain.Appointment;
|
import nl.veenm.paypoint.domain.Appointment;
|
||||||
import nl.veenm.paypoint.domain.Company;
|
import nl.veenm.paypoint.domain.Company;
|
||||||
@@ -12,16 +11,12 @@ import nl.veenm.paypoint.helper.EmailHelper;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class EmailService {
|
public class EmailService {
|
||||||
|
|
||||||
private final Mailer mailer;
|
private final Mailer mailer;
|
||||||
|
|
||||||
@Inject
|
|
||||||
EmailTemplateService emailTemplateService;
|
|
||||||
|
|
||||||
public EmailService(Mailer mailer) {
|
public EmailService(Mailer mailer) {
|
||||||
this.mailer = mailer;
|
this.mailer = mailer;
|
||||||
}
|
}
|
||||||
@@ -30,14 +25,14 @@ public class EmailService {
|
|||||||
Company company = appointment.getCompany();
|
Company company = appointment.getCompany();
|
||||||
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
||||||
String imageUrl = appointment.getCompany().getImg_href();
|
String imageUrl = appointment.getCompany().getImg_href();
|
||||||
String formattedDate = appointment.getStartDateTime().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
||||||
|
|
||||||
String formattedHour = String.valueOf(appointment.getStartDateTime().getHour()).length() == 1 ? "0" + appointment.getStartDateTime().getHour() : String.valueOf(appointment.getStartDateTime().getHour());
|
String formattedHour = String.valueOf(appointment.getStartHour()).length() == 1 ? "0" + appointment.getStartHour() : String.valueOf(appointment.getStartHour());
|
||||||
String formattedMinute = String.valueOf(appointment.getStartDateTime().getMinute()).length() == 1 ? "0" + appointment.getStartDateTime().getMinute() : String.valueOf(appointment.getStartDateTime().getMinute());
|
String formattedMinute = String.valueOf(appointment.getStartMinute()).length() == 1 ? "0" + appointment.getStartMinute() : String.valueOf(appointment.getStartMinute());
|
||||||
String formattedTime = formattedHour + ":" + formattedMinute;
|
String formattedTime = formattedHour + ":" + formattedMinute;
|
||||||
|
|
||||||
String formattedEndHour = String.valueOf(appointment.getEndDateTime().getHour()).length() == 1 ? "0" + appointment.getEndDateTime().getHour() : String.valueOf(appointment.getEndDateTime().getHour());
|
String formattedEndHour = String.valueOf(appointment.getEndHour()).length() == 1 ? "0" + appointment.getEndHour() : String.valueOf(appointment.getEndHour());
|
||||||
String formattedEndMinute = String.valueOf(appointment.getEndDateTime().getMinute()).length() == 1 ? "0" + appointment.getEndDateTime().getMinute() : String.valueOf(appointment.getEndDateTime().getMinute());
|
String formattedEndMinute = String.valueOf(appointment.getEndMinute()).length() == 1 ? "0" + appointment.getEndMinute() : String.valueOf(appointment.getEndMinute());
|
||||||
String formattedEndTime = formattedEndHour + ":" + formattedEndMinute;
|
String formattedEndTime = formattedEndHour + ":" + formattedEndMinute;
|
||||||
|
|
||||||
// Bouw de HTML-inhoud van de e-mail
|
// Bouw de HTML-inhoud van de e-mail
|
||||||
@@ -115,8 +110,8 @@ public class EmailService {
|
|||||||
|
|
||||||
String subject = String.format(" Afspraak bevestigd: %s", formattedDate);
|
String subject = String.format(" Afspraak bevestigd: %s", formattedDate);
|
||||||
String recipient = appointment.getCustomer().getEmail();
|
String recipient = appointment.getCustomer().getEmail();
|
||||||
LocalDateTime date = appointment.getStartDateTime();
|
LocalDateTime date = appointment.getStartDate();
|
||||||
date = date.withHour(appointment.getStartDateTime().getHour()).withMinute(appointment.getStartDateTime().getMinute());
|
date = date.withHour(appointment.getStartHour()).withMinute(appointment.getStartMinute());
|
||||||
|
|
||||||
String dtStamp = date.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
|
String dtStamp = date.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));
|
||||||
String sender = appointment.getCompany().getName() + " <paypoint@melvanveen.nl>";
|
String sender = appointment.getCompany().getName() + " <paypoint@melvanveen.nl>";
|
||||||
@@ -130,7 +125,7 @@ public class EmailService {
|
|||||||
public void stuurVerwijdering(Appointment appointment) {
|
public void stuurVerwijdering(Appointment appointment) {
|
||||||
Company company = appointment.getCompany();
|
Company company = appointment.getCompany();
|
||||||
String imageUrl = company.getImg_href();
|
String imageUrl = company.getImg_href();
|
||||||
String formattedDate = appointment.getStartDateTime().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
||||||
|
|
||||||
// Bouw de HTML-inhoud van de e-mail
|
// Bouw de HTML-inhoud van de e-mail
|
||||||
String emailBody = """
|
String emailBody = """
|
||||||
@@ -211,9 +206,9 @@ public class EmailService {
|
|||||||
Company company = appointment.getCompany();
|
Company company = appointment.getCompany();
|
||||||
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
||||||
String imageUrl = appointment.getCompany().getImg_href();
|
String imageUrl = appointment.getCompany().getImg_href();
|
||||||
String formattedDate = appointment.getStartDateTime().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
||||||
|
|
||||||
String formattedTime = String.format("%s:%s", appointment.getStartDateTime().getHour(), String.valueOf(appointment.getStartDateTime().getMinute()).length() == 1 ? "0" + appointment.getStartDateTime().getMinute() : appointment.getStartDateTime().getMinute());
|
String formattedTime = String.format("%s:%s", appointment.getStartHour(), String.valueOf(appointment.getStartMinute()).length() == 1 ? "0" + appointment.getStartMinute() : appointment.getStartMinute());
|
||||||
|
|
||||||
|
|
||||||
// Bouw de HTML-inhoud van de e-mail
|
// Bouw de HTML-inhoud van de e-mail
|
||||||
@@ -299,9 +294,9 @@ public class EmailService {
|
|||||||
Company company = appointment.getCompany();
|
Company company = appointment.getCompany();
|
||||||
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
String location = String.format("<br>%s<br>%s %s", company.getAddress(), company.getPostal_code(), company.getCity());
|
||||||
String imageUrl = appointment.getCompany().getImg_href();
|
String imageUrl = appointment.getCompany().getImg_href();
|
||||||
String formattedDate = appointment.getStartDateTime().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
String formattedDate = appointment.getStartDate().toLocalDate().format(DateTimeFormatter.ofPattern("dd MMMM yyyy", Locale.forLanguageTag("nl")));
|
||||||
|
|
||||||
String formattedTime = String.format("%s:%s", appointment.getStartDateTime().getHour(), String.valueOf(appointment.getStartDateTime().getMinute()).length() == 1 ? "0" + appointment.getStartDateTime().getMinute() : appointment.getStartDateTime().getMinute());
|
String formattedTime = String.format("%s:%s", appointment.getStartHour(), String.valueOf(appointment.getStartMinute()).length() == 1 ? "0" + appointment.getStartMinute() : appointment.getStartMinute());
|
||||||
|
|
||||||
|
|
||||||
// Bouw de HTML-inhoud van de e-mail
|
// Bouw de HTML-inhoud van de e-mail
|
||||||
@@ -383,18 +378,7 @@ public class EmailService {
|
|||||||
mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom("Hairstyling By Daan <paypoint@melvanveen.nl>").setReplyTo(company.getEmail()));
|
mailer.send(Mail.withHtml(recipient, subject, emailBody).setFrom("Hairstyling By Daan <paypoint@melvanveen.nl>").setReplyTo(company.getEmail()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stuurUitnodiging(String recipient, String agendaLink) {
|
|
||||||
Map<String, String> replacements = Map.of(
|
|
||||||
"link", agendaLink
|
|
||||||
);
|
|
||||||
|
|
||||||
String templatePath = "templates/agenda-invite.html";
|
|
||||||
String htmlBody = emailTemplateService.loadTemplate(templatePath, replacements);
|
|
||||||
|
|
||||||
mailer.send(Mail.withHtml(recipient, "Uitnodiging om agenda te bekijken", htmlBody).setFrom("PayPoint <paypoint@melvanveen.nl>"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package nl.veenm.paypoint.service;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class EmailTemplateService {
|
|
||||||
|
|
||||||
public String loadTemplate(String templatePath, Map<String, String> replacements) {
|
|
||||||
try (InputStream is = Thread.currentThread().getContextClassLoader()
|
|
||||||
.getResourceAsStream(templatePath)) {
|
|
||||||
|
|
||||||
if (is == null) {
|
|
||||||
throw new RuntimeException("Kon e-mailtemplate niet vinden!");
|
|
||||||
}
|
|
||||||
|
|
||||||
String template = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
|
||||||
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
|
||||||
template = template.replace("{{" + entry.getKey() + "}}", entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
return template;
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Kon e-mailtemplate niet inladen: " + templatePath, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="nl">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<title>Agenda-uitnodiging</title>
|
|
||||||
</head>
|
|
||||||
<body style="margin:0;padding:0;background-color:#f4f4f4;">
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f4f4;padding:20px 0;">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<table width="600" cellpadding="0" cellspacing="0"
|
|
||||||
style="background-color:#ffffff;border-radius:8px;padding:30px;font-family:sans-serif;">
|
|
||||||
|
|
||||||
<!-- Logo -->
|
|
||||||
<tr>
|
|
||||||
<td style="text-align:center;padding-bottom:20px;">
|
|
||||||
<img
|
|
||||||
src="https://paypoint.melvanveen.nl/assets/logo-minimal.png"
|
|
||||||
alt="Agenda logo"
|
|
||||||
style="max-width:200px;height:auto;margin-bottom:10px;"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Titel -->
|
|
||||||
<tr>
|
|
||||||
<td style="text-align:center;padding-bottom:20px;">
|
|
||||||
<h2 style="margin:0;color:#1f2937;">Uitnodiging om een agenda te bekijken</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Inhoud -->
|
|
||||||
<tr>
|
|
||||||
<td style="font-size:16px;color:#374151;line-height:1.6;text-align: center;">
|
|
||||||
<p>
|
|
||||||
Je bent uitgenodigd om een agenda te bekijken of eraan deel te nemen.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Klik op onderstaande knop om toegang te krijgen:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="text-align:center;margin:30px 0;">
|
|
||||||
<a
|
|
||||||
href="{{link}}"
|
|
||||||
style="background-color:#3b82f6;color:#ffffff;padding:12px 24px;border-radius:6px;text-decoration:none;display:inline-block;font-weight:bold;"
|
|
||||||
>
|
|
||||||
Bekijk de agenda
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<tr>
|
|
||||||
<td style="font-size:12px;text-align:center;color:#9ca3af;padding-top:30px;">
|
|
||||||
Als je deze uitnodiging niet verwachtte, kun je deze e-mail negeren.
|
|
||||||
<p>© 2025 PayPoint. Alle rechten voorbehouden.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user