Compare commits
80 Commits
d145fc1b2e
...
dev-comp
| Author | SHA1 | Date | |
|---|---|---|---|
| 73f026210c | |||
| 4b969e6d69 | |||
| 4706af27f8 | |||
| 3e8c19534b | |||
| a1b5ca2694 | |||
| c5f7b81ac3 | |||
| 7f999733dc | |||
| 0ac92fcda3 | |||
| 8e01fb46f8 | |||
| 09a51edd5f | |||
| 354fbfede9 | |||
| ef5b707697 | |||
| 489bfeb354 | |||
| bb901392fc | |||
| 6f61db6817 | |||
| 00701fb874 | |||
| 936392f8bd | |||
| f6d4bb0fe4 | |||
| 160c7d59e3 | |||
| 9689201a8c | |||
| 083d72fbfa | |||
| 1c7466d883 | |||
| c9c8c8536d | |||
| b1bcf75e56 | |||
| b78b3f005b | |||
| a83088387b | |||
| 22fa896ee0 | |||
| f8976deb91 | |||
| eb9badb4a1 | |||
| 661fcdb16b | |||
| b2ad633b21 | |||
| 1b5bf8ba6c | |||
| bf75d9d036 | |||
| 9457c5749a | |||
| c7f56881cd | |||
| aebcd62aa9 | |||
| c2eecf4906 | |||
| 87b3bc12e0 | |||
| 3d3d63e58c | |||
| 81c115c655 | |||
| a7ba1d16a4 | |||
| 645949a2f6 | |||
| beb40db1b1 | |||
| 61a4af6ff1 | |||
| d9fc68298c | |||
| fccea5bf6a | |||
| ee476cd0e2 | |||
| b320d7db37 | |||
| 80fef98e07 | |||
| 7e80703c04 | |||
| cc4a3e4e06 | |||
| 9e28356f2c | |||
| 77d66813c7 | |||
| 7625da1d4b | |||
| 4262845074 | |||
| b84e10de44 | |||
| ac6563ac95 | |||
| baf57c3464 | |||
| d1c7f37a94 | |||
| 587173c79f | |||
| 0fc871bd46 | |||
| 2a1bdfbdcb | |||
| 11dca5630c | |||
| dedae02676 | |||
| 9e9391465d | |||
| 18ea38f85a | |||
| d740ad255f | |||
| 49bb471b60 | |||
| fee96e7900 | |||
| 1e37c43dcd | |||
| 15f65b1014 | |||
| 0a56f8c180 | |||
| 0563c7c8de | |||
| 09f6cd7463 | |||
| 7bd5e7baa5 | |||
| f75e805cc0 | |||
| 1cd4a1ff97 | |||
| 41a88ea914 | |||
| c85c28fee2 | |||
| 580104de00 |
@@ -76,6 +76,7 @@ jobs:
|
||||
key: ${{ secrets.SSH_KEY }}
|
||||
script: |
|
||||
cd ${{ secrets.TARGET_DIR }}
|
||||
docker logs ffsaf > "log/ffsaf_logs_$(date +"%Y-%m-%d_%H-%M-%S").log" 2>&1
|
||||
docker stop ffsaf
|
||||
docker rm ffsaf
|
||||
docker compose up --build -d ffsaf
|
||||
|
||||
5
pom.xml
5
pom.xml
@@ -133,6 +133,11 @@
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-mailer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-websockets-next</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
package fr.titionfire.ffsaf.data.id;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import lombok.Data;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@Embeddable
|
||||
public class RegisterId implements Serializable {
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_competition")
|
||||
private CompetitionModel competition;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "id_membre")
|
||||
private MembreModel membre;
|
||||
private Long competitionId;
|
||||
private Long membreId;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ public class AffiliationRequestModel {
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
long siret;
|
||||
String RNA;
|
||||
String state_id;
|
||||
String address;
|
||||
String contact;
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "cardboard")
|
||||
public class CardboardModel {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "comb", referencedColumnName = "id")
|
||||
MembreModel comb;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "guest_comb", referencedColumnName = "id")
|
||||
CompetitionGuestModel guestComb;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "match", referencedColumnName = "id")
|
||||
MatchModel match;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "compet", referencedColumnName = "id")
|
||||
CompetitionModel compet;
|
||||
|
||||
int red;
|
||||
int yellow;
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import java.util.List;
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "poule")
|
||||
public class PouleModel {
|
||||
@Table(name = "category")
|
||||
public class CategoryModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
@@ -34,12 +34,14 @@ public class PouleModel {
|
||||
CompetitionModel compet;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
||||
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||
List<MatchModel> matchs;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
||||
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||
List<TreeModel> tree;
|
||||
|
||||
Integer type;
|
||||
|
||||
String liceName = "1";
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "checkout")
|
||||
public class CheckoutModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Schema(description = "Identifiant du checkout", example = "42")
|
||||
Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "membre", referencedColumnName = "id")
|
||||
MembreModel membre;
|
||||
|
||||
Date creationDate = new Date();
|
||||
|
||||
List<Long> licenseIds;
|
||||
|
||||
Integer checkoutId;
|
||||
|
||||
PaymentStatus paymentStatus;
|
||||
|
||||
public enum PaymentStatus {
|
||||
PENDING, AUTHORIZED, REFUSED, UNKNOW, REGISTERED, REFUNDING, REFUNDED, CONTESTED
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,8 @@ public class ClubModel implements LoggableModel {
|
||||
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris")
|
||||
String address;
|
||||
|
||||
@Schema(description = "RNA du club", example = "W123456789")
|
||||
String RNA;
|
||||
|
||||
@Schema(description = "Numéro SIRET du club", example = "12345678901234")
|
||||
Long SIRET;
|
||||
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234")
|
||||
String StateId;
|
||||
|
||||
@Schema(description = "Numéro d'affiliation du club", example = "12345")
|
||||
Long no_affiliation;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "competition_guest")
|
||||
public class CompetitionGuestModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "competition", referencedColumnName = "id")
|
||||
CompetitionModel competition;
|
||||
|
||||
String lname = "";
|
||||
String fname = "";
|
||||
|
||||
Categorie categorie = null;
|
||||
|
||||
String club = null;
|
||||
|
||||
Genre genre = null;
|
||||
|
||||
String country = "fr";
|
||||
|
||||
Integer weight = null;
|
||||
|
||||
public CompetitionGuestModel(String s) {
|
||||
this.fname = s.substring(0, s.indexOf(" "));
|
||||
this.lname = s.substring(s.indexOf(" ") + 1);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return fname + " " + lname;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -8,6 +9,7 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,6 +23,7 @@ import java.util.List;
|
||||
@Table(name = "compet")
|
||||
public class CompetitionModel {
|
||||
@Id
|
||||
@Access(AccessType.PROPERTY)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@@ -36,9 +39,36 @@ public class CompetitionModel {
|
||||
String uuid;
|
||||
|
||||
Date date;
|
||||
Date todate;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
String description;
|
||||
String adresse;
|
||||
|
||||
Date startRegister;
|
||||
Date endRegister;
|
||||
|
||||
RegisterMode registerMode;
|
||||
|
||||
boolean publicVisible;
|
||||
|
||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
List<RegisterModel> insc;
|
||||
|
||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
List<CompetitionGuestModel> guests = new ArrayList<>();
|
||||
|
||||
|
||||
List<Long> banMembre = new ArrayList<>();
|
||||
|
||||
String owner;
|
||||
|
||||
List<String> admin = new ArrayList<>();
|
||||
@Column(name = "table_")
|
||||
List<String> table = new ArrayList<>();
|
||||
|
||||
String data1;
|
||||
String data2;
|
||||
String data3;
|
||||
String data4;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package fr.titionfire.ffsaf.data.model;
|
||||
|
||||
import fr.titionfire.ffsaf.data.id.RegisterId;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
|
||||
@Entity
|
||||
@Table(name = "helloasso_register")
|
||||
public class HelloAssoRegisterModel {
|
||||
@EmbeddedId
|
||||
RegisterId id;
|
||||
|
||||
@MapsId("competitionId")
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "id_competition")
|
||||
CompetitionModel competition;
|
||||
|
||||
@MapsId("membreId")
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "id_membre")
|
||||
MembreModel membre;
|
||||
|
||||
Integer orderId;
|
||||
|
||||
public HelloAssoRegisterModel(CompetitionModel competition, MembreModel membre, Integer orderId) {
|
||||
this.id = new RegisterId(competition.getId(), membre.getId());
|
||||
this.competition = competition;
|
||||
this.membre = membre;
|
||||
this.orderId = orderId;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
@Entity
|
||||
@Table(name = "licence")
|
||||
public class LicenceModel {
|
||||
public class LicenceModel implements LoggableModel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Schema(description = "L'identifiant de la licence.")
|
||||
@@ -30,9 +30,23 @@ public class LicenceModel {
|
||||
@Schema(description = "La saison de la licence.", example = "2025")
|
||||
int saison;
|
||||
|
||||
@Schema(description = "Nom du médecin sur certificat médical.", example = "M. Jean")
|
||||
@Schema(description = "Nom et date du médecin sur certificat médical.", example = "M. Jean¤2025-02-03", format = "<Nom>¤<yyyy-mm-dd>")
|
||||
String certificate;
|
||||
|
||||
@Schema(description = "Licence validée", example = "true")
|
||||
boolean validate;
|
||||
|
||||
@Schema(description = "Licence payer", example = "true")
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
boolean pay = false;
|
||||
|
||||
@Override
|
||||
public String getObjectName() {
|
||||
return "licence " + id.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogModel.ObjectType getObjectType() {
|
||||
return LogModel.ObjectType.Licence;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ public class LogModel {
|
||||
|
||||
Long target_id;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
String target_name;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
String message;
|
||||
|
||||
public enum ActionType {
|
||||
|
||||
@@ -7,6 +7,7 @@ import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@@ -32,25 +33,65 @@ public class MatchModel {
|
||||
@JoinColumn(name = "c1", referencedColumnName = "id")
|
||||
MembreModel c1_id = null;
|
||||
|
||||
String c1_str = null;
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c1_guest", referencedColumnName = "id")
|
||||
CompetitionGuestModel c1_guest = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c2", referencedColumnName = "id")
|
||||
MembreModel c2_id = null;
|
||||
|
||||
String c2_str = null;
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "c2_guest", referencedColumnName = "id")
|
||||
CompetitionGuestModel c2_guest = null;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
||||
PouleModel poule = null;
|
||||
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||
CategoryModel category = null;
|
||||
|
||||
long poule_ord = 0;
|
||||
long category_ord = 0;
|
||||
|
||||
boolean isEnd = true;
|
||||
|
||||
Date date = null;
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "score", joinColumns = @JoinColumn(name = "id_match"))
|
||||
List<ScoreEmbeddable> scores = new ArrayList<>();
|
||||
|
||||
char groupe = 'A';
|
||||
char poule = 'A';
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "match", referencedColumnName = "id")
|
||||
List<CardboardModel> cardboard = new ArrayList<>();
|
||||
|
||||
public String getC1Name() {
|
||||
if (c1_id != null)
|
||||
return c1_id.fname + " " + c1_id.lname;
|
||||
if (c1_guest != null)
|
||||
return c1_guest.fname + " " + c1_guest.lname;
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getC2Name() {
|
||||
if (c2_id != null)
|
||||
return c2_id.fname + " " + c2_id.lname;
|
||||
if (c2_guest != null)
|
||||
return c2_guest.fname + " " + c2_guest.lname;
|
||||
return "";
|
||||
}
|
||||
|
||||
public int win() {
|
||||
int sum = 0;
|
||||
for (ScoreEmbeddable score : this.getScores()) {
|
||||
if (score.getS1() == -1000 || score.getS2() == -1000)
|
||||
continue;
|
||||
|
||||
if (score.getS1() > score.getS2())
|
||||
sum++;
|
||||
else if (score.getS1() < score.getS2())
|
||||
sum--;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +82,22 @@ public class MembreModel implements LoggableModel {
|
||||
public LogModel.ObjectType getObjectType() {
|
||||
return LogModel.ObjectType.Membre;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MembreModel{" +
|
||||
"id=" + id +
|
||||
", userId='" + userId + '\'' +
|
||||
", lname='" + lname + '\'' +
|
||||
", fname='" + fname + '\'' +
|
||||
", categorie=" + categorie +
|
||||
", genre=" + genre +
|
||||
", licence=" + licence +
|
||||
", country='" + country + '\'' +
|
||||
", birth_date=" + birth_date +
|
||||
", email='" + email + '\'' +
|
||||
", role=" + role +
|
||||
", grade_arbitrage=" + grade_arbitrage +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@@ -17,14 +19,17 @@ import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "register")
|
||||
@IdClass(RegisterId.class)
|
||||
public class RegisterModel {
|
||||
@Id
|
||||
|
||||
@EmbeddedId
|
||||
RegisterId id;
|
||||
|
||||
@MapsId("competitionId")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "id_competition")
|
||||
CompetitionModel competition;
|
||||
|
||||
@Id
|
||||
@MapsId("membreId")
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "id_membre")
|
||||
MembreModel membre;
|
||||
@@ -35,6 +40,30 @@ public class RegisterModel {
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "club")
|
||||
@OnDelete(action = OnDeleteAction.SET_NULL)
|
||||
ClubModel club = null;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
boolean lockEdit = false;
|
||||
|
||||
public RegisterModel(CompetitionModel competition, MembreModel membre, Integer weight, int overCategory,
|
||||
Categorie categorie, ClubModel club) {
|
||||
this.id = new RegisterId(competition.getId(), membre.getId());
|
||||
this.competition = competition;
|
||||
this.membre = membre;
|
||||
this.weight = weight;
|
||||
this.overCategory = overCategory;
|
||||
this.categorie = categorie;
|
||||
this.club = club;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return membre.fname + " " + membre.lname;
|
||||
}
|
||||
|
||||
public ClubModel getClub2() {
|
||||
if (club == null)
|
||||
return membre.club;
|
||||
return club;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@@ -20,8 +23,8 @@ public class TreeModel {
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
|
||||
@Column(name = "id_poule")
|
||||
Long poule;
|
||||
@Column(name = "id_category")
|
||||
Long category;
|
||||
|
||||
Integer level;
|
||||
|
||||
@@ -36,4 +39,20 @@ public class TreeModel {
|
||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(referencedColumnName = "id")
|
||||
TreeModel right;
|
||||
|
||||
public List<TreeModel> flat() {
|
||||
List<TreeModel> out = new ArrayList<>();
|
||||
this.flat(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private void flat(List<TreeModel> out) {
|
||||
out.add(this);
|
||||
|
||||
if (this.right != null)
|
||||
this.right.flat(out);
|
||||
|
||||
if (this.left != null)
|
||||
this.left.flat(out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CardboardModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CardboardRepository implements PanacheRepositoryBase<CardboardModel, Long> {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CategoryRepository implements PanacheRepositoryBase<CategoryModel, Long> {
|
||||
|
||||
public Uni<CategoryModel> create(CategoryModel categoryModel) {
|
||||
categoryModel.setSystem(CompetitionSystem.INTERNAL);
|
||||
return Panache.withTransaction(() -> this.persist(categoryModel)
|
||||
.invoke(categoryModel1 -> categoryModel1.setSystemId(categoryModel1.getId())))
|
||||
.chain(this::persist);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
||||
import fr.titionfire.ffsaf.data.model.CheckoutModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class PouleRepository implements PanacheRepositoryBase<PouleModel, Long> {
|
||||
public class CheckoutRepository implements PanacheRepositoryBase<CheckoutModel, Long> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CompetitionGuestRepository implements PanacheRepositoryBase<CompetitionGuestModel, Long> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.HelloAssoRegisterModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class HelloAssoRegisterRepository implements PanacheRepositoryBase<HelloAssoRegisterModel, Long> {
|
||||
}
|
||||
@@ -1,9 +1,30 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
public class MatchRepository implements PanacheRepositoryBase<MatchModel, Long> {
|
||||
|
||||
public Uni<MatchModel> create(MatchModel matchModel) {
|
||||
matchModel.setSystem(CompetitionSystem.INTERNAL);
|
||||
return Panache.withTransaction(() -> this.persistAndFlush(matchModel)
|
||||
.invoke(matchModel1 -> matchModel1.setSystemId(matchModel1.getId())))
|
||||
.chain(this::persist);
|
||||
}
|
||||
|
||||
public Uni<Void> create(List<MatchModel> matchModel) {
|
||||
matchModel.forEach(model -> model.setSystem(CompetitionSystem.INTERNAL));
|
||||
return Panache.withTransaction(() -> this.persist(matchModel)
|
||||
.call(__ -> this.flush())
|
||||
.invoke(__ -> matchModel.forEach(model -> model.setSystemId(model.getId())))
|
||||
.map(__ -> matchModel))
|
||||
.chain(this::persist);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.id.RegisterId;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class RegisterRepository implements PanacheRepository<RegisterModel> {
|
||||
public class RegisterRepository implements PanacheRepositoryBase<RegisterModel, RegisterId> {
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,22 @@ package fr.titionfire.ffsaf.data.repository;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@ApplicationScoped
|
||||
public class TreeRepository implements PanacheRepositoryBase<TreeModel, Long> {
|
||||
|
||||
@WithTransaction
|
||||
public Uni<Boolean> deleteTree(TreeModel entity) {
|
||||
Uni<Boolean> uni = Uni.createFrom().item(false);
|
||||
if (entity == null)
|
||||
return uni;
|
||||
if (entity.getLeft() != null)
|
||||
uni = uni.chain(__ -> this.deleteTree(entity.getLeft()));
|
||||
if (entity.getRight() != null)
|
||||
uni = uni.chain(__ -> this.deleteTree(entity.getRight()));
|
||||
return uni.chain(__ -> this.deleteById(entity.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CardboardModel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CardboardEntity {
|
||||
long comb_id;
|
||||
long match_id;
|
||||
long compet_id;
|
||||
|
||||
int red;
|
||||
int yellow;
|
||||
|
||||
public static CardboardEntity fromModel(CardboardModel model) {
|
||||
return new CardboardEntity(
|
||||
model.getComb() != null ? model.getComb().getId() : model.getGuestComb().getId() * -1,
|
||||
model.getMatch().getId(),
|
||||
model.getCompet().getId(),
|
||||
model.getRed(), model.getYellow());
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,7 @@ public class ClubEntity {
|
||||
private String training_location;
|
||||
private String training_day_time;
|
||||
private String contact_intern;
|
||||
private String RNA;
|
||||
private Long SIRET;
|
||||
private String StateId;
|
||||
private Long no_affiliation;
|
||||
private boolean international;
|
||||
|
||||
@@ -41,8 +40,7 @@ public class ClubEntity {
|
||||
.training_location(model.getTraining_location())
|
||||
.training_day_time(model.getTraining_day_time())
|
||||
.contact_intern(model.getContact_intern())
|
||||
.RNA(model.getRNA())
|
||||
.SIRET(model.getSIRET())
|
||||
.StateId(model.getStateId())
|
||||
.no_affiliation(model.getNo_affiliation())
|
||||
.international(model.isInternational())
|
||||
.build();
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CombEntity {
|
||||
private long id;
|
||||
private String lname;
|
||||
private String fname;
|
||||
Categorie categorie;
|
||||
String club_uuid;
|
||||
String club_str;
|
||||
Genre genre;
|
||||
String country;
|
||||
int overCategory;
|
||||
Integer weight;
|
||||
|
||||
public static CombEntity fromModel(MembreModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(),
|
||||
model.getClub() == null ? null : model.getClub().getClubId(),
|
||||
model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(),
|
||||
0, null);
|
||||
}
|
||||
|
||||
|
||||
public static CombEntity fromModel(CompetitionGuestModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new CombEntity(model.getId() * -1, model.getLname(), model.getFname(), model.getCategorie(), null,
|
||||
model.getClub(), model.getGenre(), model.getCountry(), 0, model.getWeight());
|
||||
}
|
||||
|
||||
public static CombEntity fromModel(RegisterModel registerModel) {
|
||||
if (registerModel == null || registerModel.getMembre() == null)
|
||||
return null;
|
||||
MembreModel model = registerModel.getMembre();
|
||||
|
||||
return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(),
|
||||
registerModel.getClub2() == null ? null : registerModel.getClub2().getClubId(),
|
||||
registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(),
|
||||
model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class MatchEntity {
|
||||
private long id;
|
||||
private CombEntity c1;
|
||||
private CombEntity c2;
|
||||
private long categorie_ord = 0;
|
||||
private boolean isEnd;
|
||||
private long categorie;
|
||||
private Date date;
|
||||
private List<ScoreEmbeddable> scores;
|
||||
private char poule;
|
||||
private List<CardboardEntity> cardboard;
|
||||
|
||||
public static MatchEntity fromModel(MatchModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
return new MatchEntity(model.getId(),
|
||||
(model.getC1_id() == null) ? CombEntity.fromModel(model.getC1_guest()) : CombEntity.fromModel(
|
||||
model.getC1_id()),
|
||||
(model.getC2_id() == null) ? CombEntity.fromModel(model.getC2_guest()) : CombEntity.fromModel(
|
||||
model.getC2_id()),
|
||||
model.getCategory_ord(), model.isEnd(), model.getCategory().getId(), model.getDate(),
|
||||
model.getScores(),
|
||||
model.getPoule(),
|
||||
(model.getCardboard() == null) ? new ArrayList<>() : model.getCardboard().stream()
|
||||
.map(CardboardEntity::fromModel).toList());
|
||||
}
|
||||
|
||||
public int win() {
|
||||
int sum = 0;
|
||||
for (ScoreEmbeddable score : scores) {
|
||||
if (score.getS1() == -1000 || score.getS2() == -1000)
|
||||
continue;
|
||||
|
||||
if (score.getS1() > score.getS2())
|
||||
sum++;
|
||||
else if (score.getS1() < score.getS2())
|
||||
sum--;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package fr.titionfire.ffsaf.domain.entity;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class TreeEntity {
|
||||
private Long id;
|
||||
private Long categorie;
|
||||
private Integer level;
|
||||
private MatchEntity match;
|
||||
private TreeEntity left;
|
||||
private TreeEntity right;
|
||||
private TreeEntity associatedNode;
|
||||
|
||||
public static TreeEntity fromModel(TreeModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new TreeEntity(model.getId(), model.getCategory(), model.getLevel(), MatchEntity.fromModel(model.getMatch()), fromModel(model.getLeft()),
|
||||
fromModel(model.getRight()), null);
|
||||
}
|
||||
|
||||
public TreeEntity getMatchNode(Long matchId) {
|
||||
if (this.match != null && this.match.getId() == matchId) {
|
||||
return this;
|
||||
} else {
|
||||
if (this.left != null) {
|
||||
TreeEntity left = this.left.getMatchNode(matchId);
|
||||
if (left != null) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
if (this.right != null) {
|
||||
TreeEntity right = this.right.getMatchNode(matchId);
|
||||
if (right != null) {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TreeEntity getParent(TreeEntity current, TreeEntity target) {
|
||||
if (current == null) {
|
||||
return null;
|
||||
} else if (current.equals(target)) {
|
||||
return null;
|
||||
} else if (target.equals(current.left) || target.equals(current.right)) {
|
||||
return current;
|
||||
} else {
|
||||
TreeEntity left = getParent(current.left, target);
|
||||
if (left != null)
|
||||
return left;
|
||||
return getParent(current.right, target);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAssociated(TreeEntity current, TreeEntity next) {
|
||||
if (current == null || next == null) {
|
||||
return;
|
||||
}
|
||||
current.setAssociatedNode(next);
|
||||
setAssociated(current.getLeft(), next.getLeft());
|
||||
setAssociated(current.getRight(), next.getRight());
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.rest.client.SirenService;
|
||||
import fr.titionfire.ffsaf.rest.client.StateIdService;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleAffiliation;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleReqAffiliation;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
@@ -20,23 +22,20 @@ import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class AffiliationService {
|
||||
private static final Logger LOGGER = Logger.getLogger(AffiliationService.class);
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
@@ -62,6 +61,15 @@ public class AffiliationService {
|
||||
@Inject
|
||||
ReactiveMailer reactiveMailer;
|
||||
|
||||
@Inject
|
||||
LoggerService ls;
|
||||
|
||||
@RestClient
|
||||
StateIdService stateIdService;
|
||||
|
||||
@RestClient
|
||||
SirenService sirenService;
|
||||
|
||||
@ConfigProperty(name = "upload_dir")
|
||||
String media;
|
||||
|
||||
@@ -75,6 +83,8 @@ public class AffiliationService {
|
||||
public Uni<AffiliationRequestModel> pre_save(AffiliationRequestForm form, boolean unique) {
|
||||
AffiliationRequestModel affModel = form.toModel();
|
||||
int currentSaison = Utils.getSaison();
|
||||
List<String> out = new ArrayList<>();
|
||||
out.add(affModel.getState_id());
|
||||
|
||||
return Uni.createFrom().item(affModel)
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
@@ -82,14 +92,26 @@ public class AffiliationService {
|
||||
throw new DBadRequestException("Saison non valid");
|
||||
}
|
||||
}))
|
||||
.chain(() -> repositoryRequest.count("siret = ?1 and saison = ?2", affModel.getSiret(),
|
||||
affModel.getSaison()))
|
||||
.chain(() -> ((affModel.getState_id().charAt(0) == 'W') ? stateIdService.get_rna(
|
||||
affModel.getState_id()) : sirenService.get_unite(affModel.getState_id())
|
||||
.chain(stateIdService::getAssoDataFromUnit)).onItem().transform(o -> {
|
||||
if (o.getRna() != null && !o.getRna().isBlank())
|
||||
out.add(o.getRna());
|
||||
if (o.getSiren() != null && !o.getSiren().isBlank())
|
||||
out.add(o.getSiren());
|
||||
if (o.getIdentite().getSiret_siege() != null && !o.getIdentite().getSiret_siege().isBlank())
|
||||
out.add(o.getIdentite().getSiret_siege());
|
||||
return out;
|
||||
}).onFailure().recoverWithItem(out)
|
||||
.chain(a -> repositoryRequest.count("state_id IN ?1 and saison = ?2",
|
||||
out, affModel.getSaison()))
|
||||
.onItem().invoke(Unchecked.consumer(count -> {
|
||||
if (count != 0 && unique) {
|
||||
throw new DBadRequestException("Demande d'affiliation déjà existante");
|
||||
}
|
||||
}))
|
||||
.chain(() -> clubRepository.find("SIRET = ?1", affModel.getSiret()).firstResult().chain(club ->
|
||||
)
|
||||
.chain(() -> clubRepository.find("StateId IN ?1", out).firstResult().chain(club ->
|
||||
repository.count("club = ?1 and saison = ?2", club, affModel.getSaison())))
|
||||
.onItem().invoke(Unchecked.consumer(count -> {
|
||||
if (count != 0) {
|
||||
@@ -126,7 +148,6 @@ public class AffiliationService {
|
||||
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
|
||||
.chain(origine -> {
|
||||
origine.setName(model.getName());
|
||||
origine.setRNA(model.getRNA());
|
||||
origine.setAddress(model.getAddress());
|
||||
origine.setContact(model.getContact());
|
||||
origine.setM1_lname(model.getM1_lname());
|
||||
@@ -150,6 +171,9 @@ public class AffiliationService {
|
||||
}
|
||||
|
||||
public Uni<String> save(AffiliationRequestForm form) {
|
||||
LOGGER.debug("Affiliation Request Created");
|
||||
LOGGER.debug(form.toString());
|
||||
|
||||
// noinspection ResultOfMethodCallIgnored,ReactiveStreamsUnusedPublisher
|
||||
return pre_save(form, true)
|
||||
.chain(model -> Panache.withTransaction(() -> repositoryRequest.persist(model)))
|
||||
@@ -173,12 +197,14 @@ public class AffiliationService {
|
||||
}
|
||||
|
||||
public Uni<?> saveAdmin(AffiliationRequestSaveForm form) {
|
||||
LOGGER.debug("Affiliation Request Saved");
|
||||
LOGGER.debug(form.toString());
|
||||
|
||||
return repositoryRequest.findById(form.getId())
|
||||
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
|
||||
.map(model -> {
|
||||
model.setName(form.getName());
|
||||
model.setSiret(form.getSiret());
|
||||
model.setRNA(form.getRna());
|
||||
model.setState_id(form.getState_id());
|
||||
model.setAddress(form.getAddress());
|
||||
model.setContact(form.getContact());
|
||||
|
||||
@@ -263,24 +289,34 @@ public class AffiliationService {
|
||||
}).call(m -> Panache.withTransaction(() -> combRepository.persist(m)));
|
||||
}
|
||||
})
|
||||
.call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId()) :
|
||||
.call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId())
|
||||
.onFailure().invoke(t -> LOGGER.warnf("Failed to init account: %s", t.getMessage())).onFailure()
|
||||
.recoverWithNull() :
|
||||
keycloakService.setClubGroupMembre(m, club).map(__ -> m.getUserId()))
|
||||
.call(userId -> keycloakService.setAutoRoleMembre(userId, m.getRole(), m.getGrade_arbitrage())))
|
||||
.call(userId -> keycloakService.setAutoRoleMembre(userId, m.getRole(), m.getGrade_arbitrage()))
|
||||
.call(userId -> keycloakService.setEmail(userId, m.getEmail())))
|
||||
.call(m -> Mutiny.fetch(m.getLicences())
|
||||
.call(l1 -> l1 != null && l1.stream().anyMatch(l -> l.getSaison() == saison) ?
|
||||
Uni.createFrom().nullItem() :
|
||||
Panache.withTransaction(() -> licenceRepository.persist(
|
||||
new LicenceModel(null, m, club.getId(), saison, null, true)))));
|
||||
new LicenceModel(null, m, club.getId(), saison, null, true, false)))
|
||||
.call(licenceModel -> ls.logA(LogModel.ActionType.ADD, m.getObjectName(),
|
||||
licenceModel))));
|
||||
}
|
||||
|
||||
public Uni<?> accept(AffiliationRequestSaveForm form) {
|
||||
LOGGER.debug("Affiliation Request Accepted");
|
||||
LOGGER.debug(form.toString());
|
||||
|
||||
return repositoryRequest.findById(form.getId())
|
||||
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
|
||||
.chain(req ->
|
||||
clubRepository.find("SIRET = ?1", form.getSiret()).firstResult()
|
||||
clubRepository.find("StateId = ?1", form.getState_id()).firstResult()
|
||||
.chain(model -> (model == null) ? acceptNew(form, req) : acceptOld(form, req, model))
|
||||
.call(club -> setMembre(form.new Member(1), club, req.getSaison())
|
||||
.call(__ -> setMembre(form.new Member(2), club, req.getSaison())
|
||||
.call(club -> setMembre(form.new Member(1), club, req.getSaison()).onFailure()
|
||||
.recoverWithNull()
|
||||
.call(__ -> setMembre(form.new Member(2), club, req.getSaison()).onFailure()
|
||||
.recoverWithNull()
|
||||
.call(___ -> setMembre(form.new Member(3), club, req.getSaison()))))
|
||||
.onItem()
|
||||
.invoke(model -> Uni.createFrom()
|
||||
@@ -299,13 +335,13 @@ public class AffiliationService {
|
||||
}
|
||||
|
||||
private Uni<ClubModel> acceptNew(AffiliationRequestSaveForm form, AffiliationRequestModel model) {
|
||||
LOGGER.debug("New Club Accepted");
|
||||
return Uni.createFrom().nullItem()
|
||||
.chain(() -> {
|
||||
ClubModel club = new ClubModel();
|
||||
club.setName(form.getName());
|
||||
club.setCountry("FR");
|
||||
club.setSIRET(form.getSiret());
|
||||
club.setRNA(form.getRna());
|
||||
club.setStateId(form.getState_id());
|
||||
club.setAddress(form.getAddress());
|
||||
club.setContact_intern(form.getContact());
|
||||
club.setAffiliations(new ArrayList<>());
|
||||
@@ -337,17 +373,24 @@ public class AffiliationService {
|
||||
}
|
||||
|
||||
private Uni<ClubModel> acceptOld(AffiliationRequestSaveForm form, AffiliationRequestModel model, ClubModel club) {
|
||||
AtomicBoolean nameChange = new AtomicBoolean(false);
|
||||
LOGGER.debug("Old Club Accepted");
|
||||
return Uni.createFrom().nullItem()
|
||||
.chain(() -> {
|
||||
if (!form.getName().equals(club.getName())) {
|
||||
club.setName(form.getName());
|
||||
nameChange.set(true);
|
||||
}
|
||||
club.setCountry("FR");
|
||||
club.setSIRET(form.getSiret());
|
||||
club.setRNA(form.getRna());
|
||||
club.setStateId(form.getState_id());
|
||||
club.setAddress(form.getAddress());
|
||||
club.setContact_intern(form.getContact());
|
||||
return Panache.withTransaction(() -> clubRepository.persist(club)
|
||||
.chain(() -> repository.persist(new AffiliationModel(null, club, model.getSaison())))
|
||||
.chain(() -> repositoryRequest.delete(model)));
|
||||
.chain(() -> repositoryRequest.delete(model)))
|
||||
.call(() -> nameChange.get() ? keycloakService.updateGroupFromClub(
|
||||
club) // update group in keycloak
|
||||
: Uni.createFrom().nullItem());
|
||||
})
|
||||
.map(__ -> club);
|
||||
}
|
||||
@@ -355,7 +398,7 @@ public class AffiliationService {
|
||||
public Uni<SimpleReqAffiliation> getRequest(long id) {
|
||||
return repositoryRequest.findById(id).map(SimpleReqAffiliation::fromModel)
|
||||
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
|
||||
.call(out -> clubRepository.find("SIRET = ?1", out.getSiret()).firstResult().invoke(c -> {
|
||||
.call(out -> clubRepository.find("StateId = ?1", out.getStateId()).firstResult().invoke(c -> {
|
||||
if (c != null) {
|
||||
out.setClub(c.getId());
|
||||
out.setClub_name(c.getName());
|
||||
@@ -368,7 +411,7 @@ public class AffiliationService {
|
||||
public Uni<List<SimpleAffiliation>> getCurrentSaisonAffiliation() {
|
||||
return repositoryRequest.list("saison = ?1 or saison = ?1 + 1", Utils.getSaison())
|
||||
.map(models -> models.stream()
|
||||
.map(model -> new SimpleAffiliation(model.getId() * -1, model.getSiret(), model.getSaison(),
|
||||
.map(model -> new SimpleAffiliation(model.getId() * -1, model.getState_id(), model.getSaison(),
|
||||
false)).toList())
|
||||
.chain(aff -> repository.list("saison = ?1", Utils.getSaison())
|
||||
.map(models -> models.stream().map(SimpleAffiliation::fromModel).toList())
|
||||
@@ -380,9 +423,9 @@ public class AffiliationService {
|
||||
return clubRepository.findById(id)
|
||||
.onItem().ifNull().failWith(new DNotFoundException("Club non trouvé"))
|
||||
.call(model -> Mutiny.fetch(model.getAffiliations()))
|
||||
.chain(model -> repositoryRequest.list("siret = ?1", model.getSIRET())
|
||||
.chain(model -> repositoryRequest.list("state_id = ?1", model.getStateId())
|
||||
.map(reqs -> reqs.stream().map(req ->
|
||||
new SimpleAffiliation(req.getId() * -1, model.getId(), req.getSaison(), false)))
|
||||
new SimpleAffiliation(req.getId() * -1, model.getStateId(), req.getSaison(), false)))
|
||||
.map(aff2 -> Stream.concat(aff2,
|
||||
model.getAffiliations().stream().map(SimpleAffiliation::fromModel)).toList())
|
||||
);
|
||||
@@ -412,9 +455,9 @@ public class AffiliationService {
|
||||
return Panache.withTransaction(() -> repository.deleteById(id));
|
||||
}
|
||||
|
||||
public Uni<?> deleteReqAffiliation(long id, String reason) {
|
||||
public Uni<?> deleteReqAffiliation(long id, String reason, boolean federationAdmin) {
|
||||
return repositoryRequest.findById(id)
|
||||
.call(aff -> reactiveMailer.send(
|
||||
.call(aff -> federationAdmin ? reactiveMailer.send(
|
||||
Mail.withText(aff.getM1_email(),
|
||||
"FFSAF - Votre demande d'affiliation a été rejetée.",
|
||||
String.format(
|
||||
@@ -431,7 +474,7 @@ public class AffiliationService {
|
||||
""", aff.getName(), reason)
|
||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
|
||||
.addTo(aff.getM2_email(), aff.getM3_email())
|
||||
))
|
||||
) : Uni.createFrom().nullItem())
|
||||
.chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff)))
|
||||
.call(__ -> Utils.deleteMedia(id, media, "aff_request/logo"))
|
||||
.call(__ -> Utils.deleteMedia(id, media, "aff_request/status"));
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleData;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryData;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryFullData;
|
||||
import fr.titionfire.ffsaf.rest.data.TreeData;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
@@ -25,10 +22,10 @@ import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class PouleService {
|
||||
public class CategoryService {
|
||||
|
||||
@Inject
|
||||
PouleRepository repository;
|
||||
CategoryRepository repository;
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competRepository;
|
||||
@@ -45,35 +42,24 @@ public class PouleService {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
public Uni<PouleData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
public Uni<CategoryData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
||||
.map(PouleData::fromModel);
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Category not found"))
|
||||
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet()))
|
||||
.map(CategoryData::fromModel);
|
||||
}
|
||||
|
||||
public Uni<List<PouleData>> getAll(SecurityCtx securityCtx, CompetitionSystem system) {
|
||||
return repository.list("system = ?1", system)
|
||||
.chain(o ->
|
||||
permService.getAllHaveAccess(securityCtx.getSubject())
|
||||
.chain(map -> Uni.createFrom().item(o.stream()
|
||||
.filter(p -> {
|
||||
if (securityCtx.getSubject().equals(p.getCompet().getOwner()))
|
||||
return true;
|
||||
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
||||
if (map.containsKey(p.getCompet().getId()))
|
||||
return map.get(p.getId()).equals("admin");
|
||||
return securityCtx.roleHas("federation_admin")
|
||||
|| securityCtx.roleHas("safca_super_admin");
|
||||
}
|
||||
return securityCtx.roleHas("federation_admin");
|
||||
})
|
||||
.map(PouleData::fromModel).toList())
|
||||
));
|
||||
public Uni<List<CategoryData>> getAllAdmin(SecurityCtx securityCtx, CompetitionSystem system) {
|
||||
return permService.getAllHaveAdminAccess(securityCtx)
|
||||
.chain(ids -> repository.list("system = ?1 AND compet.id IN ?2", system, ids))
|
||||
.map(pouleModels -> pouleModels.stream().map(CategoryData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<PouleData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, PouleData data) {
|
||||
public Uni<CategoryData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, CategoryData data) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||
.chain(o -> {
|
||||
if (o == null) {
|
||||
@@ -81,7 +67,7 @@ public class PouleService {
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Competition not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2))
|
||||
.chain(competitionModel -> {
|
||||
PouleModel model = new PouleModel();
|
||||
CategoryModel model = new CategoryModel();
|
||||
|
||||
model.setId(null);
|
||||
model.setSystem(system);
|
||||
@@ -99,7 +85,7 @@ public class PouleService {
|
||||
o.setType(data.getType());
|
||||
return Panache.withTransaction(() -> repository.persist(o));
|
||||
}
|
||||
}).map(PouleData::fromModel);
|
||||
}).map(CategoryData::fromModel);
|
||||
}
|
||||
|
||||
private MatchModel findMatch(List<MatchModel> matchModelList, Long id) {
|
||||
@@ -128,7 +114,7 @@ public class PouleService {
|
||||
}
|
||||
}
|
||||
|
||||
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, PouleModel poule,
|
||||
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, CategoryModel poule,
|
||||
List<MatchModel> matchModelList) {
|
||||
TreeModel mm = findNode(node, data.getMatch());
|
||||
if (mm == null) {
|
||||
@@ -136,7 +122,7 @@ public class PouleService {
|
||||
mm.setId(null);
|
||||
}
|
||||
mm.setLevel(data.getLevel());
|
||||
mm.setPoule(poule.getId());
|
||||
mm.setCategory(poule.getId());
|
||||
mm.setMatch(findMatch(matchModelList, data.getMatch()));
|
||||
|
||||
return Uni.createFrom().item(mm)
|
||||
@@ -147,7 +133,7 @@ public class PouleService {
|
||||
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
|
||||
}
|
||||
|
||||
public Uni<?> syncPoule(SecurityCtx securityCtx, CompetitionSystem system, PouleFullData data) {
|
||||
public Uni<?> syncCategory(SecurityCtx securityCtx, CompetitionSystem system, CategoryFullData data) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNotNull().call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
@@ -156,7 +142,7 @@ public class PouleService {
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Compet not found"))
|
||||
.call(o -> permService.hasEditPerm(securityCtx, o))
|
||||
.map(o -> {
|
||||
PouleModel model = new PouleModel();
|
||||
CategoryModel model = new CategoryModel();
|
||||
model.setId(null);
|
||||
model.setSystem(system);
|
||||
model.setSystemId(data.getId());
|
||||
@@ -172,10 +158,10 @@ public class PouleService {
|
||||
o.setType(data.getType());
|
||||
|
||||
WorkData workData = new WorkData();
|
||||
workData.poule = o;
|
||||
workData.category = o;
|
||||
return workData;
|
||||
})
|
||||
.call(o -> Panache.withTransaction(() -> repository.persist(o.poule)))
|
||||
.call(o -> Panache.withTransaction(() -> repository.persist(o.category)))
|
||||
.call(o -> (data.getMatches() == null || data.getMatches().isEmpty()) ? Uni.createFrom().nullItem() :
|
||||
Uni.createFrom()
|
||||
.item(data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id())
|
||||
@@ -185,9 +171,18 @@ public class PouleService {
|
||||
.invoke(o2 -> o2.forEach(m -> o.membres.put(m.getId(), m)))
|
||||
)
|
||||
)
|
||||
.call(o -> Mutiny.fetch(o.category.getCompet().getGuests())
|
||||
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m)))
|
||||
.map(o2 -> data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_str(), m.getC2_str())
|
||||
.filter(Objects::nonNull)).distinct().filter(s -> !o.guest.containsKey(s)).map(
|
||||
CompetitionGuestModel::new).toList())
|
||||
.call(o3 -> o3.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
Uni.join().all(o3.stream().map(o4 -> competitionGuestRepository.persist(o4)).toList())
|
||||
.andFailFast())
|
||||
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m))))
|
||||
.invoke(in -> {
|
||||
ArrayList<TreeModel> node = new ArrayList<>();
|
||||
for (TreeModel treeModel : in.poule.getTree())
|
||||
for (TreeModel treeModel : in.category.getTree())
|
||||
flatTreeChild(treeModel, node);
|
||||
|
||||
ArrayList<TreeData> new_node = new ArrayList<>();
|
||||
@@ -204,7 +199,7 @@ public class PouleService {
|
||||
n.setLeft(null);
|
||||
});
|
||||
|
||||
in.toRmMatch = in.poule.getMatchs().stream()
|
||||
in.toRmMatch = in.category.getMatchs().stream()
|
||||
.filter(m -> data.getMatches().stream().noneMatch(m2 -> m2.getId().equals(m.getSystemId())))
|
||||
.map(MatchModel::getId).toList();
|
||||
})
|
||||
@@ -219,21 +214,21 @@ public class PouleService {
|
||||
.call(in -> data.getMatches().isEmpty() ? Uni.createFrom().nullItem() :
|
||||
Uni.join().all(
|
||||
data.getMatches().stream().map(m -> {
|
||||
MatchModel mm = findMatch(in.poule.getMatchs(), m.getId());
|
||||
MatchModel mm = findMatch(in.category.getMatchs(), m.getId());
|
||||
if (mm == null) {
|
||||
mm = new MatchModel();
|
||||
mm.setId(null);
|
||||
mm.setSystem(system);
|
||||
mm.setSystemId(m.getId());
|
||||
}
|
||||
mm.setPoule(in.poule);
|
||||
mm.setPoule_ord(m.getPoule_ord());
|
||||
mm.setC1_str(m.getC1_str());
|
||||
mm.setC2_str(m.getC2_str());
|
||||
mm.setCategory(in.category);
|
||||
mm.setCategory_ord(m.getCategory_ord());
|
||||
mm.setC1_guest(in.guest.getOrDefault(m.getC1_str(), null));
|
||||
mm.setC2_guest(in.guest.getOrDefault(m.getC2_str(), null));
|
||||
mm.setC1_id(in.membres.getOrDefault(m.getC1_id(), null));
|
||||
mm.setC2_id(in.membres.getOrDefault(m.getC2_id(), null));
|
||||
mm.setEnd(m.isEnd());
|
||||
mm.setGroupe(m.getGroupe());
|
||||
mm.setPoule(m.getPoule());
|
||||
mm.getScores().clear();
|
||||
mm.getScores().addAll(m.getScores());
|
||||
|
||||
@@ -244,14 +239,15 @@ public class PouleService {
|
||||
.andCollectFailures())
|
||||
.call(in -> data.getTrees().isEmpty() ? Uni.createFrom().nullItem() :
|
||||
Uni.join().all(data.getTrees().stream()
|
||||
.map(m -> persisteTree(m, in.poule.getTree(), in.poule, in.match)).toList())
|
||||
.map(m -> persisteTree(m, in.category.getTree(), in.category, in.match)).toList())
|
||||
.andCollectFailures())
|
||||
.map(__ -> "OK");
|
||||
}
|
||||
|
||||
private static class WorkData {
|
||||
PouleModel poule;
|
||||
CategoryModel category;
|
||||
HashMap<Long, MembreModel> membres = new HashMap<>();
|
||||
HashMap<String, CompetitionGuestModel> guest = new HashMap<>();
|
||||
List<MatchModel> match = new ArrayList<>();
|
||||
List<Long> toRmMatch;
|
||||
List<TreeModel> unlinkNode;
|
||||
@@ -260,7 +256,7 @@ public class PouleService {
|
||||
|
||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Category not found"))
|
||||
.call(o -> permService.hasEditPerm(securityCtx, o.getCompet()))
|
||||
.call(o -> Mutiny.fetch(o.getTree())
|
||||
.call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
@@ -274,7 +270,7 @@ public class PouleService {
|
||||
Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in)))
|
||||
)
|
||||
)
|
||||
.call(o -> matchRepository.delete("poule.id = ?1", o.getId()))
|
||||
.call(o -> matchRepository.delete("category.id = ?1", o.getId()))
|
||||
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CheckoutModel;
|
||||
import fr.titionfire.ffsaf.data.model.LogModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CheckoutRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.LicenceRepository;
|
||||
import fr.titionfire.ffsaf.rest.client.HelloAssoService;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsRequest;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsResponse;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutMetadata;
|
||||
import fr.titionfire.ffsaf.rest.exception.DInternalError;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.scheduler.Scheduled;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class CheckoutService {
|
||||
|
||||
@Inject
|
||||
CheckoutRepository repository;
|
||||
|
||||
@Inject
|
||||
LicenceRepository licenceRepository;
|
||||
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
LicenceService licenceService;
|
||||
|
||||
@Inject
|
||||
LoggerService ls;
|
||||
|
||||
@RestClient
|
||||
HelloAssoService helloAssoService;
|
||||
|
||||
@ConfigProperty(name = "frontRootUrl")
|
||||
String frontRootUrl;
|
||||
|
||||
@ConfigProperty(name = "unitLicencePrice")
|
||||
int unitLicencePrice;
|
||||
|
||||
@ConfigProperty(name = "helloasso.organizationSlug")
|
||||
String organizationSlug;
|
||||
|
||||
public Uni<Boolean> canDeleteLicence(long id) {
|
||||
return repository.find("?1 IN licenseIds", id).count().map(count -> count == 0);
|
||||
}
|
||||
|
||||
public Uni<String> create(List<Long> ids, SecurityCtx securityCtx) {
|
||||
return membreService.getByAccountId(securityCtx.getSubject())
|
||||
.call(membreModel -> Mutiny.fetch(membreModel.getClub()))
|
||||
.chain(membreModel -> {
|
||||
CheckoutModel model = new CheckoutModel();
|
||||
model.setMembre(membreModel);
|
||||
model.setLicenseIds(ids);
|
||||
model.setPaymentStatus(CheckoutModel.PaymentStatus.UNKNOW);
|
||||
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
})
|
||||
.chain(checkoutModel -> {
|
||||
CheckoutIntentsRequest request = new CheckoutIntentsRequest();
|
||||
request.setTotalAmount(unitLicencePrice * checkoutModel.getLicenseIds().size());
|
||||
request.setInitialAmount(unitLicencePrice * checkoutModel.getLicenseIds().size());
|
||||
request.setItemName("%d licences %d-%d pour %s".formatted(checkoutModel.getLicenseIds().size(),
|
||||
Utils.getSaison(), Utils.getSaison() + 1, checkoutModel.getMembre().getClub().getName()));
|
||||
request.setBackUrl(frontRootUrl + "/club/member/pay");
|
||||
request.setErrorUrl(frontRootUrl + "/club/member/pay/error");
|
||||
request.setReturnUrl(frontRootUrl + "/club/member/pay/return");
|
||||
request.setContainsDonation(false);
|
||||
request.setPayer(new CheckoutIntentsRequest.Payer(checkoutModel.getMembre().getFname(),
|
||||
checkoutModel.getMembre().getLname(), checkoutModel.getMembre().getEmail()));
|
||||
request.setMetadata(new CheckoutMetadata(checkoutModel.getId()));
|
||||
|
||||
return helloAssoService.checkout(organizationSlug, request)
|
||||
.call(response -> {
|
||||
checkoutModel.setCheckoutId(response.getId());
|
||||
return Panache.withTransaction(() -> repository.persist(checkoutModel));
|
||||
});
|
||||
})
|
||||
.onFailure().transform(t -> new DInternalError(t.getMessage()))
|
||||
.map(CheckoutIntentsResponse::getRedirectUrl);
|
||||
}
|
||||
|
||||
public Uni<Response> paymentStatusChange(String state, CheckoutMetadata metadata) {
|
||||
return repository.findById(metadata.getCheckoutDBId())
|
||||
.chain(checkoutModel -> {
|
||||
CheckoutModel.PaymentStatus newStatus = CheckoutModel.PaymentStatus.valueOf(state.toUpperCase());
|
||||
|
||||
Uni<?> uni = Uni.createFrom().nullItem();
|
||||
|
||||
if (checkoutModel.getPaymentStatus().equals(newStatus))
|
||||
return uni;
|
||||
|
||||
if (newStatus.equals(CheckoutModel.PaymentStatus.AUTHORIZED)) {
|
||||
for (Long id : checkoutModel.getLicenseIds()) {
|
||||
uni = uni.chain(__ -> licenceRepository.findById(id)
|
||||
.onFailure().recoverWithNull()
|
||||
.call(licenceModel -> {
|
||||
if (licenceModel == null) {
|
||||
ls.logAnonymous(LogModel.ActionType.UPDATE, LogModel.ObjectType.Licence,
|
||||
"Fail to save payment for licence (checkout n°" + checkoutModel.getCheckoutId() + ")",
|
||||
"", id);
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
|
||||
ls.logUpdateAnonymous("Paiement de la licence", licenceModel);
|
||||
licenceModel.setPay(true);
|
||||
|
||||
if (licenceModel.getCertificate() != null && licenceModel.getCertificate()
|
||||
.length() > 3) {
|
||||
if (!licenceModel.isValidate())
|
||||
ls.logUpdateAnonymous("Validation automatique de la licence",
|
||||
licenceModel);
|
||||
return licenceService.validateLicences(licenceModel);
|
||||
} else {
|
||||
return Panache.withTransaction(
|
||||
() -> licenceRepository.persist(licenceModel));
|
||||
}
|
||||
}));
|
||||
}
|
||||
} else if (checkoutModel.getPaymentStatus().equals(CheckoutModel.PaymentStatus.AUTHORIZED)) {
|
||||
for (Long id : checkoutModel.getLicenseIds()) {
|
||||
uni = uni.chain(__ -> licenceRepository.findById(id)
|
||||
.onFailure().recoverWithNull()
|
||||
.call(licenceModel -> {
|
||||
if (licenceModel == null)
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
ls.logUpdateAnonymous("Annulation automatique du paiement de la licence",
|
||||
licenceModel);
|
||||
licenceModel.setPay(false);
|
||||
if (licenceModel.isValidate())
|
||||
ls.logUpdateAnonymous(
|
||||
"Annulation automatique de la validation de la licence",
|
||||
licenceModel);
|
||||
licenceModel.setValidate(false);
|
||||
return Panache.withTransaction(() -> licenceRepository.persist(licenceModel));
|
||||
}));
|
||||
}
|
||||
}
|
||||
uni = uni.call(__ -> ls.append());
|
||||
|
||||
checkoutModel.setPaymentStatus(newStatus);
|
||||
return uni.chain(__ -> Panache.withTransaction(() -> repository.persist(checkoutModel)));
|
||||
})
|
||||
.onFailure().invoke(Throwable::printStackTrace)
|
||||
.map(__ -> Response.ok().build());
|
||||
}
|
||||
|
||||
@Scheduled(cron = "0 0 * * * ?")
|
||||
Uni<Void> everyHours() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.HOUR, -1);
|
||||
Date dateLimit = calendar.getTime();
|
||||
|
||||
return repository.delete("creationDate < ?1 AND (checkoutId IS NULL OR paymentStatus = ?2)", dateLimit,
|
||||
CheckoutModel.PaymentStatus.UNKNOW)
|
||||
.map(__ -> null);
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,7 @@ import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.net2.request.SReqClub;
|
||||
import fr.titionfire.ffsaf.rest.data.ClubMapData;
|
||||
import fr.titionfire.ffsaf.rest.data.DeskMember;
|
||||
import fr.titionfire.ffsaf.rest.data.RenewAffData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleClubList;
|
||||
import fr.titionfire.ffsaf.rest.data.*;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
@@ -31,16 +28,11 @@ import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
||||
@@ -48,7 +40,6 @@ import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class ClubService {
|
||||
private static final Logger LOGGER = Logger.getLogger(ClubService.class);
|
||||
|
||||
@Inject
|
||||
ClubRepository repository;
|
||||
@@ -68,12 +59,6 @@ public class ClubService {
|
||||
@Inject
|
||||
LoggerService ls;
|
||||
|
||||
@ConfigProperty(name = "pdf-maker.jar-path")
|
||||
String pdfMakerJarPath;
|
||||
|
||||
@ConfigProperty(name = "pdf-maker.sign-file")
|
||||
String sign_file;
|
||||
|
||||
public SimpleClubModel findByIdOptionalClub(long id) throws Throwable {
|
||||
return VertxContextSupport.subscribeAndAwait(
|
||||
() -> Panache.withTransaction(() -> repository.findById(id).map(SimpleClubModel::fromModel)));
|
||||
@@ -157,6 +142,19 @@ public class ClubService {
|
||||
.toList());
|
||||
}
|
||||
|
||||
public Uni<List<VerySimpleMembre>> getMembers(SecurityCtx securityCtx) {
|
||||
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null || m.getClub() == null)
|
||||
throw new DNotFoundException("Club non trouvé");
|
||||
if (!securityCtx.isInClubGroup(m.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
}))
|
||||
.chain(m -> combRepository.list("club = ?1", m.getClub()))
|
||||
.map(membreModels -> membreModels.stream()
|
||||
.map(m -> new VerySimpleMembre(m.getLname(), m.getFname(), m.getLicence())).toList());
|
||||
}
|
||||
|
||||
public Uni<String> updateOfUser(SecurityCtx securityCtx, PartClubForm form) {
|
||||
TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() {
|
||||
};
|
||||
@@ -196,12 +194,17 @@ public class ClubService {
|
||||
}
|
||||
|
||||
public Uni<String> update(long id, FullClubForm input) {
|
||||
AtomicBoolean nameChange = new AtomicBoolean(false);
|
||||
|
||||
return repository.findById(id).call(m -> Mutiny.fetch(m.getContact()))
|
||||
.onItem().transformToUni(Unchecked.function(m -> {
|
||||
TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() {
|
||||
};
|
||||
|
||||
if (!input.getName().equals(m.getName())) {
|
||||
m.setName(input.getName());
|
||||
nameChange.set(true);
|
||||
}
|
||||
m.setCountry(input.getCountry());
|
||||
m.setInternational(input.isInternational());
|
||||
|
||||
@@ -214,11 +217,9 @@ public class ClubService {
|
||||
m.setTraining_day_time(input.getTraining_day_time());
|
||||
ls.logChange("Contact interne", m.getContact_intern(), input.getContact_intern(), m);
|
||||
m.setContact_intern(input.getContact_intern());
|
||||
ls.logChange("N° RNA", m.getRNA(), input.getRna(), m);
|
||||
m.setRNA(input.getRna());
|
||||
if (input.getSiret() != null && !input.getSiret().isBlank()) {
|
||||
ls.logChange("N° SIRET", m.getSIRET(), input.getSiret(), m);
|
||||
m.setSIRET(Long.parseLong(input.getSiret()));
|
||||
if (input.getState_id() != null && !input.getState_id().isBlank()) {
|
||||
ls.logChange("N° SIRET", m.getClubId(), input.getState_id(), m);
|
||||
m.setStateId(input.getState_id());
|
||||
}
|
||||
ls.logChange("Adresse administrative", m.getAddress(), input.getAddress(), m);
|
||||
m.setAddress(input.getAddress());
|
||||
@@ -233,6 +234,8 @@ public class ClubService {
|
||||
}
|
||||
return Panache.withTransaction(() -> repository.persist(m)).call(() -> ls.append());
|
||||
}))
|
||||
.call(clubModel -> nameChange.get() ? keycloakService.updateGroupFromClub(clubModel) // update group in keycloak
|
||||
: Uni.createFrom().nullItem())
|
||||
.invoke(membreModel -> SReqClub.sendIfNeed(serverCustom.clients,
|
||||
SimpleClubModel.fromModel(membreModel)))
|
||||
.map(__ -> "OK");
|
||||
@@ -254,9 +257,8 @@ public class ClubService {
|
||||
clubModel.setTraining_location(input.getTraining_location());
|
||||
clubModel.setTraining_day_time(input.getTraining_day_time());
|
||||
clubModel.setContact_intern(input.getContact_intern());
|
||||
clubModel.setRNA(input.getRna());
|
||||
if (input.getSiret() != null && !input.getSiret().isBlank())
|
||||
clubModel.setSIRET(Long.parseLong(input.getSiret()));
|
||||
if (input.getState_id() != null && !input.getState_id().isBlank())
|
||||
clubModel.setStateId(input.getState_id());
|
||||
clubModel.setAddress(input.getAddress());
|
||||
|
||||
try {
|
||||
@@ -303,9 +305,9 @@ public class ClubService {
|
||||
.call(clubModel -> Mutiny.fetch(clubModel.getAffiliations()))
|
||||
.invoke(clubModel -> {
|
||||
data.setName(clubModel.getName());
|
||||
data.setSiret(clubModel.getSIRET());
|
||||
data.setRna(clubModel.getRNA());
|
||||
data.setState_id(clubModel.getStateId());
|
||||
data.setAddress(clubModel.getAddress());
|
||||
data.setContact(clubModel.getContact_intern());
|
||||
data.setSaison(
|
||||
clubModel.getAffiliations().stream().max(Comparator.comparing(AffiliationModel::getSaison))
|
||||
.map(AffiliationModel::getSaison).map(i -> Math.min(i + 1, Utils.getSaison() + 1))
|
||||
@@ -346,120 +348,4 @@ public class ClubService {
|
||||
return data;
|
||||
}).collect().asList();
|
||||
}
|
||||
|
||||
public Uni<Response> getAffiliationPdf(String subject) {
|
||||
return getAffiliationPdf(
|
||||
combRepository.find("userId = ?1", subject).firstResult()
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null || m.getClub() == null)
|
||||
throw new DNotFoundException("Club non trouvé");
|
||||
}))
|
||||
.map(MembreModel::getClub)
|
||||
.call(m -> Mutiny.fetch(m.getAffiliations())));
|
||||
}
|
||||
|
||||
public Uni<Response> getAffiliationPdf(long id) {
|
||||
return getAffiliationPdf(
|
||||
repository.findById(id)
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null)
|
||||
throw new DNotFoundException("Club non trouvé");
|
||||
}))
|
||||
.call(m -> Mutiny.fetch(m.getAffiliations())));
|
||||
}
|
||||
|
||||
|
||||
private Uni<Response> getAffiliationPdf(Uni<ClubModel> uniBase) {
|
||||
return uniBase
|
||||
.map(Unchecked.function(m -> {
|
||||
if (m.getAffiliations().stream()
|
||||
.noneMatch(licenceModel -> licenceModel.getSaison() == Utils.getSaison()))
|
||||
throw new DNotFoundException("Pas d'affiliation pour la saison en cours");
|
||||
|
||||
try {
|
||||
byte[] buff = make_pdf(m);
|
||||
if (buff == null)
|
||||
throw new IOException("Error making pdf");
|
||||
|
||||
String mimeType = "application/pdf";
|
||||
|
||||
Response.ResponseBuilder resp = Response.ok(buff);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, buff.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + "filename=\"Attestation d'affiliation " + Utils.getSaison() + "-" +
|
||||
(Utils.getSaison() + 1) + " de " + m.getName() + ".pdf\"");
|
||||
return resp.build();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private byte[] make_pdf(ClubModel m) throws IOException, InterruptedException {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add("java");
|
||||
cmd.add("-jar");
|
||||
cmd.add(pdfMakerJarPath);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
cmd.add("/tmp/" + uuid + ".pdf");
|
||||
cmd.add("club");
|
||||
cmd.add(m.getName());
|
||||
cmd.add(Utils.getSaison() + "");
|
||||
cmd.add(m.getNo_affiliation() + "");
|
||||
cmd.add(new File(sign_file).getAbsolutePath());
|
||||
|
||||
return getPdf(cmd, uuid, LOGGER);
|
||||
}
|
||||
|
||||
static byte[] getPdf(List<String> cmd, UUID uuid, Logger logger) throws IOException, InterruptedException {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
Process process = processBuilder.start();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
builder.append(line).append("\n");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
int code = -1;
|
||||
if (!process.waitFor(30, TimeUnit.SECONDS)) {
|
||||
process.destroy();
|
||||
builder.append("Timeout...");
|
||||
} else {
|
||||
code = process.exitValue();
|
||||
}
|
||||
|
||||
if (t.isAlive())
|
||||
t.interrupt();
|
||||
|
||||
logger.debug("PDF maker: " + builder);
|
||||
|
||||
if (code != 0) {
|
||||
throw new IOException("Error code: " + code);
|
||||
} else {
|
||||
File file = new File("/tmp/" + uuid + ".pdf");
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
byte[] buff = fis.readAllBytes();
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.delete();
|
||||
return buff;
|
||||
} catch (IOException e) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.RegisterRepository;
|
||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
||||
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.cache.Cache;
|
||||
import io.quarkus.cache.CacheName;
|
||||
@@ -15,7 +17,10 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -28,6 +33,9 @@ public class CompetPermService {
|
||||
@Inject
|
||||
ServerCustom serverCustom;
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competitionRepository;
|
||||
|
||||
@Inject
|
||||
@CacheName("safca-config")
|
||||
Cache cache;
|
||||
@@ -37,76 +45,236 @@ public class CompetPermService {
|
||||
Cache cacheAccess;
|
||||
|
||||
@Inject
|
||||
CompetitionRepository competitionRepository;
|
||||
@CacheName("have-access")
|
||||
Cache cacheNoneAccess;
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
|
||||
|
||||
public Uni<SimpleCompet> getSafcaConfig(long id) {
|
||||
return cache.get(id, k -> {
|
||||
CompletableFuture<SimpleCompet> f = new CompletableFuture<>();
|
||||
SReqCompet.getConfig(serverCustom.clients, id, f);
|
||||
System.out.println("get config");
|
||||
try {
|
||||
return f.get(1500, TimeUnit.MILLISECONDS);
|
||||
return f.get(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<HashMap<Long, String>> getAllHaveAccess(String subject) {
|
||||
return cacheAccess.get(subject, k -> {
|
||||
CompletableFuture<HashMap<Long, String>> f = new CompletableFuture<>();
|
||||
SReqCompet.getAllHaveAccess(serverCustom.clients, subject, f);
|
||||
System.out.println("get all have access");
|
||||
try {
|
||||
return f.get(1500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
public Uni<List<Long>> getAllHaveAdminAccess(SecurityCtx securityCtx) {
|
||||
ArrayList<Long> out = new ArrayList<>();
|
||||
|
||||
Uni<HashMap<Long, String>> safca = cacheAccess.getAsync(securityCtx.getSubject(),
|
||||
k -> competitionRepository.list("system = ?1", CompetitionSystem.SAFCA)
|
||||
.chain(competitionModels -> {
|
||||
CompletableFuture<HashMap<String, String>> f = new CompletableFuture<>();
|
||||
SReqCompet.getAllHaveAccess(serverCustom.clients, securityCtx.getSubject(), f);
|
||||
return Uni.createFrom().future(f, Duration.ofMillis(500))
|
||||
.onFailure().recoverWithItem(new HashMap<>())
|
||||
.map(map_ -> {
|
||||
HashMap<Long, String> map = new HashMap<>();
|
||||
map_.forEach((key, value) -> map.put(Long.parseLong(key), value));
|
||||
|
||||
for (CompetitionModel model : competitionModels) {
|
||||
if (model.getOwner().equals(securityCtx.getSubject()))
|
||||
map.putIfAbsent(model.getId(), "owner");
|
||||
else if (securityCtx.roleHas("federation_admin")
|
||||
|| securityCtx.roleHas("safca_super_admin"))
|
||||
map.putIfAbsent(model.getId(), "admin");
|
||||
}
|
||||
return map;
|
||||
});
|
||||
}))
|
||||
.onFailure().call(throwable -> cacheAccess.invalidate(securityCtx.getSubject()));
|
||||
|
||||
Uni<HashMap<Long, String>> none = cacheNoneAccess.getAsync(securityCtx.getSubject(),
|
||||
k -> competitionRepository.list("system = ?1", CompetitionSystem.INTERNAL)
|
||||
.map(competitionModels -> {
|
||||
HashMap<Long, String> map = new HashMap<>();
|
||||
for (CompetitionModel model : competitionModels) {
|
||||
if (model.getOwner().equals(securityCtx.getSubject()))
|
||||
map.putIfAbsent(model.getId(), "owner");
|
||||
else if (securityCtx.roleHas("federation_admin"))
|
||||
map.putIfAbsent(model.getId(), "admin");
|
||||
else if (securityCtx.isInClubGroup(model.getClub().getId()) && (securityCtx.roleHas(
|
||||
"club_president")
|
||||
|| securityCtx.roleHas("club_respo_intra") || securityCtx.roleHas(
|
||||
"club_secretaire")
|
||||
|| securityCtx.roleHas("club_tresorier")))
|
||||
map.putIfAbsent(model.getId(), "admin");
|
||||
}
|
||||
return map;
|
||||
}));
|
||||
|
||||
return safca.invoke(map ->
|
||||
map.forEach((k, v) -> {
|
||||
if (v.equals("owner") || v.equals("admin"))
|
||||
out.add(k);
|
||||
})
|
||||
)
|
||||
.call(__ -> none.invoke(map ->
|
||||
map.forEach((k, v) -> {
|
||||
if (v.equals("owner") || v.equals("admin"))
|
||||
out.add(k);
|
||||
})
|
||||
))
|
||||
.map(__ -> out.stream().distinct().toList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, long id) {
|
||||
return hasViewPerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
private Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(o -> (
|
||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
||||
hasSafcaViewPerm(securityCtx, o.getId())
|
||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(cm -> (cm.isPublicVisible() || cm.getRegisterMode() == RegisterMode.FREE
|
||||
|| cm.getRegisterMode() == RegisterMode.HELLOASSO
|
||||
|| (cm.getRegisterMode() == RegisterMode.CLUB_ADMIN && securityCtx.isClubAdmin())) ?
|
||||
Uni.createFrom().nullItem() :
|
||||
hasAdminViewPerm(securityCtx, cm).onFailure()
|
||||
.recoverWithUni(__ ->
|
||||
registerRepository.count("membre.userId = ?1 AND competition = ?2",
|
||||
securityCtx.getSubject(), cm).map(Unchecked.function(c -> {
|
||||
if (c == 0)
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
return cm;
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasAdminViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, long id) {
|
||||
return hasAdminViewPerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(Unchecked.function(o -> {
|
||||
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||
return hasSafcaViewPerm(securityCtx, o.getId());
|
||||
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||
throw new DForbiddenException();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL)
|
||||
if (securityCtx.roleHas("club_president") || securityCtx.roleHas("club_respo_intra")
|
||||
|| securityCtx.roleHas("club_secretaire") || securityCtx.roleHas("club_tresorier"))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasEditPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, long id) {
|
||||
return hasEditPerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(o -> (
|
||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
||||
hasSafcaEditPerm(securityCtx, o.getId())
|
||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
||||
return in.call(Unchecked.function(o -> {
|
||||
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||
return hasSafcaEditPerm(securityCtx, o.getId());
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL) {
|
||||
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getAdmin().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
throw new DForbiddenException();
|
||||
}
|
||||
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasTablePerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, long id) {
|
||||
return hasTablePerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||
*/
|
||||
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(Unchecked.function(o -> {
|
||||
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||
return hasSafcaTablePerm(securityCtx, o.getId());
|
||||
|
||||
if (o.getSystem() == CompetitionSystem.INTERNAL) {
|
||||
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
if (o.getAdmin().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
if (o.getTable().contains(securityCtx.getSubject()))
|
||||
return Uni.createFrom().nullItem();
|
||||
|
||||
throw new DForbiddenException();
|
||||
}
|
||||
|
||||
throw new DForbiddenException();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private Uni<?> hasSafcaViewPerm(SecurityCtx securityCtx, long id) {
|
||||
@@ -114,8 +282,8 @@ public class CompetPermService {
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
getSafcaConfig(id).chain(Unchecked.function(o -> {
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject())) && !o.table()
|
||||
.contains(UUID.fromString(securityCtx.getSubject())))
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))
|
||||
&& !o.table().contains(UUID.fromString(securityCtx.getSubject())))
|
||||
throw new DForbiddenException();
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
@@ -131,4 +299,16 @@ public class CompetPermService {
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
}
|
||||
|
||||
private Uni<?> hasSafcaTablePerm(SecurityCtx securityCtx, long id) {
|
||||
return securityCtx.roleHas("safca_super_admin") ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
getSafcaConfig(id).chain(Unchecked.function(o -> {
|
||||
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))
|
||||
&& !o.table().contains(UUID.fromString(securityCtx.getSubject())))
|
||||
throw new DForbiddenException();
|
||||
return Uni.createFrom().nullItem();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
||||
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
||||
import fr.titionfire.ffsaf.net2.request.SReqRegister;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.NotificationData;
|
||||
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
||||
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
||||
@@ -14,21 +14,24 @@ import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import fr.titionfire.ffsaf.ws.send.SRegister;
|
||||
import io.quarkus.cache.Cache;
|
||||
import io.quarkus.cache.CacheName;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.mailer.Mail;
|
||||
import io.quarkus.mailer.reactive.ReactiveMailer;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import io.vertx.mutiny.core.Vertx;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
import java.util.*;
|
||||
@@ -37,31 +40,51 @@ import java.util.stream.Stream;
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class CompetitionService {
|
||||
private static final Logger LOGGER = Logger.getLogger(CompetitionService.class);
|
||||
|
||||
@Inject
|
||||
CompetitionRepository repository;
|
||||
|
||||
@Inject
|
||||
PouleRepository pouleRepository;
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
|
||||
@Inject
|
||||
KeycloakService keycloakService;
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
@Inject
|
||||
ServerCustom serverCustom;
|
||||
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
@Inject
|
||||
HelloAssoRegisterRepository helloAssoRepository;
|
||||
|
||||
@SuppressWarnings("CdiInjectionPointsInspection")
|
||||
@Inject
|
||||
ReactiveMailer reactiveMailer;
|
||||
|
||||
@Inject
|
||||
Vertx vertx;
|
||||
|
||||
@Inject
|
||||
SRegister sRegister;
|
||||
|
||||
@Inject
|
||||
@CacheName("safca-config")
|
||||
Cache cache;
|
||||
@@ -69,18 +92,26 @@ public class CompetitionService {
|
||||
@Inject
|
||||
@CacheName("safca-have-access")
|
||||
Cache cacheAccess;
|
||||
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
@CacheName("have-access")
|
||||
Cache cacheNoneAccess;
|
||||
|
||||
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
||||
return permService.hasViewPerm(securityCtx, id).map(CompetitionData::fromModelLight);
|
||||
}
|
||||
|
||||
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
||||
if (id == 0) {
|
||||
return Uni.createFrom()
|
||||
.item(new CompetitionData(null, "", "", new Date(), CompetitionSystem.SAFCA,
|
||||
null, "", "", null));
|
||||
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
||||
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
||||
null, "", "", null, true, "", "", "", ""));
|
||||
}
|
||||
return permService.hasViewPerm(securityCtx, id)
|
||||
return permService.hasAdminViewPerm(securityCtx, id)
|
||||
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
||||
.map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
|
||||
.chain(insc -> Mutiny.fetch(competitionModel.getGuests())
|
||||
.map(guest -> CompetitionData.fromModel(competitionModel).addInsc(insc, guest))))
|
||||
.chain(data ->
|
||||
vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
keycloakService.getUser(UUID.fromString(data.getOwner()))
|
||||
@@ -91,64 +122,61 @@ public class CompetitionService {
|
||||
}
|
||||
|
||||
public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) {
|
||||
return repository.listAll()
|
||||
.chain(o ->
|
||||
permService.getAllHaveAccess(securityCtx.getSubject())
|
||||
.chain(map -> Uni.createFrom().item(o.stream()
|
||||
.filter(p -> {
|
||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
||||
return true;
|
||||
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
||||
if (map.containsKey(p.getId()))
|
||||
return map.get(p.getId()).equals("admin");
|
||||
return securityCtx.roleHas("federation_admin")
|
||||
|| securityCtx.roleHas("safca_super_admin");
|
||||
List<CompetitionData> out = new ArrayList<>();
|
||||
return permService.getAllHaveAdminAccess(securityCtx)
|
||||
.call(ids -> repository.list("id IN ?1", ids)
|
||||
.invoke(cm -> {
|
||||
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
||||
out.forEach(competition -> competition.setCanEdit(true));
|
||||
}))
|
||||
.call(ids ->
|
||||
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids,
|
||||
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO,
|
||||
RegisterMode.CLUB_ADMIN) : List.of(RegisterMode.FREE, RegisterMode.HELLOASSO))
|
||||
.invoke(cm -> out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList()))
|
||||
.call(cm -> registerRepository.list(
|
||||
"membre.userId = ?1 AND competition.id NOT IN ?2 AND competition NOT IN ?3",
|
||||
securityCtx.getSubject(), ids, cm)
|
||||
.chain(registerModels -> {
|
||||
Uni<Void> uni = Uni.createFrom().nullItem();
|
||||
for (RegisterModel registerModel : registerModels) {
|
||||
uni = uni.call(__ -> Mutiny.fetch(registerModel.getCompetition())
|
||||
.invoke(cm2 -> out.add(CompetitionData.fromModelLight(cm2))));
|
||||
}
|
||||
return securityCtx.roleHas("federation_admin");
|
||||
return uni;
|
||||
})
|
||||
.map(CompetitionData::fromModel).toList())
|
||||
));
|
||||
))
|
||||
.map(__ -> out);
|
||||
}
|
||||
|
||||
public Uni<List<CompetitionData>> getAllSystem(SecurityCtx securityCtx,
|
||||
public Uni<List<CompetitionData>> getAllAdmin(SecurityCtx securityCtx) {
|
||||
return permService.getAllHaveAdminAccess(securityCtx)
|
||||
.chain(ids -> repository.list("id IN ?1", ids))
|
||||
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<List<CompetitionData>> getAllSystemAdmin(SecurityCtx securityCtx,
|
||||
CompetitionSystem system) {
|
||||
if (system == CompetitionSystem.SAFCA) {
|
||||
return permService.getAllHaveAccess(securityCtx.getSubject())
|
||||
.chain(map ->
|
||||
repository.list("system = ?1", system)
|
||||
.map(data -> data.stream()
|
||||
.filter(p -> {
|
||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
||||
return true;
|
||||
if (map.containsKey(p.getId()))
|
||||
return map.get(p.getId()).equals("admin");
|
||||
return securityCtx.roleHas("federation_admin")
|
||||
|| securityCtx.roleHas("safca_super_admin");
|
||||
})
|
||||
.map(CompetitionData::fromModel).toList())
|
||||
);
|
||||
return permService.getAllHaveAdminAccess(securityCtx)
|
||||
.chain(ids -> repository.list("system = ?1 AND id IN ?2", system, ids))
|
||||
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
|
||||
CompetitionSystem system) {
|
||||
return repository.list("system = ?1", system)
|
||||
.map(data -> data.stream()
|
||||
.filter(p -> {
|
||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
||||
return true;
|
||||
return securityCtx.roleHas("federation_admin") ||
|
||||
securityCtx.isInClubGroup(p.getClub().getId());
|
||||
})
|
||||
.map(CompetitionData::fromModel).toList());
|
||||
.chain(l -> Uni.join().all(l.stream().map(cm -> permService.hasTablePerm(securityCtx, cm)).toList())
|
||||
.andCollectFailures())
|
||||
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList());
|
||||
}
|
||||
|
||||
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
|
||||
if (data.getId() == null) {
|
||||
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
||||
.invoke(Unchecked.consumer(combModel -> {
|
||||
if (combModel == null)
|
||||
throw new DNotFoundException("Profile non trouvé");
|
||||
if (data.getSystem() == CompetitionSystem.SAFCA)
|
||||
if (!securityCtx.getRoles().contains("safca_create_compet"))
|
||||
throw new DForbiddenException("Vous ne pouvez pas créer de compétition SAFCA");
|
||||
if (!securityCtx.getRoles().contains("create_compet") && !securityCtx.getRoles()
|
||||
.contains("federation_admin"))
|
||||
throw new DForbiddenException("Vous ne pouvez pas créer de compétition");
|
||||
}))
|
||||
.map(MembreModel::getClub)
|
||||
.chain(clubModel -> {
|
||||
@@ -157,22 +185,25 @@ public class CompetitionService {
|
||||
model.setId(null);
|
||||
model.setSystem(data.getSystem());
|
||||
model.setClub(clubModel);
|
||||
model.setDate(data.getDate());
|
||||
model.setInsc(new ArrayList<>());
|
||||
model.setGuests(new ArrayList<>());
|
||||
model.setUuid(UUID.randomUUID().toString());
|
||||
model.setName(data.getName());
|
||||
model.setOwner(securityCtx.getSubject());
|
||||
|
||||
copyData(data, model);
|
||||
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
}).map(CompetitionData::fromModel)
|
||||
.call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||
} else {
|
||||
return permService.hasEditPerm(securityCtx, data.getId())
|
||||
.chain(model -> {
|
||||
model.setDate(data.getDate());
|
||||
model.setName(data.getName());
|
||||
copyData(data, model);
|
||||
|
||||
return vertx.getOrCreateContext().executeBlocking(() ->
|
||||
return vertx.getOrCreateContext().executeBlocking(() -> // Update owner
|
||||
keycloakService.getUser(data.getOwner()).map(UserRepresentation::getId).orElse(null))
|
||||
.invoke(Unchecked.consumer(newOwner -> {
|
||||
if (newOwner == null)
|
||||
@@ -187,30 +218,154 @@ public class CompetitionService {
|
||||
}))
|
||||
.chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
|
||||
}).map(CompetitionData::fromModel)
|
||||
.call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
|
||||
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id) {
|
||||
private void copyData(CompetitionData data, CompetitionModel model) {
|
||||
if (model.getBanMembre() == null)
|
||||
model.setBanMembre(new ArrayList<>());
|
||||
|
||||
model.setName(data.getName());
|
||||
model.setAdresse(data.getAdresse());
|
||||
model.setDescription(data.getDescription());
|
||||
model.setDate(data.getDate());
|
||||
model.setTodate(data.getDate());
|
||||
model.setPublicVisible(data.isPublicVisible());
|
||||
model.setStartRegister(data.getStartRegister());
|
||||
model.setEndRegister(data.getEndRegister());
|
||||
model.setRegisterMode(data.getRegisterMode());
|
||||
model.setData1(data.getData1());
|
||||
model.setData2(data.getData2());
|
||||
model.setData3(data.getData3());
|
||||
model.setData4(data.getData4());
|
||||
}
|
||||
|
||||
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id, String source) {
|
||||
if ("admin".equals(source))
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> Mutiny.fetch(c.getInsc()))
|
||||
.chain(c -> {
|
||||
Uni<List<SimpleRegisterComb>> uni = Mutiny.fetch(c.getInsc())
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||
.map(cm -> SimpleRegisterComb.fromModel(cm, cm.getMembre().getLicences()))
|
||||
.collect().asList();
|
||||
return uni
|
||||
.call(l -> Mutiny.fetch(c.getGuests())
|
||||
.map(guest -> guest.stream().map(SimpleRegisterComb::fromModel).toList())
|
||||
.invoke(l::addAll));
|
||||
});
|
||||
|
||||
if ("club".equals(source))
|
||||
return Uni.createFrom().nullItem()
|
||||
.invoke(Unchecked.consumer(__ -> {
|
||||
if (!securityCtx.isClubAdmin())
|
||||
throw new DForbiddenException();
|
||||
}))
|
||||
.chain(__ -> membreService.getByAccountId(securityCtx.getSubject()))
|
||||
.chain(model -> registerRepository.list("competition.id = ?1 AND membre.club = ?2", id,
|
||||
model.getClub()))
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
||||
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
|
||||
.collect().asList();
|
||||
|
||||
return membreService.getByAccountId(securityCtx.getSubject())
|
||||
.chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult()
|
||||
.map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()))));
|
||||
}
|
||||
|
||||
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data) {
|
||||
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data,
|
||||
String source) {
|
||||
if ("admin".equals(source))
|
||||
if (data.getLicence() != -1) { // not a guest
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||
.chain(combModel -> Mutiny.fetch(c.getInsc())
|
||||
.chain(Unchecked.function(insc -> {
|
||||
Optional<RegisterModel> opt = insc.stream()
|
||||
.filter(m -> m.getMembre().equals(combModel)).findAny();
|
||||
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
||||
.call(combModel -> {
|
||||
if (c.getBanMembre() == null)
|
||||
c.setBanMembre(new ArrayList<>());
|
||||
c.getBanMembre().remove(combModel.getId());
|
||||
return Panache.withTransaction(() -> repository.persist(c));
|
||||
})
|
||||
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
||||
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
|
||||
} else {
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> competitionGuestRepository.findById(data.getId() * -1)
|
||||
.map(g -> {
|
||||
if (g != null)
|
||||
return g;
|
||||
CompetitionGuestModel model = new CompetitionGuestModel();
|
||||
model.setCompetition(c);
|
||||
return model;
|
||||
}))
|
||||
.chain(model -> {
|
||||
model.setFname(data.getFname());
|
||||
model.setLname(data.getLname());
|
||||
model.setGenre(data.getGenre());
|
||||
model.setClub(data.getClub());
|
||||
model.setCountry(data.getCountry());
|
||||
model.setWeight(data.getWeight());
|
||||
model.setCategorie(data.getCategorie());
|
||||
|
||||
RegisterModel r;
|
||||
if (opt.isPresent()) {
|
||||
r = opt.get();
|
||||
return Panache.withTransaction(() -> competitionGuestRepository.persist(model))
|
||||
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegister(model.getCompetition().getUuid(),
|
||||
r) : Uni.createFrom().voidItem());
|
||||
})
|
||||
.map(SimpleRegisterComb::fromModel);
|
||||
}
|
||||
if ("club".equals(source))
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|
||||
|| !securityCtx.isClubAdmin())
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
||||
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
if (c.getBanMembre().contains(model.getId()))
|
||||
throw new DForbiddenException(
|
||||
"Vous n'avez pas le droit d'inscrire ce membre (par décision de l'administrateur de la compétition)");
|
||||
}))
|
||||
.chain(combModel -> updateRegister(data, c, combModel, false)))
|
||||
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
|
||||
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
if (cm.getRegisterMode() != RegisterMode.FREE)
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
.chain(c -> membreService.getByAccountId(securityCtx.getSubject())
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (c.getBanMembre().contains(model.getId()))
|
||||
throw new DForbiddenException(
|
||||
"Vous n'avez pas le droit de vous inscrire (par décision de l'administrateur de la compétition)");
|
||||
}))
|
||||
.chain(combModel -> updateRegister(data, c, combModel, false)))
|
||||
.map(r -> SimpleRegisterComb.fromModel(r, List.of()));
|
||||
}
|
||||
|
||||
private Uni<RegisterModel> updateRegister(RegisterRequestData data, CompetitionModel c,
|
||||
MembreModel combModel, boolean admin) {
|
||||
return registerRepository.find("competition = ?1 AND membre = ?2", c, combModel).firstResult()
|
||||
.onFailure().recoverWithNull()
|
||||
.map(Unchecked.function(r -> {
|
||||
if (r != null) {
|
||||
if (!admin && r.isLockEdit())
|
||||
throw new DForbiddenException(
|
||||
"Modification bloquée par l'administrateur de la compétition");
|
||||
r.setWeight(data.getWeight());
|
||||
r.setOverCategory(data.getOverCategory());
|
||||
r.setCategorie(
|
||||
@@ -218,32 +373,38 @@ public class CompetitionService {
|
||||
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
||||
c.getDate()));
|
||||
int days = Utils.getDaysBeforeCompetition(c.getDate());
|
||||
if (days > -7) {
|
||||
if (days > -7)
|
||||
r.setClub(combModel.getClub());
|
||||
}
|
||||
if (admin)
|
||||
r.setLockEdit(data.isLockEdit());
|
||||
} else {
|
||||
r = new RegisterModel(c, combModel, data.getWeight(), data.getOverCategory(),
|
||||
(combModel.getBirth_date() == null) ? combModel.getCategorie() :
|
||||
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
||||
c.getDate()),
|
||||
(combModel.getClub() == null) ? null : combModel.getClub());
|
||||
insc.add(r);
|
||||
if (admin)
|
||||
r.setLockEdit(data.isLockEdit());
|
||||
else
|
||||
r.setLockEdit(false);
|
||||
}
|
||||
|
||||
if (c.getSystem() == CompetitionSystem.SAFCA) {
|
||||
SReqRegister.sendIfNeed(serverCustom.clients,
|
||||
new CompetitionData.SimpleRegister(r.getMembre().getId(),
|
||||
r.getOverCategory(), r.getWeight(), r.getCategorie(),
|
||||
(r.getClub() == null) ? null : r.getClub().getId()), c.getId());
|
||||
(r.getClub() == null) ? null : r.getClub().getId(),
|
||||
(r.getClub() == null) ? null : r.getClub().getName()), c.getId());
|
||||
}
|
||||
return Panache.withTransaction(() -> repository.persist(c)).map(__ -> r);
|
||||
}))))
|
||||
.chain(r -> Mutiny.fetch(r.getMembre().getLicences())
|
||||
.map(licences -> SimpleRegisterComb.fromModel(r, licences)));
|
||||
return r;
|
||||
}))
|
||||
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegister(c.getUuid(), r) : Uni.createFrom().voidItem());
|
||||
}
|
||||
|
||||
private Uni<MembreModel> findComb(Long licence, String fname, String lname) {
|
||||
if (licence != null && licence != 0) {
|
||||
if (licence != null && licence > 0) {
|
||||
return combRepository.find("licence = ?1", licence).firstResult()
|
||||
.invoke(Unchecked.consumer(combModel -> {
|
||||
if (combModel == null)
|
||||
@@ -252,7 +413,8 @@ public class CompetitionService {
|
||||
} else {
|
||||
if (fname == null || lname == null)
|
||||
return Uni.createFrom().failure(new DBadRequestException("Nom et prénom requis"));
|
||||
return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)", lname,
|
||||
return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)",
|
||||
lname,
|
||||
fname).firstResult()
|
||||
.invoke(Unchecked.consumer(combModel -> {
|
||||
if (combModel == null)
|
||||
@@ -261,19 +423,71 @@ public class CompetitionService {
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<Void> removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId) {
|
||||
public Uni<Void> removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId, String source, boolean ban) {
|
||||
if ("admin".equals(source))
|
||||
return permService.hasEditPerm(securityCtx, id)
|
||||
.chain(c -> registerRepository.delete("competition = ?1 AND membre.id = ?2", c, combId)
|
||||
.invoke(Unchecked.consumer(l -> {
|
||||
if (l != 0){
|
||||
if (c.getSystem() == CompetitionSystem.SAFCA) {
|
||||
SReqRegister.sendRmIfNeed(serverCustom.clients, combId, id);
|
||||
}
|
||||
.chain(cm -> {
|
||||
if (cm.getBanMembre() == null)
|
||||
cm.setBanMembre(new ArrayList<>());
|
||||
if (ban) {
|
||||
if (!cm.getBanMembre().contains(combId))
|
||||
cm.getBanMembre().add(combId);
|
||||
} else {
|
||||
throw new DBadRequestException("Combattant non inscrit");
|
||||
cm.getBanMembre().remove(combId);
|
||||
}
|
||||
return Panache.withTransaction(() -> repository.persist(cm));
|
||||
})
|
||||
.chain(c -> deleteRegister(combId, c, true));
|
||||
if ("club".equals(source))
|
||||
return repository.findById(id)
|
||||
.invoke(Unchecked.consumer(cm -> {
|
||||
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|
||||
|| !securityCtx.isClubAdmin())
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
}))
|
||||
).replaceWithVoid();
|
||||
.call(cm -> membreService.getById(combId)
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (model == null)
|
||||
throw new DNotFoundException("Membre " + combId + " n'existe pas");
|
||||
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
})))
|
||||
.chain(c -> deleteRegister(combId, c, false));
|
||||
|
||||
return repository.findById(id)
|
||||
.call(cm -> membreService.getByAccountId(securityCtx.getSubject())
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (cm.getRegisterMode() != RegisterMode.FREE || !Objects.equals(model.getId(), combId))
|
||||
throw new DForbiddenException();
|
||||
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
||||
throw new DBadRequestException("Inscription fermée");
|
||||
})))
|
||||
.chain(c -> deleteRegister(combId, c, false));
|
||||
}
|
||||
|
||||
private Uni<Void> deleteRegister(Long combId, CompetitionModel c, boolean admin) {
|
||||
if (admin && combId < 0) {
|
||||
return competitionGuestRepository.find("competition = ?1 AND id = ?2", c, combId * -1).firstResult()
|
||||
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
|
||||
.call(Unchecked.function(
|
||||
model -> Panache.withTransaction(() -> competitionGuestRepository.delete(model))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom()
|
||||
.voidItem())))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
return registerRepository.find("competition = ?1 AND membre.id = ?2", c, combId).firstResult()
|
||||
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
|
||||
.call(Unchecked.function(registerModel -> {
|
||||
if (!admin && registerModel.isLockEdit())
|
||||
throw new DForbiddenException("Modification bloquée par l'administrateur de la compétition");
|
||||
return Panache.withTransaction(() -> registerRepository.delete(registerModel))
|
||||
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom().voidItem());
|
||||
}))
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
public Uni<?> delete(SecurityCtx securityCtx, Long id) {
|
||||
@@ -281,7 +495,7 @@ public class CompetitionService {
|
||||
if (!(securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")))
|
||||
throw new DForbiddenException();
|
||||
}))
|
||||
.call(competitionModel -> pouleRepository.list("compet = ?1", competitionModel)
|
||||
.call(competitionModel -> categoryRepository.list("compet = ?1", competitionModel)
|
||||
.call(pouleModels -> pouleModels.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
Uni.join().all(pouleModels.stream()
|
||||
.map(pouleModel -> Panache.withTransaction(
|
||||
@@ -289,7 +503,11 @@ public class CompetitionService {
|
||||
.toList())
|
||||
.andCollectFailures()))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> pouleRepository.delete("compet = ?1", competitionModel)))
|
||||
() -> categoryRepository.delete("compet = ?1", competitionModel)))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> registerRepository.delete("competition = ?1", competitionModel)))
|
||||
.call(competitionModel -> Panache.withTransaction(
|
||||
() -> competitionGuestRepository.delete("competition = ?1", competitionModel)))
|
||||
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
|
||||
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
|
||||
.call(__ -> cache.invalidate(id));
|
||||
@@ -362,4 +580,106 @@ public class CompetitionService {
|
||||
}))
|
||||
.call(__ -> cache.invalidate(data.getId()));
|
||||
}
|
||||
|
||||
public Uni<Response> unregisterHelloAsso(NotificationData data) {
|
||||
if (!data.getState().equals("Refunded"))
|
||||
return Uni.createFrom().item(Response.ok().build());
|
||||
|
||||
return helloAssoRepository.list("orderId = ?1", data.getOrder().getId())
|
||||
.chain(regs -> {
|
||||
Uni<?> uni = Uni.createFrom().nullItem();
|
||||
|
||||
for (HelloAssoRegisterModel reg : regs) {
|
||||
if (reg.getCompetition().getRegisterMode() != RegisterMode.HELLOASSO)
|
||||
continue;
|
||||
if (!data.getOrder().getOrganizationSlug().equalsIgnoreCase(reg.getCompetition().getData1()))
|
||||
continue;
|
||||
|
||||
uni = uni.call(__ -> Panache.withTransaction(
|
||||
() -> registerRepository.delete("competition = ?1 AND membre = ?2",
|
||||
reg.getCompetition(), reg.getMembre())))
|
||||
.call(r -> reg.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
|
||||
sRegister.sendRegisterRemove(reg.getCompetition().getUuid(),
|
||||
reg.getMembre().getId()) : Uni.createFrom().voidItem()).onFailure()
|
||||
.recoverWithNull()
|
||||
;
|
||||
}
|
||||
|
||||
return uni;
|
||||
})
|
||||
.onFailure().invoke(Throwable::printStackTrace)
|
||||
.map(__ -> Response.ok().build());
|
||||
}
|
||||
|
||||
public Uni<Response> registerHelloAsso(NotificationData data) {
|
||||
String organizationSlug = data.getOrganizationSlug();
|
||||
String formSlug = data.getFormSlug();
|
||||
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false, null, Categorie.CADET, Genre.NA,
|
||||
null, "fr");
|
||||
|
||||
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
|
||||
.onFailure().recoverWithNull()
|
||||
.chain(cm -> {
|
||||
Uni<?> uni = Uni.createFrom().nullItem();
|
||||
if (cm == null || cm.getRegisterMode() != RegisterMode.HELLOASSO)
|
||||
return uni;
|
||||
|
||||
List<String> place = List.of(cm.getData3().toLowerCase().split(";"));
|
||||
List<String> fail = new ArrayList<>();
|
||||
|
||||
for (NotificationData.Item item : data.getItems()) {
|
||||
if (!place.contains(item.getName().toLowerCase()))
|
||||
continue;
|
||||
if (item.getCustomFields() == null || item.getCustomFields().isEmpty()) {
|
||||
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
|
||||
item.getUser().getFirstName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<Long> optional = item.getCustomFields().stream()
|
||||
.filter(cf -> cf.getName().equalsIgnoreCase("Numéro de licence")).findAny().map(
|
||||
NotificationData.CustomField::getAnswer).map(Long::valueOf);
|
||||
|
||||
if (optional.isPresent()) {
|
||||
uni = uni.call(__ -> membreService.getByLicence(optional.get())
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null)
|
||||
throw new NotFoundException();
|
||||
}))
|
||||
.call(m -> Panache.withTransaction(() ->
|
||||
helloAssoRepository.persist(
|
||||
new HelloAssoRegisterModel(cm, m, data.getId()))))
|
||||
.chain(m -> updateRegister(req, cm, m, true)))
|
||||
.onFailure().recoverWithItem(throwable -> {
|
||||
fail.add("%s %s - licence n°%d".formatted(item.getUser().getLastName(),
|
||||
item.getUser().getFirstName(), optional.get()));
|
||||
return null;
|
||||
})
|
||||
.replaceWithVoid();
|
||||
} else {
|
||||
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
|
||||
item.getUser().getFirstName()));
|
||||
}
|
||||
}
|
||||
|
||||
return uni.call(__ -> fail.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
reactiveMailer.send(
|
||||
Mail.withText(cm.getData4(),
|
||||
"FFSAF - Compétition - Erreur HelloAsso",
|
||||
String.format(
|
||||
"""
|
||||
Bonjour,
|
||||
|
||||
Une erreur a été rencontrée lors de l'enregistrement d'une inscription à votre compétition %s pour les combattants suivants:
|
||||
%s
|
||||
|
||||
Cordialement,
|
||||
L'intranet de la FFSAF
|
||||
""", cm.getName(), String.join("\r\n", fail))
|
||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
||||
).onFailure().invoke(e -> LOGGER.error("Fail to send email", e)));
|
||||
})
|
||||
.onFailure().invoke(Throwable::printStackTrace)
|
||||
.map(__ -> Response.ok().build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.client.HelloAssoAuthClient;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.TokenResponse;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
@ApplicationScoped
|
||||
public class HelloAssoTokenService {
|
||||
private static final Logger LOG = Logger.getLogger(HelloAssoTokenService.class);
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
HelloAssoAuthClient authClient;
|
||||
|
||||
@ConfigProperty(name = "helloasso.client-id")
|
||||
String clientId;
|
||||
|
||||
@ConfigProperty(name = "helloasso.client-secret")
|
||||
String clientSecret;
|
||||
|
||||
private TokenResponse currentToken; // Stockage en mémoire (pour un seul pod)
|
||||
|
||||
// Récupère un token valide (en le rafraîchissant si nécessaire)
|
||||
public Uni<String> getValidAccessToken() {
|
||||
if (currentToken == null || currentToken.isExpired()) {
|
||||
return fetchNewToken(clientId, clientSecret);
|
||||
}
|
||||
return Uni.createFrom().item(currentToken.accessToken);
|
||||
}
|
||||
|
||||
// Récupère un nouveau token (via client_credentials ou refresh_token)
|
||||
private Uni<String> fetchNewToken(String clientId, String clientSecret) {
|
||||
if (currentToken != null && currentToken.refreshToken != null) {
|
||||
// On utilise le refresh_token si disponible
|
||||
return authClient.refreshToken("refresh_token", clientId, currentToken.refreshToken)
|
||||
.onItem().invoke(token -> {
|
||||
LOG.info("Token rafraîchi avec succès");
|
||||
currentToken = token;
|
||||
})
|
||||
.onFailure().recoverWithItem(e -> {
|
||||
LOG.warn("Échec du rafraîchissement, utilisation des credentials", e);
|
||||
return null; // Force l'utilisation des credentials
|
||||
})
|
||||
.flatMap(token -> token != null ?
|
||||
Uni.createFrom().item(token.accessToken) :
|
||||
getTokenWithCredentials(clientId, clientSecret)
|
||||
);
|
||||
} else {
|
||||
return getTokenWithCredentials(clientId, clientSecret);
|
||||
}
|
||||
}
|
||||
|
||||
// Récupère un token avec client_id/client_secret
|
||||
private Uni<String> getTokenWithCredentials(String clientId, String clientSecret) {
|
||||
return authClient.getToken("client_credentials", clientId, clientSecret)
|
||||
.onItem().invoke(token -> {
|
||||
LOG.info("Nouveau token obtenu");
|
||||
currentToken = token;
|
||||
})
|
||||
.onFailure().invoke(e -> LOG.error("Erreur lors de l'obtention du token", e))
|
||||
.map(token -> token.accessToken);
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,31 @@ public class KeycloakService {
|
||||
return Uni.createFrom().item(club::getClubId);
|
||||
}
|
||||
|
||||
public Uni<String> updateGroupFromClub(ClubModel club) {
|
||||
if (club.getClubId() == null) {
|
||||
return getGroupFromClub(club);
|
||||
} else {
|
||||
LOGGER.infof("Updating name of club group %d-%s...", club.getId(), club.getName());
|
||||
return vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
GroupRepresentation clubGroup =
|
||||
keycloak.realm(realm).groups().groups().stream().filter(g -> g.getName().equals("club"))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new KeycloakException("Fail to fetch group %s".formatted("club")));
|
||||
|
||||
keycloak.realm(realm).groups().group(clubGroup.getId()).getSubGroups(0, 1000, true).stream()
|
||||
.filter(g -> g.getName().startsWith(club.getId() + "-")).findAny()
|
||||
.ifPresent(groupRepresentation -> {
|
||||
groupRepresentation.setName(club.getId() + "-" + club.getName());
|
||||
keycloak.realm(realm).groups().group(groupRepresentation.getId())
|
||||
.update(groupRepresentation);
|
||||
});
|
||||
|
||||
return club.getClubId();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<String> getUserFromMember(MembreModel membreModel) {
|
||||
if (membreModel.getUserId() == null) {
|
||||
return Uni.createFrom()
|
||||
@@ -231,9 +256,6 @@ public class KeycloakService {
|
||||
user.setEmail(membreModel.getEmail());
|
||||
user.setEnabled(true);
|
||||
|
||||
user.setRequiredActions(List.of(RequiredAction.VERIFY_EMAIL.name(),
|
||||
RequiredAction.UPDATE_PASSWORD.name()));
|
||||
|
||||
try (Response response = keycloak.realm(realm).users().create(user)) {
|
||||
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo()
|
||||
.equals(Response.Status.CONFLICT))
|
||||
@@ -245,14 +267,8 @@ public class KeycloakService {
|
||||
return getUser(login).orElseThrow(
|
||||
() -> new KeycloakException("Fail to fetch user %s".formatted(finalLogin)));
|
||||
})
|
||||
.call(user -> enabled_email ?
|
||||
vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
keycloak.realm(realm).users().get(user.getId())
|
||||
.executeActionsEmail(List.of(RequiredAction.VERIFY_EMAIL.name(),
|
||||
RequiredAction.UPDATE_PASSWORD.name()));
|
||||
return null;
|
||||
}) : Uni.createFrom().nullItem())
|
||||
.invoke(user -> membreModel.setUserId(user.getId()))
|
||||
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
|
||||
.call(user -> enabled_email ? reactiveMailer.send(
|
||||
Mail.withText(user.getEmail(),
|
||||
"FFSAF - Creation de votre compte sur l'intranet",
|
||||
@@ -260,20 +276,22 @@ public class KeycloakService {
|
||||
"""
|
||||
Bonjour,
|
||||
|
||||
Suite à votre première inscription à la Fédération Française de Soft Armored Fighting (FFSAF), votre compte pour accéder à l'intranet a été créé.
|
||||
Ce compte vous permettra de consulter vos informations, de vous inscrire aux compétitions et de consulter vos résultats.
|
||||
|
||||
Vous allez recevoir dans les prochaines minutes un email vous demandant de vérifier votre email et de définir un mot de passe.
|
||||
Suite à votre première inscription %sà la Fédération Française de Soft Armored Fighting (FFSAF), votre compte intranet a été créé.
|
||||
Ce compte vous permettra de consulter vos informations et, dans un futur proche, de vous inscrire aux compétitions ainsi que d'en consulter les résultats.
|
||||
|
||||
L'intranet est accessible à l'adresse suivante : https://intra.ffsaf.fr
|
||||
Votre nom d'utilisateur est : %s
|
||||
|
||||
Pour définir votre mot de passe, rendez-vous sur l'intranet > "Connexion" > "Mot de passe oublié ?"
|
||||
|
||||
Si vous n'avez pas demandé cette inscription, veuillez contacter le support à l'adresse support@ffsaf.fr.
|
||||
(Pas de panique, nous ne vous enverrons pas de message autre que ce concernant votre compte)
|
||||
|
||||
Cordialement,
|
||||
L'équipe de la FFSAF
|
||||
""", user.getUsername())
|
||||
""",
|
||||
membreModel.getRole() == RoleAsso.MEMBRE ? "par votre club (" + membreModel.getClub()
|
||||
.getName() + ") " : "", user.getUsername())
|
||||
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
||||
) : Uni.createFrom().nullItem())
|
||||
.call(user -> membreService.setUserId(membreModel.getId(), user.getId()))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
||||
import fr.titionfire.ffsaf.data.model.LogModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.LicenceRepository;
|
||||
@@ -17,13 +18,16 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class LicenceService {
|
||||
private static final Logger LOGGER = Logger.getLogger(LicenceService.class);
|
||||
|
||||
@Inject
|
||||
LicenceRepository repository;
|
||||
@@ -34,6 +38,15 @@ public class LicenceService {
|
||||
@Inject
|
||||
SequenceRepository sequenceRepository;
|
||||
|
||||
@Inject
|
||||
KeycloakService keycloakService;
|
||||
|
||||
@Inject
|
||||
LoggerService ls;
|
||||
|
||||
@Inject
|
||||
CheckoutService checkoutService;
|
||||
|
||||
public Uni<List<LicenceModel>> getLicence(long id, Consumer<MembreModel> checkPerm) {
|
||||
return combRepository.findById(id).invoke(checkPerm)
|
||||
.chain(combRepository -> Mutiny.fetch(combRepository.getLicences()));
|
||||
@@ -48,6 +61,29 @@ public class LicenceService {
|
||||
.chain(membres -> repository.find("saison = ?1 AND membre IN ?2", Utils.getSaison(), membres).list());
|
||||
}
|
||||
|
||||
public Uni<?> valideLicences(List<Long> ids) {
|
||||
Uni<String> uni = Uni.createFrom().nullItem();
|
||||
|
||||
for (Long id : ids) {
|
||||
uni = uni.chain(__ -> repository.find("membre.id = ?1 AND saison = ?2", id, Utils.getSaison()).firstResult()
|
||||
.chain(model -> {
|
||||
if (!model.isValidate())
|
||||
ls.logUpdate("validation de la licence", model);
|
||||
return validateLicences(model);
|
||||
}))
|
||||
.map(__ -> "OK");
|
||||
}
|
||||
return uni.call(__ -> ls.append());
|
||||
}
|
||||
|
||||
protected Uni<LicenceModel> validateLicences(LicenceModel model) {
|
||||
model.setValidate(true);
|
||||
return Panache.withTransaction(() -> repository.persist(model)
|
||||
.call(m -> Mutiny.fetch(m.getMembre())
|
||||
.call(genLicenceNumberAndAccountIfNeed())
|
||||
));
|
||||
}
|
||||
|
||||
public Uni<LicenceModel> setLicence(long id, LicenceForm form) {
|
||||
if (form.getId() == -1) {
|
||||
return combRepository.findById(id).chain(membreModel -> {
|
||||
@@ -57,33 +93,71 @@ public class LicenceService {
|
||||
model.setSaison(form.getSaison());
|
||||
model.setCertificate(form.getCertificate());
|
||||
model.setValidate(form.isValidate());
|
||||
model.setPay(form.isPay());
|
||||
return Panache.withTransaction(() -> repository.persist(model)
|
||||
.call(m -> (m.isValidate() && membreModel.getLicence() <= 0) ?
|
||||
sequenceRepository.getNextValueInTransaction(SequenceType.Licence)
|
||||
.invoke(i -> membreModel.setLicence(Math.toIntExact(i)))
|
||||
.chain(() -> combRepository.persist(membreModel))
|
||||
.call(m -> m.isValidate() ? Uni.createFrom().item(membreModel)
|
||||
.call(genLicenceNumberAndAccountIfNeed())
|
||||
: Uni.createFrom().nullItem()
|
||||
));
|
||||
))
|
||||
.call(licenceModel -> ls.logA(LogModel.ActionType.ADD, membreModel.getObjectName(),
|
||||
licenceModel));
|
||||
});
|
||||
} else {
|
||||
return repository.findById(form.getId()).chain(model -> {
|
||||
ls.logChange("Certificate", model.getCertificate(), form.getCertificate(), model);
|
||||
ls.logChange("Validate", model.isValidate(), form.isValidate(), model);
|
||||
ls.logChange("Pay", model.isPay(), form.isPay(), model);
|
||||
model.setCertificate(form.getCertificate());
|
||||
model.setValidate(form.isValidate());
|
||||
model.setPay(form.isPay());
|
||||
return Panache.withTransaction(() -> repository.persist(model)
|
||||
.call(m -> m.isValidate() ? Mutiny.fetch(m.getMembre())
|
||||
.call(membreModel -> (membreModel.getLicence() <= 0) ?
|
||||
sequenceRepository.getNextValueInTransaction(SequenceType.Licence)
|
||||
.invoke(i -> membreModel.setLicence(Math.toIntExact(i)))
|
||||
.chain(() -> combRepository.persist(membreModel))
|
||||
: Uni.createFrom().nullItem())
|
||||
.call(genLicenceNumberAndAccountIfNeed())
|
||||
: Uni.createFrom().nullItem()
|
||||
));
|
||||
))
|
||||
.call(__ -> ls.append());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Function<MembreModel, Uni<?>> genLicenceNumberAndAccountIfNeed() {
|
||||
return membreModel -> ((membreModel.getLicence() <= 0) ?
|
||||
sequenceRepository.getNextValueInTransaction(SequenceType.Licence)
|
||||
.invoke(i -> membreModel.setLicence(Math.toIntExact(i)))
|
||||
.chain(() -> combRepository.persist(membreModel))
|
||||
: Uni.createFrom().nullItem())
|
||||
.call(__ -> (membreModel.getUserId() == null) ?
|
||||
keycloakService.initCompte(membreModel.getId()).onFailure()
|
||||
.invoke(t -> LOGGER.infof("Failed to init account: %s", t.getMessage())).onFailure()
|
||||
.recoverWithNull()
|
||||
: Uni.createFrom().nullItem());
|
||||
}
|
||||
|
||||
public Uni<String> payLicences(List<Long> ids, Consumer<MembreModel> checkPerm, SecurityCtx securityCtx) {
|
||||
return repository.list("membre.id IN ?1 AND saison = ?2 AND pay = FALSE", ids, Utils.getSaison())
|
||||
.invoke(Unchecked.consumer(models -> {
|
||||
if (models.size() != ids.size())
|
||||
throw new DBadRequestException("Erreur lors de la sélection des membres");
|
||||
}))
|
||||
.call(models -> {
|
||||
Uni<?> uni = Uni.createFrom().nullItem();
|
||||
for (LicenceModel model : models)
|
||||
uni = uni.chain(__ -> Mutiny.fetch(model.getMembre()).invoke(checkPerm));
|
||||
return uni;
|
||||
})
|
||||
.chain(models -> checkoutService.create(models.stream().map(LicenceModel::getId).toList(),
|
||||
securityCtx));
|
||||
}
|
||||
|
||||
public Uni<?> deleteLicence(long id) {
|
||||
return Panache.withTransaction(() -> repository.deleteById(id));
|
||||
return repository.findById(id)
|
||||
.call(__ -> checkoutService.canDeleteLicence(id)
|
||||
.invoke(Unchecked.consumer(b -> {
|
||||
if (!b) throw new DBadRequestException(
|
||||
"Impossible de supprimer une licence pour laquelle un paiement est en cours");
|
||||
})))
|
||||
.call(model -> ls.logADelete(model))
|
||||
.chain(model -> repository.delete(model));
|
||||
}
|
||||
|
||||
public Uni<LicenceModel> askLicence(long id, LicenceForm form, Consumer<MembreModel> checkPerm) {
|
||||
@@ -101,11 +175,15 @@ public class LicenceService {
|
||||
model.setCertificate(form.getCertificate());
|
||||
model.setValidate(false);
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
}));
|
||||
}))
|
||||
.call(licenceModel -> ls.logA(LogModel.ActionType.ADD, membreModel.getObjectName(),
|
||||
licenceModel));
|
||||
} else {
|
||||
return repository.findById(form.getId()).chain(model -> {
|
||||
ls.logChange("Certificate", model.getCertificate(), form.getCertificate(), model);
|
||||
model.setCertificate(form.getCertificate());
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
return Panache.withTransaction(() -> repository.persist(model))
|
||||
.call(__ -> ls.append());
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -114,10 +192,18 @@ public class LicenceService {
|
||||
public Uni<?> deleteAskLicence(long id, Consumer<MembreModel> checkPerm) {
|
||||
return repository.findById(id)
|
||||
.call(licenceModel -> Mutiny.fetch(licenceModel.getMembre()).invoke(checkPerm))
|
||||
.call(__ -> checkoutService.canDeleteLicence(id)
|
||||
.invoke(Unchecked.consumer(b -> {
|
||||
if (!b) throw new DBadRequestException(
|
||||
"Impossible de supprimer une licence pour laquelle un paiement est en cours");
|
||||
})))
|
||||
.invoke(Unchecked.consumer(licenceModel -> {
|
||||
if (licenceModel.isValidate())
|
||||
throw new DBadRequestException("Impossible de supprimer une licence déjà validée");
|
||||
if (licenceModel.isPay())
|
||||
throw new DBadRequestException("Impossible de supprimer une licence déjà payée");
|
||||
}))
|
||||
.call(model -> ls.logADelete(model))
|
||||
.chain(__ -> Panache.withTransaction(() -> repository.deleteById(id)));
|
||||
}
|
||||
|
||||
|
||||
@@ -71,10 +71,18 @@ public class LoggerService {
|
||||
message));
|
||||
}
|
||||
|
||||
public void logAnonymous(ActionType action, ObjectType object, String message, String target_name, Long target_id) {
|
||||
buffer.add(new LogModel(null, null, new Date(), action, object, target_id, target_name, message));
|
||||
}
|
||||
|
||||
public void log(ActionType action, String message, LoggableModel model) {
|
||||
log(action, model.getObjectType(), message, model.getObjectName(), model.getId());
|
||||
}
|
||||
|
||||
public void logAnonymous(ActionType action, String message, LoggableModel model) {
|
||||
logAnonymous(action, model.getObjectType(), message, model.getObjectName(), model.getId());
|
||||
}
|
||||
|
||||
public void logAdd(LoggableModel model) {
|
||||
log(ActionType.ADD, "", model);
|
||||
}
|
||||
@@ -83,6 +91,10 @@ public class LoggerService {
|
||||
log(ActionType.UPDATE, message, model);
|
||||
}
|
||||
|
||||
public void logUpdateAnonymous(String message, LoggableModel model) {
|
||||
logAnonymous(ActionType.UPDATE, message, model);
|
||||
}
|
||||
|
||||
public void logChange(String champ, Object o1, Object o2, LoggableModel model) {
|
||||
if (Objects.equals(o1, o2))
|
||||
return;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionGuestRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.PouleRepository;
|
||||
import fr.titionfire.ffsaf.rest.data.MatchData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
@@ -25,7 +27,7 @@ public class MatchService {
|
||||
MatchRepository repository;
|
||||
|
||||
@Inject
|
||||
PouleRepository pouleRepository;
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
@@ -33,17 +35,20 @@ public class MatchService {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
public Uni<MatchData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
@Inject
|
||||
CompetitionGuestRepository competitionGuestRepository;
|
||||
|
||||
public Uni<MatchData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getPoule().getCompet()))
|
||||
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCategory().getCompet()))
|
||||
.map(MatchData::fromModel);
|
||||
}
|
||||
|
||||
public Uni<List<MatchData>> getAllByPoule(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
public Uni<List<MatchData>> getAllByPouleAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return categoryRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
||||
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet()))
|
||||
.chain(data -> repository.list("poule = ?1", data.getId())
|
||||
.map(o -> o.stream().map(MatchData::fromModel).toList()));
|
||||
}
|
||||
@@ -52,21 +57,21 @@ public class MatchService {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||
.chain(o -> {
|
||||
if (o == null) {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
||||
return categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
.map(pouleModel -> {
|
||||
.map(categoryModel -> {
|
||||
MatchModel model = new MatchModel();
|
||||
|
||||
model.setId(null);
|
||||
model.setSystem(system);
|
||||
model.setSystemId(data.getId());
|
||||
model.setPoule(pouleModel);
|
||||
model.setCategory(categoryModel);
|
||||
return model;
|
||||
});
|
||||
} else {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
||||
return categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
@@ -75,9 +80,7 @@ public class MatchService {
|
||||
}
|
||||
)
|
||||
.chain(o -> {
|
||||
o.setC1_str(data.getC1_str());
|
||||
o.setC2_str(data.getC2_str());
|
||||
o.setPoule_ord(data.getPoule_ord());
|
||||
o.setCategory_ord(data.getCategory_ord());
|
||||
o.getScores().clear();
|
||||
o.getScores().addAll(data.getScores());
|
||||
|
||||
@@ -88,6 +91,20 @@ public class MatchService {
|
||||
.chain(() -> (data.getC1_id() == null) ?
|
||||
Uni.createFrom().nullItem() : combRepository.findById(data.getC2_id()))
|
||||
.invoke(o::setC2_id)
|
||||
.chain(() -> (data.getC1_str() == null) ?
|
||||
Uni.createFrom()
|
||||
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
|
||||
"fname = ?1 AND lname = ?2",
|
||||
data.getC1_str().substring(0, data.getC1_str().indexOf(" ")),
|
||||
data.getC1_str().substring(data.getC1_str().indexOf(" ") + 1)).firstResult())
|
||||
.invoke(o::setC1_guest)
|
||||
.chain(() -> (data.getC2_str() == null) ?
|
||||
Uni.createFrom()
|
||||
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
|
||||
"fname = ?1 AND lname = ?2",
|
||||
data.getC2_str().substring(0, data.getC2_str().indexOf(" ")),
|
||||
data.getC2_str().substring(data.getC2_str().indexOf(" ") + 1)).firstResult())
|
||||
.invoke(o::setC2_guest)
|
||||
.chain(() -> Panache.withTransaction(() -> repository.persist(o)));
|
||||
})
|
||||
.map(MatchData::fromModel);
|
||||
@@ -97,7 +114,7 @@ public class MatchService {
|
||||
List<ScoreEmbeddable> scores) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCategory().getCompet()))
|
||||
.invoke(data -> {
|
||||
data.getScores().clear();
|
||||
data.getScores().addAll(scores);
|
||||
@@ -109,7 +126,7 @@ public class MatchService {
|
||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCategory().getCompet()))
|
||||
.chain(data -> Panache.withTransaction(() -> repository.delete(data)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import fr.titionfire.ffsaf.rest.data.SimpleMembre;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DInternalError;
|
||||
import fr.titionfire.ffsaf.rest.from.FullMemberForm;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
@@ -27,22 +27,13 @@ import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static fr.titionfire.ffsaf.domain.service.ClubService.getPdf;
|
||||
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@@ -67,8 +58,6 @@ public class MembreService {
|
||||
@ConfigProperty(name = "upload_dir")
|
||||
String media;
|
||||
|
||||
@ConfigProperty(name = "pdf-maker.jar-path")
|
||||
String pdfMakerJarPath;
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
|
||||
@@ -90,44 +79,133 @@ public class MembreService {
|
||||
final static String FIND_NAME_REQUEST = "unaccent(fname) ILIKE unaccent(?1) OR unaccent(lname) ILIKE unaccent(?1) " +
|
||||
"OR unaccent(fname || ' ' || lname) ILIKE unaccent(?1) OR unaccent(lname || ' ' || fname) ILIKE unaccent(?1)";
|
||||
|
||||
public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, String club) {
|
||||
private Uni<List<LicenceModel>> getLicenceListe(int licenceRequest, int payState) {
|
||||
Uni<List<LicenceModel>> baseUni;
|
||||
String queryStr = "saison = ?1";
|
||||
if (payState == 0)
|
||||
queryStr += " AND pay = FALSE";
|
||||
if (payState == 1)
|
||||
queryStr += " AND pay = TRUE";
|
||||
if (licenceRequest == 0 || licenceRequest == 1)
|
||||
baseUni = licenceRepository.list(queryStr, Utils.getSaison());
|
||||
else if (licenceRequest == 2)
|
||||
baseUni = licenceRepository.list(queryStr + " AND validate = FALSE", Utils.getSaison());
|
||||
else if (licenceRequest == 5)
|
||||
baseUni = licenceRepository.list(queryStr + " AND validate = FALSE AND LENGTH(certificate) >= 3",
|
||||
Utils.getSaison());
|
||||
else if (licenceRequest == 6)
|
||||
baseUni = licenceRepository.list(queryStr + " AND validate = FALSE AND LENGTH(certificate) <= 2",
|
||||
Utils.getSaison());
|
||||
else if (licenceRequest == 3)
|
||||
baseUni = licenceRepository.list(queryStr + " AND validate = TRUE", Utils.getSaison());
|
||||
else
|
||||
baseUni = Uni.createFrom().item(new ArrayList<>());
|
||||
return baseUni;
|
||||
}
|
||||
|
||||
private Sort getSort(String order) {
|
||||
|
||||
Sort sort;
|
||||
if (order == null || order.isBlank()) {
|
||||
sort = Sort.ascending("fname", "lname");
|
||||
} else {
|
||||
sort = Sort.empty();
|
||||
|
||||
for (String e : order.split(",")) {
|
||||
String[] split = e.split(" ");
|
||||
if (split.length == 2) {
|
||||
sort = sort.and(split[0],
|
||||
split[1].equals("n") ? Sort.Direction.Ascending : Sort.Direction.Descending);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sort;
|
||||
}
|
||||
|
||||
public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, String club,
|
||||
int licenceRequest, int payState, String order, String categorie) {
|
||||
if (search == null)
|
||||
search = "";
|
||||
search = "%" + search.replaceAll(" ", "% %") + "%";
|
||||
|
||||
String categorieFilter;
|
||||
if (categorie == null || categorie.isBlank())
|
||||
categorieFilter = " True";
|
||||
else
|
||||
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
|
||||
|
||||
String finalSearch = search;
|
||||
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
|
||||
|
||||
Sort sort = getSort(order);
|
||||
if (sort == null)
|
||||
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
|
||||
|
||||
return baseUni
|
||||
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
|
||||
.chain(ids -> {
|
||||
PanacheQuery<MembreModel> query;
|
||||
|
||||
String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN");
|
||||
|
||||
if (club == null || club.isBlank()) {
|
||||
query = repository.find(FIND_NAME_REQUEST, Sort.ascending("fname", "lname"), search)
|
||||
query = repository.find(
|
||||
"id " + idf + " ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
||||
sort, finalSearch, ids)
|
||||
.page(Page.ofSize(limit));
|
||||
} else {
|
||||
if (club.equals("null")) {
|
||||
query = repository.find(
|
||||
"club IS NULL AND (" + FIND_NAME_REQUEST + ")",
|
||||
Sort.ascending("fname", "lname"), search).page(Page.ofSize(limit));
|
||||
"id " + idf + " ?2 AND club IS NULL AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
||||
sort, finalSearch, ids).page(Page.ofSize(limit));
|
||||
} else {
|
||||
query = repository.find(
|
||||
"LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ")",
|
||||
Sort.ascending("fname", "lname"), search, club + "%").page(Page.ofSize(limit));
|
||||
"id " + idf + " ?3 AND LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
||||
sort, finalSearch, club, ids)
|
||||
.page(Page.ofSize(limit));
|
||||
}
|
||||
}
|
||||
return getPageResult(query, limit, page);
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, String subject) {
|
||||
public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, int licenceRequest, int payState,
|
||||
String order, String categorie, String subject) {
|
||||
if (search == null)
|
||||
search = "";
|
||||
search = "%" + search.replaceAll(" ", "% %") + "%";
|
||||
|
||||
String finalSearch = search;
|
||||
|
||||
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
|
||||
|
||||
String categorieFilter;
|
||||
if (categorie == null || categorie.isBlank())
|
||||
categorieFilter = " True";
|
||||
else
|
||||
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
|
||||
|
||||
Sort sort = getSort(order);
|
||||
if (sort == null)
|
||||
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
|
||||
|
||||
return baseUni
|
||||
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
|
||||
.chain(ids -> {
|
||||
String idf = ((licenceRequest == 0 || licenceRequest == 4) ? "NOT IN" : "IN");
|
||||
|
||||
return repository.find("userId = ?1", subject).firstResult()
|
||||
.chain(membreModel -> {
|
||||
PanacheQuery<MembreModel> query = repository.find(
|
||||
"club = ?2 AND (" + FIND_NAME_REQUEST + ")",
|
||||
Sort.ascending("fname", "lname"), finalSearch, membreModel.getClub())
|
||||
"id " + idf + " ?3 AND club = ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter,
|
||||
sort, finalSearch, membreModel.getClub(), ids)
|
||||
.page(Page.ofSize(limit));
|
||||
return getPageResult(query, limit, page);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private Uni<PageResult<SimpleMembre>> getPageResult(PanacheQuery<MembreModel> query, int limit, int page) {
|
||||
@@ -162,26 +240,37 @@ public class MembreService {
|
||||
return Uni.createFrom().nullItem();
|
||||
AtomicReference<ClubModel> clubModel = new AtomicReference<>();
|
||||
|
||||
LOGGER.debugf("Membre import (size=%d)", data2.size());
|
||||
for (SimpleMembreInOutData simpleMembreInOutData : data2) {
|
||||
LOGGER.debugf("-> %s", simpleMembreInOutData.toString());
|
||||
}
|
||||
|
||||
return repository.find("userId = ?1", subject).firstResult()
|
||||
.chain(membreModel -> {
|
||||
clubModel.set(membreModel.getClub());
|
||||
if (data2.stream().noneMatch(d -> d.getLicence() != null))
|
||||
return Uni.createFrom().item(new ArrayList<MembreModel>());
|
||||
return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2",
|
||||
return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2 OR email IN ?3",
|
||||
data2.stream().map(SimpleMembreInOutData::getLicence).filter(Objects::nonNull).toList(),
|
||||
data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList());
|
||||
data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList(),
|
||||
data2.stream().map(SimpleMembreInOutData::getEmail).filter(o -> o != null && !o.isBlank())
|
||||
.toList());
|
||||
})
|
||||
.call(Unchecked.function(membres -> {
|
||||
for (MembreModel membreModel : membres) {
|
||||
if (!Objects.equals(membreModel.getClub(), clubModel.get()))
|
||||
if (!Objects.equals(membreModel.getClub(), clubModel.get())) {
|
||||
LOGGER.info("Similar membres found: " + membreModel);
|
||||
throw new DForbiddenException(
|
||||
"Le membre n°" + membreModel.getLicence() + " n'appartient pas à votre club");
|
||||
}
|
||||
}
|
||||
Uni<Void> uniResult = Uni.createFrom().voidItem();
|
||||
for (SimpleMembreInOutData dataIn : data2) {
|
||||
MembreModel model = membres.stream()
|
||||
.filter(m -> Objects.equals(m.getLicence(), dataIn.getLicence()) || m.getLname()
|
||||
.equals(dataIn.getNom()) && m.getFname().equals(dataIn.getPrenom())).findFirst()
|
||||
.filter(m -> (dataIn.getLicence() != null && Objects.equals(m.getLicence(),
|
||||
dataIn.getLicence())) || m.getLname().equals(dataIn.getNom()) && m.getFname()
|
||||
.equals(dataIn.getPrenom()) || (dataIn.getEmail() != null && !dataIn.getEmail()
|
||||
.isBlank() && Objects.equals(m.getFname(), dataIn.getEmail()))).findFirst()
|
||||
.orElseGet(() -> {
|
||||
MembreModel mm = new MembreModel();
|
||||
mm.setClub(clubModel.get());
|
||||
@@ -189,12 +278,32 @@ public class MembreService {
|
||||
mm.setCountry("FR");
|
||||
return mm;
|
||||
});
|
||||
if (model.getId() != null) {
|
||||
LOGGER.debugf("updating -> %s", dataIn.toString());
|
||||
} else {
|
||||
LOGGER.debugf("creating -> %s", dataIn.toString());
|
||||
}
|
||||
|
||||
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
||||
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
||||
LOGGER.info("Similar membres found: " + model);
|
||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
||||
}
|
||||
|
||||
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
||||
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
||||
LOGGER.info("Similar membres found: " + model);
|
||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
||||
}
|
||||
}
|
||||
|
||||
boolean add = model.getId() == null;
|
||||
|
||||
if ((!add && StringSimilarity.similarity(model.getLname().toUpperCase(),
|
||||
dataIn.getNom().toUpperCase()) > 3) || (!add && StringSimilarity.similarity(
|
||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) {
|
||||
LOGGER.info("Similar membres found: " + model);
|
||||
throw new DBadRequestException(
|
||||
"Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide.");
|
||||
}
|
||||
@@ -268,6 +377,11 @@ public class MembreService {
|
||||
|
||||
public Uni<String> update(long id, FullMemberForm membre) {
|
||||
return update(repository.findById(id)
|
||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||
.invoke(Unchecked.consumer(c -> {
|
||||
if (c > 0 && !membre.getEmail().isBlank())
|
||||
throw new DBadRequestException("Email déjà utiliser");
|
||||
})))
|
||||
.chain(membreModel -> clubRepository.findById(membre.getClub())
|
||||
.map(club -> new Pair<>(membreModel, club)))
|
||||
.onItem().transform(pair -> {
|
||||
@@ -285,9 +399,20 @@ public class MembreService {
|
||||
|
||||
public Uni<String> update(long id, FullMemberForm membre, SecurityCtx securityCtx) {
|
||||
return update(repository.findById(id)
|
||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||
.invoke(Unchecked.consumer(c -> {
|
||||
if (c > 0 && !membre.getEmail().isBlank())
|
||||
throw new DBadRequestException("Email déjà utiliser");
|
||||
})))
|
||||
.invoke(Unchecked.consumer(membreModel -> {
|
||||
if (!securityCtx.isInClubGroup(membreModel.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
if (StringSimilarity.similarity(membreModel.getLname().toUpperCase(),
|
||||
membre.getLname().toUpperCase()) > 3 || StringSimilarity.similarity(
|
||||
membreModel.getFname().toUpperCase(), membre.getFname().toUpperCase()) > 3) {
|
||||
throw new DBadRequestException(
|
||||
"Pour enregistrer un nouveau membre, veuillez utilisez le bouton prévue a cette effet.");
|
||||
}
|
||||
}))
|
||||
.invoke(Unchecked.consumer(membreModel -> {
|
||||
RoleAsso source = RoleAsso.MEMBRE;
|
||||
@@ -365,6 +490,10 @@ public class MembreService {
|
||||
|
||||
public Uni<Long> add(FullMemberForm input) {
|
||||
return clubRepository.findById(input.getClub())
|
||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||
.invoke(Unchecked.consumer(c -> {
|
||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
||||
})))
|
||||
.chain(clubModel -> {
|
||||
MembreModel model = getMembreModel(input, clubModel);
|
||||
return Panache.withTransaction(() -> repository.persist(model));
|
||||
@@ -377,6 +506,18 @@ public class MembreService {
|
||||
|
||||
public Uni<Long> add(FullMemberForm input, String subject) {
|
||||
return repository.find("userId = ?1", subject).firstResult()
|
||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||
.invoke(Unchecked.consumer(c -> {
|
||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
||||
})))
|
||||
.call(membreModel ->
|
||||
repository.count(
|
||||
"unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2) AND club = ?3",
|
||||
input.getLname(), input.getFname(), membreModel.getClub())
|
||||
.invoke(Unchecked.consumer(c -> {
|
||||
if (c > 0)
|
||||
throw new DBadRequestException("Membre déjà existent");
|
||||
})))
|
||||
.chain(membreModel -> {
|
||||
MembreModel model = getMembreModel(input, membreModel.getClub());
|
||||
model.setRole(RoleAsso.MEMBRE);
|
||||
@@ -477,70 +618,4 @@ public class MembreService {
|
||||
.map(__ -> null);
|
||||
}
|
||||
|
||||
public Uni<Response> getLicencePdf(String subject) {
|
||||
return getLicencePdf(repository.find("userId = ?1", subject).firstResult()
|
||||
.call(m -> Mutiny.fetch(m.getLicences())));
|
||||
}
|
||||
|
||||
public Uni<Response> getLicencePdf(Uni<MembreModel> uniBase) {
|
||||
return uniBase
|
||||
.map(Unchecked.function(m -> {
|
||||
LicenceModel licence = m.getLicences().stream()
|
||||
.filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate())
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
|
||||
|
||||
try {
|
||||
byte[] buff = make_pdf(m, licence);
|
||||
if (buff == null)
|
||||
throw new IOException("Error making pdf");
|
||||
|
||||
String mimeType = "application/pdf";
|
||||
|
||||
Response.ResponseBuilder resp = Response.ok(buff);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, buff.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" +
|
||||
(Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\"");
|
||||
return resp.build();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add("java");
|
||||
cmd.add("-jar");
|
||||
cmd.add(pdfMakerJarPath);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
cmd.add("/tmp/" + uuid + ".pdf");
|
||||
cmd.add("membre");
|
||||
cmd.add(m.getFname());
|
||||
cmd.add(m.getLname());
|
||||
cmd.add(m.getGenre().str);
|
||||
cmd.add(m.getCategorie().getName());
|
||||
cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate());
|
||||
cmd.add(Utils.getSaison() + "");
|
||||
cmd.add(m.getLicence() + "");
|
||||
cmd.add(m.getClub().getName());
|
||||
cmd.add(m.getClub().getNo_affiliation() + "");
|
||||
cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date()));
|
||||
|
||||
FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + ".");
|
||||
File[] files = new File(media, "ppMembre").listFiles(filter);
|
||||
if (files != null && files.length > 0) {
|
||||
File file = files[0];
|
||||
cmd.add(file.getAbsolutePath());
|
||||
} else {
|
||||
cmd.add("/dev/null");
|
||||
}
|
||||
|
||||
return getPdf(cmd, uuid, LOGGER);
|
||||
}
|
||||
}
|
||||
|
||||
232
src/main/java/fr/titionfire/ffsaf/domain/service/PDFService.java
Normal file
232
src/main/java/fr/titionfire/ffsaf/domain/service/PDFService.java
Normal file
@@ -0,0 +1,232 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.repository.ClubRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class PDFService {
|
||||
private static final Logger LOGGER = Logger.getLogger(PDFService.class);
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
@Inject
|
||||
ClubRepository clubRepository;
|
||||
|
||||
@ConfigProperty(name = "upload_dir")
|
||||
String media;
|
||||
|
||||
@ConfigProperty(name = "pdf-maker.jar-path")
|
||||
String pdfMakerJarPath;
|
||||
|
||||
@ConfigProperty(name = "pdf-maker.sign-file")
|
||||
String sign_file;
|
||||
|
||||
|
||||
public Uni<Response> getLicencePdf(String subject) {
|
||||
return getLicencePdf(combRepository.find("userId = ?1", subject).firstResult()
|
||||
.call(m -> Mutiny.fetch(m.getLicences())));
|
||||
}
|
||||
|
||||
public Uni<Response> getLicencePdf(Uni<MembreModel> uniBase) {
|
||||
return uniBase
|
||||
.map(Unchecked.function(m -> {
|
||||
LicenceModel licence = m.getLicences().stream()
|
||||
.filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate())
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours"));
|
||||
|
||||
try {
|
||||
byte[] buff = make_pdf(m, licence);
|
||||
if (buff == null)
|
||||
throw new IOException("Error making pdf");
|
||||
|
||||
String mimeType = "application/pdf";
|
||||
|
||||
Response.ResponseBuilder resp = Response.ok(buff);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, buff.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" +
|
||||
(Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\"");
|
||||
return resp.build();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add("java");
|
||||
cmd.add("-jar");
|
||||
cmd.add(pdfMakerJarPath);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
cmd.add("/tmp/" + uuid + ".pdf");
|
||||
cmd.add("membre");
|
||||
cmd.add(m.getFname());
|
||||
cmd.add(m.getLname());
|
||||
cmd.add(m.getGenre().str);
|
||||
cmd.add(m.getCategorie().getName());
|
||||
cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate());
|
||||
cmd.add(Utils.getSaison() + "");
|
||||
cmd.add(m.getLicence() + "");
|
||||
cmd.add(m.getClub().getName());
|
||||
cmd.add(m.getClub().getNo_affiliation() + "");
|
||||
cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date()));
|
||||
|
||||
FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + ".");
|
||||
File[] files = new File(media, "ppMembre").listFiles(filter);
|
||||
if (files != null && files.length > 0) {
|
||||
File file = files[0];
|
||||
cmd.add(file.getAbsolutePath());
|
||||
} else {
|
||||
cmd.add("/dev/null");
|
||||
}
|
||||
|
||||
return getPdf(cmd, uuid);
|
||||
}
|
||||
|
||||
public Uni<Response> getAffiliationPdf(String subject) {
|
||||
return getAffiliationPdf(
|
||||
combRepository.find("userId = ?1", subject).firstResult()
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null || m.getClub() == null)
|
||||
throw new DNotFoundException("Club non trouvé");
|
||||
}))
|
||||
.map(MembreModel::getClub)
|
||||
.call(m -> Mutiny.fetch(m.getAffiliations())));
|
||||
}
|
||||
|
||||
public Uni<Response> getAffiliationPdf(long id) {
|
||||
return getAffiliationPdf(
|
||||
clubRepository.findById(id)
|
||||
.invoke(Unchecked.consumer(m -> {
|
||||
if (m == null)
|
||||
throw new DNotFoundException("Club non trouvé");
|
||||
}))
|
||||
.call(m -> Mutiny.fetch(m.getAffiliations())));
|
||||
}
|
||||
|
||||
|
||||
private Uni<Response> getAffiliationPdf(Uni<ClubModel> uniBase) {
|
||||
return uniBase
|
||||
.map(Unchecked.function(m -> {
|
||||
if (m.getAffiliations().stream()
|
||||
.noneMatch(licenceModel -> licenceModel.getSaison() == Utils.getSaison()))
|
||||
throw new DNotFoundException("Pas d'affiliation pour la saison en cours");
|
||||
|
||||
try {
|
||||
byte[] buff = make_pdf(m);
|
||||
if (buff == null)
|
||||
throw new IOException("Error making pdf");
|
||||
|
||||
String mimeType = "application/pdf";
|
||||
|
||||
Response.ResponseBuilder resp = Response.ok(buff);
|
||||
resp.type(MediaType.APPLICATION_OCTET_STREAM);
|
||||
resp.header(HttpHeaders.CONTENT_LENGTH, buff.length);
|
||||
resp.header(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||
resp.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; " + "filename=\"Attestation d'affiliation " + Utils.getSaison() + "-" +
|
||||
(Utils.getSaison() + 1) + " de " + m.getName() + ".pdf\"");
|
||||
return resp.build();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private byte[] make_pdf(ClubModel m) throws IOException, InterruptedException {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add("java");
|
||||
cmd.add("-jar");
|
||||
cmd.add(pdfMakerJarPath);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
cmd.add("/tmp/" + uuid + ".pdf");
|
||||
cmd.add("club");
|
||||
cmd.add(m.getName());
|
||||
cmd.add(Utils.getSaison() + "");
|
||||
cmd.add(m.getNo_affiliation() + "");
|
||||
cmd.add(new File(sign_file).getAbsolutePath());
|
||||
|
||||
return getPdf(cmd, uuid);
|
||||
}
|
||||
|
||||
static byte[] getPdf(List<String> cmd, UUID uuid) throws IOException, InterruptedException {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
Process process = processBuilder.start();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
builder.append(line).append("\n");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
int code = -1;
|
||||
if (!process.waitFor(30, TimeUnit.SECONDS)) {
|
||||
process.destroy();
|
||||
builder.append("Timeout...");
|
||||
} else {
|
||||
code = process.exitValue();
|
||||
}
|
||||
|
||||
if (t.isAlive())
|
||||
t.interrupt();
|
||||
|
||||
PDFService.LOGGER.debug("PDF maker: " + builder);
|
||||
|
||||
if (code != 0) {
|
||||
throw new IOException("Error code: " + code);
|
||||
} else {
|
||||
File file = new File("/tmp/" + uuid + ".pdf");
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
byte[] buff = fis.readAllBytes();
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.delete();
|
||||
return buff;
|
||||
} catch (IOException e) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.RegisterRepository;
|
||||
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.Builder;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
public class ResultService {
|
||||
|
||||
@Inject
|
||||
CompetitionRepository compRepository;
|
||||
|
||||
@Inject
|
||||
RegisterRepository registerRepository;
|
||||
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
CategoryRepository categoryRepository;
|
||||
|
||||
@Inject
|
||||
MatchRepository matchRepository;
|
||||
|
||||
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("lang.String");
|
||||
|
||||
public Uni<List<Object[]>> getList(SecurityCtx securityCtx) {
|
||||
return membreService.getByAccountId(securityCtx.getSubject())
|
||||
.chain(m -> registerRepository.list("membre = ?1", m))
|
||||
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(r -> Mutiny.fetch(r.getCompetition()))
|
||||
.onItem().transform(r -> new Object[]{r.getCompetition().getUuid(), r.getCompetition().getName(),
|
||||
r.getCompetition().getDate()})
|
||||
.collect().asList();
|
||||
}
|
||||
|
||||
public Uni<List<ResultCategoryData>> getCategory(String uuid, SecurityCtx securityCtx) {
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.chain(m -> categoryRepository.list("compet.uuid = ?1", uuid)
|
||||
.chain(cats -> matchRepository.list("(c1_id = ?1 OR c2_id = ?1 OR True) AND category IN ?2", //TODO rm OR True
|
||||
m.getMembre(), cats)))
|
||||
.map(matchModels -> {
|
||||
HashMap<Long, List<MatchModel>> map = new HashMap<>();
|
||||
for (MatchModel matchModel : matchModels) {
|
||||
if (!map.containsKey(matchModel.getCategory().getId()))
|
||||
map.put(matchModel.getCategory().getId(), new ArrayList<>());
|
||||
map.get(matchModel.getCategory().getId()).add(matchModel);
|
||||
}
|
||||
|
||||
return map.values();
|
||||
})
|
||||
.onItem()
|
||||
.transformToMulti(Multi.createFrom()::iterable)
|
||||
.onItem().call(list -> Mutiny.fetch(list.get(0).getCategory().getTree()))
|
||||
.onItem().transform(this::getData)
|
||||
.collect().asList();
|
||||
|
||||
}
|
||||
|
||||
private ResultCategoryData getData(List<MatchModel> matchModels) {
|
||||
ResultCategoryData out = new ResultCategoryData();
|
||||
|
||||
CategoryModel categoryModel = matchModels.get(0).getCategory();
|
||||
out.setName(categoryModel.getName());
|
||||
out.setType(categoryModel.getType());
|
||||
|
||||
getArray2(matchModels, out);
|
||||
getTree(categoryModel.getTree(), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private void getArray2(List<MatchModel> matchModels_, ResultCategoryData out) {
|
||||
List<MatchModel> matchModels = matchModels_.stream().filter(o -> o.getCategory_ord() >= 0).toList();
|
||||
|
||||
HashMap<Character, List<MatchModel>> matchMap = new HashMap<>();
|
||||
for (MatchModel model : matchModels) {
|
||||
char g = model.getPoule();
|
||||
if (!matchMap.containsKey(g))
|
||||
matchMap.put(g, new ArrayList<>());
|
||||
matchMap.get(g).add(model);
|
||||
}
|
||||
|
||||
matchMap.forEach((c, matchEntities) -> {
|
||||
List<ResultCategoryData.PouleArrayData> matchs = matchEntities.stream()
|
||||
.sorted(Comparator.comparing(MatchModel::getCategory_ord))
|
||||
.map(ResultCategoryData.PouleArrayData::fromModel)
|
||||
.toList();
|
||||
|
||||
List<ResultCategoryData.RankArray> rankArray = matchEntities.stream()
|
||||
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
|
||||
.distinct()
|
||||
.map(combName -> {
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger(0);
|
||||
AtomicInteger pointTake = new AtomicInteger(0);
|
||||
|
||||
matchEntities.stream()
|
||||
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName) || m.getC2Name()
|
||||
.equals(combName)))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((matchModel.getC1Name()
|
||||
.equals(combName) && win > 0) || matchModel.getC2Name()
|
||||
.equals(combName) && win < 0)
|
||||
w.getAndIncrement();
|
||||
|
||||
for (ScoreEmbeddable score : matchModel.getScores()) {
|
||||
if (score.getS1() <= -900 || score.getS2() <= -900)
|
||||
continue;
|
||||
if (matchModel.getC1Name().equals(combName)) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
}
|
||||
});
|
||||
float pointRate = (pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get();
|
||||
|
||||
return new ResultCategoryData.RankArray(0, combName, w.get(),
|
||||
pointMake.get(), pointTake.get(), pointRate);
|
||||
})
|
||||
.sorted(Comparator
|
||||
.comparing(ResultCategoryData.RankArray::getWin)
|
||||
.thenComparing(ResultCategoryData.RankArray::getPointRate).reversed())
|
||||
.toList();
|
||||
out.getMatchs().put(c, matchs);
|
||||
|
||||
int lastWin = -1;
|
||||
float pointRate = 0;
|
||||
int rank = 0;
|
||||
for (ResultCategoryData.RankArray rankArray1 : rankArray) {
|
||||
if (rankArray1.getWin() != lastWin || pointRate != rankArray1.getPointRate()) {
|
||||
lastWin = rankArray1.getWin();
|
||||
pointRate = rankArray1.getPointRate();
|
||||
rank++;
|
||||
}
|
||||
rankArray1.setRank(rank);
|
||||
}
|
||||
out.getRankArray().put(c, rankArray);
|
||||
});
|
||||
}
|
||||
|
||||
private static void convertTree(TreeModel src, TreeNode<ResultCategoryData.TreeData> dst) {
|
||||
dst.setData(ResultCategoryData.TreeData.from(src.getMatch()));
|
||||
if (src.getLeft() != null) {
|
||||
dst.setLeft(new TreeNode<>());
|
||||
convertTree(src.getLeft(), dst.getLeft());
|
||||
}
|
||||
if (src.getRight() != null) {
|
||||
dst.setRight(new TreeNode<>());
|
||||
convertTree(src.getRight(), dst.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
private void getTree(List<TreeModel> treeModels, ResultCategoryData out) {
|
||||
ArrayList<TreeNode<ResultCategoryData.TreeData>> trees = new ArrayList<>();
|
||||
treeModels.stream().filter(t -> t.getLevel() != 0).forEach(treeModel -> {
|
||||
TreeNode<ResultCategoryData.TreeData> root = new TreeNode<>();
|
||||
convertTree(treeModel, root);
|
||||
trees.add(root);
|
||||
});
|
||||
out.setTrees(trees);
|
||||
}
|
||||
|
||||
public Uni<CombsArrayData> getAllCombArray(String uuid, SecurityCtx securityCtx) {
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.chain(cm_register -> registerRepository.list("competition.uuid = ?1", uuid)
|
||||
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
|
||||
.map(matchModels -> new Pair<>(registers, matchModels)))
|
||||
.map(pair -> {
|
||||
List<RegisterModel> registers = pair.getKey();
|
||||
List<MatchModel> matchModels = pair.getValue();
|
||||
|
||||
CombsArrayData.CombsArrayDataBuilder builder = CombsArrayData.builder();
|
||||
|
||||
List<CombsArrayData.CombsData> combs = matchModels.stream()
|
||||
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.map(combName -> {
|
||||
var builder2 = CombsArrayData.CombsData.builder();
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger l = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger();
|
||||
AtomicInteger pointTake = new AtomicInteger();
|
||||
|
||||
matchModels.stream()
|
||||
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName)
|
||||
|| m.getC2Name().equals(combName)))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((combName.equals(matchModel.getC1Name()) && win > 0) ||
|
||||
combName.equals(matchModel.getC2Name()) && win < 0) {
|
||||
w.getAndIncrement();
|
||||
} else {
|
||||
l.getAndIncrement();
|
||||
}
|
||||
|
||||
matchModel.getScores().stream()
|
||||
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
|
||||
.forEach(score -> {
|
||||
if (combName.equals(matchModel.getC1Name())) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Categorie categorie = null;
|
||||
ClubModel club = null;
|
||||
|
||||
Optional<RegisterModel> register = registers.stream()
|
||||
.filter(r -> r.getName().equals(combName)).findFirst();
|
||||
if (register.isPresent()) {
|
||||
categorie = register.get().getCategorie();
|
||||
club = register.get().getClub2();
|
||||
}
|
||||
|
||||
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
|
||||
builder2.name(combName);
|
||||
builder2.w(w.get());
|
||||
builder2.l(l.get());
|
||||
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
|
||||
builder2.club((club == null) ? BUNDLE.getString("no.licence") : club.getName());
|
||||
builder2.pointMake(pointMake.get());
|
||||
builder2.pointTake(pointTake.get());
|
||||
builder2.ratioPoint(
|
||||
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
|
||||
|
||||
return builder2.build();
|
||||
})
|
||||
.sorted(Comparator.comparing(CombsArrayData.CombsData::name))
|
||||
.toList();
|
||||
|
||||
builder.nb_insc(combs.size());
|
||||
builder.tt_match((int) matchModels.stream().filter(MatchModel::isEnd).count());
|
||||
builder.point(combs.stream().mapToInt(CombsArrayData.CombsData::pointMake).sum());
|
||||
builder.combs(combs);
|
||||
|
||||
return builder.build();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombsArrayData(int nb_insc, int tt_match, long point, List<CombsData> combs) {
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombsData(String cat, String club, String name, int w, int l, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake) {
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<ClubArrayData> getClubArray(String uuid, SecurityCtx securityCtx) {
|
||||
ClubArrayData.ClubArrayDataBuilder builder = ClubArrayData.builder();
|
||||
|
||||
return hasAccess(uuid, securityCtx)
|
||||
.invoke(cm_register -> builder.name(cm_register.getClub2().getName()))
|
||||
.chain(cm_register -> registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid,
|
||||
cm_register.getClub2())
|
||||
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
|
||||
.map(matchModels -> new Pair<>(registers, matchModels)))
|
||||
.map(pair -> {
|
||||
List<RegisterModel> registers = pair.getKey();
|
||||
List<MatchModel> matchModels = pair.getValue();
|
||||
|
||||
builder.nb_insc(registers.size());
|
||||
|
||||
AtomicInteger tt_win = new AtomicInteger(0);
|
||||
AtomicInteger tt_match = new AtomicInteger(0);
|
||||
|
||||
List<ClubArrayData.CombData> combData = registers.stream()
|
||||
.map(register -> {
|
||||
|
||||
var builder2 = ClubArrayData.CombData.builder();
|
||||
AtomicInteger w = new AtomicInteger(0);
|
||||
AtomicInteger l = new AtomicInteger(0);
|
||||
AtomicInteger pointMake = new AtomicInteger();
|
||||
AtomicInteger pointTake = new AtomicInteger();
|
||||
|
||||
matchModels.stream()
|
||||
.filter(m -> m.isEnd() && (register.getMembre().equals(m.getC1_id())
|
||||
|| register.getMembre().equals(m.getC2_id())))
|
||||
.forEach(matchModel -> {
|
||||
int win = matchModel.win();
|
||||
if ((register.getMembre()
|
||||
.equals(matchModel.getC1_id()) && win > 0) ||
|
||||
register.getMembre()
|
||||
.equals(matchModel.getC2_id()) && win < 0) {
|
||||
w.getAndIncrement();
|
||||
} else {
|
||||
l.getAndIncrement();
|
||||
}
|
||||
|
||||
matchModel.getScores().stream()
|
||||
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
|
||||
.forEach(score -> {
|
||||
if (register.getMembre()
|
||||
.equals(matchModel.getC1_id())) {
|
||||
pointMake.addAndGet(score.getS1());
|
||||
pointTake.addAndGet(score.getS2());
|
||||
} else {
|
||||
pointMake.addAndGet(score.getS2());
|
||||
pointTake.addAndGet(score.getS1());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Categorie categorie = register.getCategorie();
|
||||
if (categorie == null)
|
||||
categorie = register.getMembre().getCategorie();
|
||||
|
||||
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
|
||||
builder2.name(register.getName());
|
||||
builder2.w(w.get());
|
||||
builder2.l(l.get());
|
||||
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
|
||||
builder2.pointMake(pointMake.get());
|
||||
builder2.pointTake(pointTake.get());
|
||||
builder2.ratioPoint(
|
||||
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
|
||||
|
||||
tt_win.addAndGet(w.get());
|
||||
tt_match.addAndGet(w.get() + l.get());
|
||||
|
||||
return builder2.build();
|
||||
})
|
||||
.sorted(Comparator.comparing(ClubArrayData.CombData::name))
|
||||
.toList();
|
||||
|
||||
builder.nb_match(tt_match.get());
|
||||
builder.match_w(tt_win.get());
|
||||
builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0)
|
||||
.mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L));
|
||||
builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum());
|
||||
builder.pointTake(combData.stream().mapToInt(ClubArrayData.CombData::pointTake).sum());
|
||||
builder.ratioPoint((float) combData.stream().filter(c -> c.l + c.w != 0)
|
||||
.mapToDouble(ClubArrayData.CombData::ratioPoint).average().orElse(0L));
|
||||
builder.combs(combData);
|
||||
|
||||
return builder.build();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record ClubArrayData(String name, int nb_insc, int nb_match, int match_w, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake, List<CombData> combs) {
|
||||
@Builder
|
||||
@RegisterForReflection
|
||||
public static record CombData(String cat, String name, int w, int l, float ratioVictoire,
|
||||
float ratioPoint, int pointMake, int pointTake) {
|
||||
}
|
||||
}
|
||||
|
||||
private Uni<RegisterModel> hasAccess(String uuid, SecurityCtx securityCtx) {
|
||||
return registerRepository.find("membre.userId = ?1 AND competition.uuid = ?2", securityCtx.getSubject(), uuid)
|
||||
.firstResult()
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DForbiddenException("Access denied");
|
||||
}));
|
||||
}
|
||||
|
||||
private Uni<RegisterModel> hasAccess(Long compId, SecurityCtx securityCtx) {
|
||||
return registerRepository.find("membre.userId = ?1 AND competition.id = ?2", securityCtx.getSubject(), compId)
|
||||
.firstResult()
|
||||
.invoke(Unchecked.consumer(o -> {
|
||||
if (o == null)
|
||||
throw new DForbiddenException("Access denied");
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
public class TreeService {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.client.dto.HelloassoNotification;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
@ApplicationScoped
|
||||
public class WebhookService {
|
||||
|
||||
@Inject
|
||||
CheckoutService checkoutService;
|
||||
|
||||
@Inject
|
||||
CompetitionService competitionService;
|
||||
|
||||
@ConfigProperty(name = "helloasso.organizationSlug")
|
||||
String organizationSlug;
|
||||
|
||||
public Uni<Response> helloAssoNotification(HelloassoNotification notification) {
|
||||
if (notification.getEventType().equals("Payment")) {
|
||||
if (notification.getData().getOrder().getFormType().equals("Checkout")) {
|
||||
if (notification.getData().getOrder().getOrganizationSlug().equalsIgnoreCase(organizationSlug)) {
|
||||
return checkoutService.paymentStatusChange(notification.getData().getState(),
|
||||
notification.getMetadata());
|
||||
}
|
||||
} else if (notification.getData().getOrder().getFormType().equals("Event")) {
|
||||
return competitionService.unregisterHelloAsso(notification.getData());
|
||||
}
|
||||
}else if (notification.getEventType().equals("Order")){
|
||||
if (notification.getData().getFormType().equals("Event")) {
|
||||
return competitionService.registerHelloAsso(notification.getData());
|
||||
}
|
||||
}
|
||||
|
||||
return Uni.createFrom().item(Response.ok().build());
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class SReqCompet {
|
||||
}
|
||||
|
||||
public static void getAllHaveAccess(ArrayList<Client_Thread> client_Thread, String userId,
|
||||
CompletableFuture<HashMap<Long, String>> future) {
|
||||
CompletableFuture<HashMap<String, String>> future) {
|
||||
if (client_Thread.isEmpty()) return;
|
||||
client_Thread.get(0).sendReq(userId, "getAllHaveAccess",
|
||||
new JsonConsumer<>(HashMap.class, future::complete));
|
||||
|
||||
@@ -92,7 +92,7 @@ public class AffiliationRequestEndpoints {
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
@RolesAllowed({"federation_admin"})
|
||||
@RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"})
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Supprime une demande d'affiliation", description = "Cette méthode supprime une demande " +
|
||||
"d'affiliation pour l'identifiant spécifié.")
|
||||
@@ -107,7 +107,7 @@ public class AffiliationRequestEndpoints {
|
||||
if (o.getClub() == null && !securityCtx.roleHas("federation_admin"))
|
||||
throw new DForbiddenException();
|
||||
})).invoke(o -> checkPerm.accept(o.getClub()))
|
||||
.chain(o -> service.deleteReqAffiliation(id, reason));
|
||||
.chain(o -> service.deleteReqAffiliation(id, reason, securityCtx.roleHas("federation_admin")));
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -186,6 +186,6 @@ public class AffiliationRequestEndpoints {
|
||||
public Uni<Response> getStatus(
|
||||
@Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException {
|
||||
return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id,
|
||||
Uni.createFrom().nullItem());
|
||||
Uni.createFrom().nullItem(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.client.SirenService;
|
||||
import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
|
||||
import fr.titionfire.ffsaf.rest.client.StateIdService;
|
||||
import fr.titionfire.ffsaf.rest.data.AssoData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.*;
|
||||
@@ -12,18 +13,24 @@ import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
@Path("api/asso")
|
||||
public class AssoEndpoints {
|
||||
|
||||
@RestClient
|
||||
StateIdService stateIdService;
|
||||
|
||||
@RestClient
|
||||
SirenService sirenService;
|
||||
|
||||
@GET
|
||||
@Path("siren/{siren}")
|
||||
@Path("state_id/{stateId}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(hidden = true)
|
||||
public Uni<UniteLegaleRoot> getInfoSiren(@PathParam("siren") String siren) {
|
||||
return sirenService.get_unite(siren).onFailure().transform(throwable -> {
|
||||
public Uni<AssoData> getAssoInfo(@PathParam("stateId") String stateId) {
|
||||
return ((stateId.charAt(0) == 'W') ? stateIdService.get_rna(stateId) : sirenService.get_unite(
|
||||
stateId).chain(stateIdService::getAssoDataFromUnit)).onFailure().transform(throwable -> {
|
||||
if (throwable instanceof WebApplicationException exception) {
|
||||
if (exception.getResponse().getStatus() == 404)
|
||||
return new DNotFoundException("Service momentanément indisponible");
|
||||
if (exception.getResponse().getStatus() == 400)
|
||||
return new DNotFoundException("Siret introuvable");
|
||||
return new DNotFoundException("Asso introuvable");
|
||||
}
|
||||
return throwable;
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.PouleService;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleData;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
||||
import fr.titionfire.ffsaf.domain.service.CategoryService;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryData;
|
||||
import fr.titionfire.ffsaf.rest.data.CategoryFullData;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
@@ -14,14 +14,14 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
|
||||
@Authenticated
|
||||
@Path("api/poule/{system}/")
|
||||
public class PouleEndpoints {
|
||||
@Path("api/poule/{system}/admin/")
|
||||
public class CategoryAdminEndpoints {
|
||||
|
||||
@PathParam("system")
|
||||
private CompetitionSystem system;
|
||||
|
||||
@Inject
|
||||
PouleService service;
|
||||
CategoryService service;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
@@ -30,28 +30,28 @@ public class PouleEndpoints {
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<PouleData> getById(@PathParam("id") Long id) {
|
||||
return service.getById(securityCtx, system, id);
|
||||
public Uni<CategoryData> getByIdAdmin(@PathParam("id") Long id) {
|
||||
return service.getByIdAdmin(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<PouleData>> getAll() {
|
||||
return service.getAll(securityCtx, system);
|
||||
public Uni<List<CategoryData>> getAllAdmin() {
|
||||
return service.getAllAdmin(securityCtx, system);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<PouleData> addOrUpdate(PouleData data) {
|
||||
public Uni<CategoryData> addOrUpdate(CategoryData data) {
|
||||
return service.addOrUpdate(securityCtx, system, data);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("sync")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Uni<?> syncPoule(PouleFullData data) {
|
||||
return service.syncPoule(securityCtx, system, data);
|
||||
public Uni<?> syncCategory(CategoryFullData data) {
|
||||
return service.syncCategory(securityCtx, system, data);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
import fr.titionfire.ffsaf.domain.service.ClubService;
|
||||
import fr.titionfire.ffsaf.domain.service.PDFService;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.rest.data.*;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
@@ -28,6 +29,7 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -39,6 +41,9 @@ public class ClubEndpoints {
|
||||
@Inject
|
||||
ClubService clubService;
|
||||
|
||||
@Inject
|
||||
PDFService pdfService;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
@@ -65,7 +70,8 @@ public class ClubEndpoints {
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<List<SimpleClubModel>> getAll() {
|
||||
return clubService.getAll().map(clubModels -> clubModels.stream().map(SimpleClubModel::fromModel).toList());
|
||||
return clubService.getAll().map(clubModels -> clubModels.stream().map(SimpleClubModel::fromModel).sorted(
|
||||
Comparator.comparing(SimpleClubModel::getName)).toList());
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -219,7 +225,7 @@ public class ClubEndpoints {
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<Response> getAffiliation(@Parameter(description = "Identifiant de club") @PathParam("id") long id) {
|
||||
return clubService.getAffiliationPdf(id);
|
||||
return pdfService.getAffiliationPdf(id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -268,9 +274,26 @@ public class ClubEndpoints {
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<Response> getMeAffiliation() {
|
||||
return clubService.getAffiliationPdf(securityCtx.getSubject());
|
||||
return pdfService.getAffiliationPdf(securityCtx.getSubject());
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/members")
|
||||
@RolesAllowed({"club_president", "club_secretaire", "club_respo_intra", "club_tresorier"})
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Revoie tout les membres de votre club")
|
||||
@APIResponses(value = {
|
||||
@APIResponse(responseCode = "200", description = "List des membres"),
|
||||
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||
@APIResponse(responseCode = "404", description = "L'utilisateur n'est pas membre d'un club"),
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<List<VerySimpleMembre>> getMembers() {
|
||||
return clubService.getMembers(securityCtx);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/renew/{id}")
|
||||
@RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"})
|
||||
@@ -312,7 +335,7 @@ public class ClubEndpoints {
|
||||
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
|
||||
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
|
||||
try {
|
||||
return Utils.getMediaFile((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||
return Utils.getMediaFileNoDefault((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||
Uni.createFrom().nullItem());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InternalError();
|
||||
@@ -335,7 +358,7 @@ public class ClubEndpoints {
|
||||
return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
|
||||
try {
|
||||
return Utils.getMediaFile(clubModel.getId(), media, "clubStatus",
|
||||
"statue-" + clubModel.getName(), Uni.createFrom().nullItem());
|
||||
"statue-" + clubModel.getName(), Uni.createFrom().nullItem(), false);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InternalError();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.CompetitionService;
|
||||
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Path("api/competition/admin")
|
||||
public class CompetitionAdminEndpoints {
|
||||
|
||||
@Inject
|
||||
CompetitionService service;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<CompetitionData> getByIdAdmin(@PathParam("id") Long id) {
|
||||
return service.getByIdAdmin(securityCtx, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("all")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<CompetitionData>> getAllAdmin() {
|
||||
return service.getAllAdmin(securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("all/{system}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<CompetitionData>> getAllSystemAdmin(@PathParam("system") CompetitionSystem system) {
|
||||
return service.getAllSystemAdmin(securityCtx, system);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("all/{system}/table")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<CompetitionData>> getAllSystemTable(@PathParam("system") CompetitionSystem system) {
|
||||
return service.getAllSystemTable(securityCtx, system);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
||||
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
@@ -29,34 +28,39 @@ public class CompetitionEndpoints {
|
||||
@Path("{id}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<CompetitionData> getById(@PathParam("id") Long id) {
|
||||
public Uni<CompetitionData> getById(@PathParam("id") Long id, @QueryParam("light") boolean light) {
|
||||
if (light)
|
||||
return service.getById(securityCtx, id);
|
||||
else
|
||||
return service.getByIdAdmin(securityCtx, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/register")
|
||||
@Path("{id}/register/{source}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<SimpleRegisterComb>> getRegister(@PathParam("id") Long id) {
|
||||
return service.getRegister(securityCtx, id);
|
||||
public Uni<List<SimpleRegisterComb>> getRegister(@PathParam("id") Long id, @PathParam("source") String source) {
|
||||
return service.getRegister(securityCtx, id, source);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}/register")
|
||||
@Path("{id}/register/{source}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(hidden = true)
|
||||
public Uni<SimpleRegisterComb> addRegisterComb(@PathParam("id") Long id, RegisterRequestData data) {
|
||||
return service.addRegisterComb(securityCtx, id, data);
|
||||
public Uni<SimpleRegisterComb> addRegisterComb(@PathParam("id") Long id, @PathParam("source") String source,
|
||||
RegisterRequestData data) {
|
||||
return service.addRegisterComb(securityCtx, id, data, source);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}/register/{comb_id}")
|
||||
@Path("{id}/register/{comb_id}/{source}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(hidden = true)
|
||||
public Uni<Void> removeRegisterComb(@PathParam("id") Long id, @PathParam("comb_id") Long combId) {
|
||||
return service.removeRegisterComb(securityCtx, id, combId);
|
||||
public Uni<Void> removeRegisterComb(@PathParam("id") Long id, @PathParam("comb_id") Long combId,
|
||||
@PathParam("source") String source, @QueryParam("ban") boolean ban) {
|
||||
return service.removeRegisterComb(securityCtx, id, combId, source, ban);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -76,14 +80,6 @@ public class CompetitionEndpoints {
|
||||
return service.getAll(securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("all/{system}")
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<CompetitionData>> getAllSystem(@PathParam("system") CompetitionSystem system) {
|
||||
return service.getAllSystem(securityCtx, system);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Authenticated
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
||||
@@ -115,8 +115,8 @@ public class CompteEndpoints {
|
||||
else toRemove.add("safca_super_admin");
|
||||
if (form.isSafca_user()) toAdd.add("safca_user");
|
||||
else toRemove.add("safca_user");
|
||||
if (form.isSafca_create_compet()) toAdd.add("safca_create_compet");
|
||||
else toRemove.add("safca_create_compet");
|
||||
if (form.isCreate_compet()) toAdd.add("create_compet");
|
||||
else toRemove.add("create_compet");
|
||||
|
||||
return service.updateRole(id, toAdd, toRemove);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
|
||||
@@ -80,6 +81,21 @@ public class LicenceEndpoints {
|
||||
.map(licenceModels -> licenceModels.stream().map(SimpleLicence::fromModel).toList());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("pay")
|
||||
@RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"})
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Paiement des licence", description = "Retourne le lien de paiement pour les licence des membre fournie")
|
||||
@APIResponses(value = {
|
||||
@APIResponse(responseCode = "200", description = "Commande avec succès"),
|
||||
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<String> payLicences(@Parameter(description = "Id des membres") List<Long> ids) {
|
||||
return licenceService.payLicences(ids, checkPerm, securityCtx);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{id}")
|
||||
@RolesAllowed("federation_admin")
|
||||
@@ -97,6 +113,21 @@ public class LicenceEndpoints {
|
||||
return licenceService.setLicence(id, form).map(SimpleLicence::fromModel);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("validate")
|
||||
@RolesAllowed("federation_admin")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Validation licence", description = "Valide en masse les licence de l'année en cours (pour les administrateurs)")
|
||||
@APIResponses(value = {
|
||||
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
||||
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<?> valideLicences(@Parameter(description = "Id des membres a valider") List<Long> ids) {
|
||||
return licenceService.valideLicences(ids);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@RolesAllowed("federation_admin")
|
||||
|
||||
@@ -14,8 +14,8 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
|
||||
@Authenticated
|
||||
@Path("api/match/{system}/")
|
||||
public class MatchEndpoints {
|
||||
@Path("api/match/{system}/admin")
|
||||
public class MatchAdminEndpoints {
|
||||
|
||||
@PathParam("system")
|
||||
private CompetitionSystem system;
|
||||
@@ -30,15 +30,15 @@ public class MatchEndpoints {
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<MatchData> getById(@PathParam("id") Long id) {
|
||||
return service.getById(securityCtx, system, id);
|
||||
public Uni<MatchData> getByIdAdmin(@PathParam("id") Long id) {
|
||||
return service.getByIdAdmin(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("getAllByPoule/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<MatchData>> getAllByPoule(@PathParam("id") Long id) {
|
||||
return service.getAllByPoule(securityCtx, system, id);
|
||||
public Uni<List<MatchData>> getAllByPouleAdmin(@PathParam("id") Long id) {
|
||||
return service.getAllByPouleAdmin(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -57,12 +57,16 @@ public class MembreAdminEndpoints {
|
||||
@Parameter(description = "Nombre max de résulta (max 50)") @QueryParam("limit") Integer limit,
|
||||
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
|
||||
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
||||
@Parameter(description = "Club à filter") @QueryParam("club") String club) {
|
||||
@Parameter(description = "Club à filter") @QueryParam("club") String club,
|
||||
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
||||
@Parameter(description = "État de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
||||
@Parameter(description = "État du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
||||
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
||||
if (limit == null)
|
||||
limit = 50;
|
||||
if (page == null || page < 1)
|
||||
page = 1;
|
||||
return membreService.searchAdmin(limit, page - 1, search, club);
|
||||
return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order, categorie);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
||||
@@ -49,12 +49,16 @@ public class MembreClubEndpoints {
|
||||
public Uni<PageResult<SimpleMembre>> getFindClub(
|
||||
@Parameter(description = "Nombre max de résulta (max 50)") @QueryParam("limit") Integer limit,
|
||||
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
|
||||
@Parameter(description = "Text à rechercher") @QueryParam("search") String search) {
|
||||
@Parameter(description = "Text à rechercher") @QueryParam("search") String search,
|
||||
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
|
||||
@Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
|
||||
@Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
|
||||
@Parameter(description = "Ordre") @QueryParam("order") String order) {
|
||||
if (limit == null)
|
||||
limit = 50;
|
||||
if (page == null || page < 1)
|
||||
page = 1;
|
||||
return membreService.search(limit, page - 1, search, securityCtx.getSubject());
|
||||
return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, securityCtx.getSubject());
|
||||
}
|
||||
|
||||
@GET
|
||||
|
||||
@@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.domain.service.MembreService;
|
||||
import fr.titionfire.ffsaf.domain.service.PDFService;
|
||||
import fr.titionfire.ffsaf.rest.data.MeData;
|
||||
import fr.titionfire.ffsaf.rest.data.SimpleMembre;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
@@ -34,6 +35,9 @@ public class MembreEndpoints {
|
||||
@Inject
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
PDFService pdfService;
|
||||
|
||||
@ConfigProperty(name = "upload_dir")
|
||||
String media;
|
||||
|
||||
@@ -106,7 +110,7 @@ public class MembreEndpoints {
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<Response> getMeLicence() {
|
||||
return membreService.getLicencePdf(securityCtx.getSubject());
|
||||
return pdfService.getLicencePdf(securityCtx.getSubject());
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -151,6 +155,6 @@ public class MembreEndpoints {
|
||||
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
|
||||
})
|
||||
public Uni<Response> getLicencePDF(@PathParam("id") long id) {
|
||||
return membreService.getLicencePdf(membreService.getByIdWithLicence(id).onItem().invoke(checkPerm));
|
||||
return pdfService.getLicencePdf(membreService.getByIdWithLicence(id).onItem().invoke(checkPerm));
|
||||
}
|
||||
}
|
||||
|
||||
48
src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java
Normal file
48
src/main/java/fr/titionfire/ffsaf/rest/ResultEndpoints.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.ResultService;
|
||||
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Authenticated
|
||||
@Path("api/result")
|
||||
public class ResultEndpoints {
|
||||
|
||||
@Inject
|
||||
ResultService resultService;
|
||||
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
@GET
|
||||
@Path("list")
|
||||
public Uni<List<Object[]>> getList() {
|
||||
return resultService.getList(securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}")
|
||||
public Uni<List<ResultCategoryData>> getCategory(@PathParam("uuid") String uuid) {
|
||||
return resultService.getCategory(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/club")
|
||||
public Uni<ResultService.ClubArrayData> getClub(@PathParam("uuid") String uuid) {
|
||||
return resultService.getClubArray(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/comb")
|
||||
public Uni<ResultService.CombsArrayData> getComb(@PathParam("uuid") String uuid) {
|
||||
return resultService.getAllCombArray(uuid, securityCtx);
|
||||
}
|
||||
}
|
||||
53
src/main/java/fr/titionfire/ffsaf/rest/WebhookEndpoints.java
Normal file
53
src/main/java/fr/titionfire/ffsaf/rest/WebhookEndpoints.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.WebhookService;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.HelloassoNotification;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
@Path("api/webhook")
|
||||
public class WebhookEndpoints {
|
||||
private static final Logger LOGGER = Logger.getLogger(WebhookEndpoints.class);
|
||||
|
||||
@Inject
|
||||
WebhookService webhookService;
|
||||
|
||||
@Inject
|
||||
RoutingContext context;
|
||||
|
||||
@ConfigProperty(name = "helloasso.webhook.ip-source")
|
||||
String helloassoIp;
|
||||
|
||||
@ConfigProperty(name = "quarkus.http.proxy.proxy-address-forwarding")
|
||||
boolean proxyForwarding;
|
||||
|
||||
@POST
|
||||
@Path("ha")
|
||||
@Operation(hidden = true)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Uni<Response> helloAsso(HelloassoNotification notification) {
|
||||
String ip;
|
||||
if (proxyForwarding) {
|
||||
ip = context.request().getHeader("X-Forwarded-For");
|
||||
if (ip == null)
|
||||
ip = context.request().authority().host();
|
||||
} else {
|
||||
ip = context.request().authority().host();
|
||||
}
|
||||
|
||||
if (!helloassoIp.equals(ip)) {
|
||||
LOGGER.infof("helloAsso webhook reject : bas ip (%s)", ip);
|
||||
return Uni.createFrom().item(Response.status(Response.Status.FORBIDDEN).build());
|
||||
}
|
||||
return webhookService.helloAssoNotification(notification);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package fr.titionfire.ffsaf.rest.client;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.client.dto.TokenResponse;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@Path("/")
|
||||
@RegisterRestClient(configKey = "helloasso-auth")
|
||||
public interface HelloAssoAuthClient {
|
||||
|
||||
@POST
|
||||
@Path("/token")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Uni<TokenResponse> getToken(
|
||||
@FormParam("grant_type") String grantType,
|
||||
@FormParam("client_id") String clientId,
|
||||
@FormParam("client_secret") String clientSecret
|
||||
);
|
||||
|
||||
@POST
|
||||
@Path("/token")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Uni<TokenResponse> refreshToken(
|
||||
@FormParam("grant_type") String grantType,
|
||||
@FormParam("client_id") String clientId,
|
||||
@FormParam("refresh_token") String refreshToken
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package fr.titionfire.ffsaf.rest.client;
|
||||
|
||||
import fr.titionfire.ffsaf.domain.service.HelloAssoTokenService;
|
||||
import io.quarkus.rest.client.reactive.ReactiveClientHeadersFactory;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import org.jboss.resteasy.reactive.common.util.MultivaluedTreeMap;
|
||||
|
||||
@ApplicationScoped
|
||||
public class HelloAssoHeadersFactory extends ReactiveClientHeadersFactory {
|
||||
|
||||
@Inject
|
||||
HelloAssoTokenService helloAssoTokenService;
|
||||
|
||||
@Override
|
||||
public Uni<MultivaluedMap<String, String>> getHeaders(MultivaluedMap<String, String> incomingHeaders,
|
||||
MultivaluedMap<String, String> clientOutgoingHeaders) {
|
||||
MultivaluedMap<String, String> map = new MultivaluedTreeMap<>();
|
||||
return helloAssoTokenService.getValidAccessToken()
|
||||
.invoke(token -> map.putSingle("Authorization", "Bearer " + token)).map(__ -> map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package fr.titionfire.ffsaf.rest.client;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsRequest;
|
||||
import fr.titionfire.ffsaf.rest.client.dto.CheckoutIntentsResponse;
|
||||
import io.quarkus.rest.client.reactive.ClientExceptionMapper;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Path("/")
|
||||
@RegisterRestClient(configKey = "helloasso-api")
|
||||
@RegisterClientHeaders(HelloAssoHeadersFactory.class)
|
||||
public interface HelloAssoService {
|
||||
|
||||
@GET
|
||||
@Path("/users/me/organizations")
|
||||
@Produces("text/plain")
|
||||
Uni<String> test();
|
||||
|
||||
@POST
|
||||
@Path("organizations/{organizationSlug}/checkout-intents")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Uni<CheckoutIntentsResponse> checkout(@PathParam("organizationSlug") String organizationSlug,
|
||||
CheckoutIntentsRequest data);
|
||||
|
||||
@ClientExceptionMapper
|
||||
static RuntimeException toException(Response response, Method method) {
|
||||
if (!method.getDeclaringClass().getName().equals("fr.titionfire.ffsaf.rest.client.HelloAssoService"))
|
||||
return null;
|
||||
|
||||
if (method.getName().equals("checkout")) {
|
||||
if (response.getStatus() == 400) {
|
||||
if (response.getEntity() instanceof ByteArrayInputStream) {
|
||||
ByteArrayInputStream error = response.readEntity(ByteArrayInputStream.class);
|
||||
return new RuntimeException(new String(error.readAllBytes(), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
return new RuntimeException("The remote service responded with HTTP 400");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package fr.titionfire.ffsaf.rest.client;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
|
||||
import io.quarkus.cache.CacheResult;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
@@ -15,5 +16,6 @@ public interface SirenService {
|
||||
|
||||
@GET
|
||||
@Path("/v3/unites_legales/{SIREN}")
|
||||
@CacheResult(cacheName = "AssoData_siren")
|
||||
Uni<UniteLegaleRoot> get_unite(@PathParam("SIREN") String siren);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package fr.titionfire.ffsaf.rest.client;
|
||||
|
||||
import fr.titionfire.ffsaf.rest.data.AssoData;
|
||||
import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
|
||||
import io.quarkus.cache.CacheResult;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@Path("/")
|
||||
@RegisterRestClient
|
||||
public interface StateIdService {
|
||||
|
||||
@GET
|
||||
@Path("/associations/{rna}")
|
||||
@CacheResult(cacheName = "AssoData_rna")
|
||||
Uni<AssoData> get_rna(@PathParam("rna") String rna);
|
||||
|
||||
default Uni<AssoData> getAssoDataFromUnit(UniteLegaleRoot u) {
|
||||
AssoData assoData = new AssoData();
|
||||
assoData.setSiren(u.getUnite_legale().getSiren());
|
||||
assoData.setRna(u.getUnite_legale().getIdentifiant_association());
|
||||
|
||||
AssoData.Identite identite = new AssoData.Identite();
|
||||
identite.setNom(u.getUnite_legale().getDenomination());
|
||||
identite.setSiret_siege(u.getUnite_legale().getEtablissement_siege().getSiret());
|
||||
assoData.setIdentite(identite);
|
||||
|
||||
AssoData.Address address = new AssoData.Address();
|
||||
StringBuilder voie = new StringBuilder();
|
||||
if (u.getUnite_legale().getEtablissement_siege().getNumero_voie() != null)
|
||||
voie.append(u.getUnite_legale().getEtablissement_siege().getNumero_voie()).append(' ');
|
||||
if (u.getUnite_legale().getEtablissement_siege().getType_voie() != null)
|
||||
voie.append(u.getUnite_legale().getEtablissement_siege().getType_voie()).append(' ');
|
||||
if (u.getUnite_legale().getEtablissement_siege().getLibelle_voie() != null)
|
||||
voie.append(u.getUnite_legale().getEtablissement_siege().getLibelle_voie()).append(' ');
|
||||
address.setVoie(voie.toString().trim());
|
||||
address.setComplement(u.getUnite_legale().getEtablissement_siege().getComplement_adresse());
|
||||
address.setCode_postal(u.getUnite_legale().getEtablissement_siege().getCode_postal());
|
||||
address.setCommune(
|
||||
new AssoData.Commune(u.getUnite_legale().getEtablissement_siege().getLibelle_commune()));
|
||||
assoData.setCoordonnees(new AssoData.Coordonnee(address));
|
||||
|
||||
return Uni.createFrom().item(assoData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
@RegisterForReflection
|
||||
public class ApiError {
|
||||
public String error;
|
||||
public String error_description;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return error + ": " + error_description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CheckoutIntentsRequest {
|
||||
public int totalAmount;
|
||||
public int initialAmount;
|
||||
public String itemName;
|
||||
public String backUrl;
|
||||
public String errorUrl;
|
||||
public String returnUrl;
|
||||
public boolean containsDonation;
|
||||
public Payer payer;
|
||||
public CheckoutMetadata metadata;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class Payer {
|
||||
public String firstName;
|
||||
public String lastName;
|
||||
public String email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public class CheckoutIntentsResponse {
|
||||
public int id;
|
||||
public String redirectUrl;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class CheckoutMetadata {
|
||||
public long checkoutDBId;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class HelloassoNotification {
|
||||
private NotificationData data;
|
||||
private String eventType;
|
||||
private CheckoutMetadata metadata;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class NotificationData {
|
||||
private Order order;
|
||||
private Integer id;
|
||||
private String formSlug;
|
||||
private String formType;
|
||||
private String organizationSlug;
|
||||
private String checkoutIntentId;
|
||||
private String oldSlugOrganization; // Pour les changements de nom d'association
|
||||
private String newSlugOrganization;
|
||||
private String state; // Pour les formulaires
|
||||
private List<Item> items;
|
||||
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class Order {
|
||||
private Integer id;
|
||||
private String organizationSlug;
|
||||
private String formSlug;
|
||||
private String formType;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class Item {
|
||||
private String name;
|
||||
private User user;
|
||||
private List<CustomField> customFields;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class User {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class CustomField {
|
||||
private String name;
|
||||
private String answer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fr.titionfire.ffsaf.rest.client.dto;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
|
||||
@RegisterForReflection
|
||||
public class TokenResponse {
|
||||
@JsonProperty("access_token")
|
||||
public String accessToken;
|
||||
|
||||
@JsonProperty("refresh_token")
|
||||
public String refreshToken;
|
||||
|
||||
@JsonProperty("token_type")
|
||||
public String tokenType; // Toujours "bearer"
|
||||
|
||||
@JsonProperty("expires_in")
|
||||
public long expiresIn; // Durée de validité en secondes (1800s = 30min)
|
||||
|
||||
// Pour stocker l'heure d'obtention du token
|
||||
private long timestamp;
|
||||
|
||||
public TokenResponse() {
|
||||
this.timestamp = System.currentTimeMillis() / 1000; // Timestamp en secondes
|
||||
}
|
||||
|
||||
// Vérifie si le token est expiré
|
||||
public boolean isExpired() {
|
||||
return (System.currentTimeMillis() / 1000) - timestamp >= expiresIn;
|
||||
}
|
||||
}
|
||||
48
src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java
Normal file
48
src/main/java/fr/titionfire/ffsaf/rest/data/AssoData.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public class AssoData {
|
||||
String siren;
|
||||
String rna;
|
||||
Identite identite;
|
||||
Coordonnee coordonnees;
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public static class Identite {
|
||||
String nom;
|
||||
String siret_siege;
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Coordonnee {
|
||||
Address adresse_gestion;
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public static class Address {
|
||||
String voie;
|
||||
String complement;
|
||||
String code_postal;
|
||||
String pays;
|
||||
Commune commune;
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Commune {
|
||||
String nom;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -8,16 +8,16 @@ import lombok.Data;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class PouleData {
|
||||
public class CategoryData {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long compet;
|
||||
private Integer type;
|
||||
|
||||
public static PouleData fromModel(PouleModel model) {
|
||||
public static CategoryData fromModel(CategoryModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new PouleData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType());
|
||||
return new CategoryData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType());
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class PouleFullData {
|
||||
public class CategoryFullData {
|
||||
private Long id;
|
||||
private String name;
|
||||
private Long compet;
|
||||
@@ -1,15 +1,18 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@@ -17,26 +20,64 @@ import java.util.List;
|
||||
public class CompetitionData {
|
||||
private Long id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String adresse;
|
||||
private String uuid;
|
||||
private Date date;
|
||||
private Date toDate;
|
||||
private CompetitionSystem system;
|
||||
private RegisterMode registerMode;
|
||||
private Date startRegister;
|
||||
private Date endRegister;
|
||||
private boolean publicVisible;
|
||||
private Long club;
|
||||
private String clubName;
|
||||
private String owner;
|
||||
private List<SimpleRegister> registers;
|
||||
private boolean canEdit;
|
||||
private String data1;
|
||||
private String data2;
|
||||
private String data3;
|
||||
private String data4;
|
||||
|
||||
public static CompetitionData fromModel(CompetitionModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new CompetitionData(model.getId(), model.getName(), model.getUuid(), model.getDate(), model.getSystem(),
|
||||
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null);
|
||||
return new CompetitionData(model.getId(), model.getName(), model.getDescription(), model.getAdresse(),
|
||||
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false,
|
||||
model.getData1(), model.getData2(), model.getData3(), model.getData4());
|
||||
}
|
||||
|
||||
public CompetitionData addInsc(List<RegisterModel> insc) {
|
||||
this.registers = insc.stream()
|
||||
public static CompetitionData fromModelLight(CompetitionModel model) {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
CompetitionData out = new CompetitionData(model.getId(), model.getName(), model.getDescription(),
|
||||
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||
null, model.getClub().getName(), "", null, false,
|
||||
"", "", "", "");
|
||||
|
||||
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
||||
out.setData1(model.getData1());
|
||||
out.setData2(model.getData2());
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public CompetitionData addInsc(List<RegisterModel> insc, List<CompetitionGuestModel> guests) {
|
||||
this.registers = Stream.concat(
|
||||
insc.stream()
|
||||
.map(i -> new SimpleRegister(i.getMembre().getId(), i.getOverCategory(), i.getWeight(),
|
||||
i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId())).toList();
|
||||
i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId(),
|
||||
(i.getClub() == null) ? null : i.getClub().getName())),
|
||||
guests.stream()
|
||||
.map(i -> new SimpleRegister(i.getId() * -1, 0, i.getWeight(),
|
||||
i.getCategorie(), null, i.getClub()))).toList();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -49,5 +90,6 @@ public class CompetitionData {
|
||||
Integer weight;
|
||||
Categorie categorie;
|
||||
Long club;
|
||||
String club_str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ public class MatchData {
|
||||
private String c1_str;
|
||||
private Long c2_id;
|
||||
private String c2_str;
|
||||
private Long poule;
|
||||
private long poule_ord;
|
||||
private Long category;
|
||||
private long category_ord;
|
||||
private boolean isEnd = true;
|
||||
private char groupe;
|
||||
private char poule;
|
||||
private List<ScoreEmbeddable> scores;
|
||||
|
||||
public static MatchData fromModel(MatchModel model) {
|
||||
@@ -28,9 +28,11 @@ public class MatchData {
|
||||
return null;
|
||||
|
||||
return new MatchData(model.getSystemId(),
|
||||
(model.getC1_id() == null) ? null : model.getC1_id().getId(), model.getC1_str(),
|
||||
(model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getC2_str(),
|
||||
model.getPoule().getId(), model.getPoule_ord(), model.isEnd(), model.getGroupe(),
|
||||
(model.getC1_id() == null) ? null : model.getC1_id().getId(),
|
||||
(model.getC1_guest() == null) ? null : model.getC1_guest().getName(),
|
||||
(model.getC2_id() == null) ? null : model.getC2_id().getId(),
|
||||
(model.getC2_guest() == null) ? null : model.getC2_guest().getName(),
|
||||
model.getCategory().getId(), model.getCategory_ord(), model.isEnd(), model.getPoule(),
|
||||
model.getScores());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class RegisterRequestData {
|
||||
private Long licence;
|
||||
@@ -12,4 +18,12 @@ public class RegisterRequestData {
|
||||
|
||||
private Integer weight;
|
||||
private int overCategory;
|
||||
private boolean lockEdit = false;
|
||||
|
||||
// for guest registration only
|
||||
private Long id = null;
|
||||
private Categorie categorie = Categorie.CADET;
|
||||
private Genre genre = Genre.NA;
|
||||
private String club = null;
|
||||
private String country = null;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ import java.util.List;
|
||||
@RegisterForReflection
|
||||
public class RenewAffData {
|
||||
String name;
|
||||
Long siret;
|
||||
String rna;
|
||||
String state_id;
|
||||
String address;
|
||||
String contact;
|
||||
int saison;
|
||||
List<RenewMember> members;
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import fr.titionfire.ffsaf.utils.TreeNode;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class ResultCategoryData {
|
||||
int type;
|
||||
String name;
|
||||
HashMap<Character, List<PouleArrayData>> matchs = new HashMap<>();
|
||||
HashMap<Character, List<RankArray>> rankArray = new HashMap<>();
|
||||
ArrayList<TreeNode<TreeData>> trees;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public static class RankArray {
|
||||
int rank;
|
||||
String name;
|
||||
int win;
|
||||
int pointMake;
|
||||
int pointTake;
|
||||
float pointRate;
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public record PouleArrayData(String red, boolean red_w, List<Integer[]> score, boolean blue_w, String blue, boolean end) {
|
||||
public static PouleArrayData fromModel(MatchModel matchModel) {
|
||||
return new PouleArrayData(
|
||||
matchModel.getC1Name(),
|
||||
matchModel.isEnd() && matchModel.win() > 0,
|
||||
matchModel.isEnd() ?
|
||||
matchModel.getScores().stream().map(s -> new Integer[]{s.getS1(), s.getS2()}).toList()
|
||||
: new ArrayList<>(),
|
||||
matchModel.isEnd() && matchModel.win() < 0,
|
||||
matchModel.getC2Name(),
|
||||
matchModel.isEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public static record TreeData(long id, String c1FullName, String c2FullName, List<ScoreEmbeddable> scores,
|
||||
boolean end) {
|
||||
public static TreeData from(MatchModel match) {
|
||||
return new TreeData(match.getId(), match.getC1Name(), match.getC2Name(), match.getScores(), match.isEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,8 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
public class SimpleAffiliation {
|
||||
@Schema(description = "L'identifiant de l'affiliation.", example = "1")
|
||||
private Long id;
|
||||
@Schema(description = "L'identifiant du club associé à l'affiliation.", example = "123")
|
||||
private Long club;
|
||||
@Schema(description = "L'identifiant du club associé à l'affiliation si id > 0 sinon n° SIRET ou RNA du club.", example = "123")
|
||||
private String club;
|
||||
@Schema(description = "La saison de l'affiliation.", example = "2022")
|
||||
private int saison;
|
||||
@Schema(description = "Indique si l'affiliation est validée ou non.", example = "true")
|
||||
@@ -27,7 +27,7 @@ public class SimpleAffiliation {
|
||||
|
||||
return new SimpleAffiliationBuilder()
|
||||
.id(model.getId())
|
||||
.club(model.getClub().getId())
|
||||
.club(String.valueOf(model.getClub().getId()))
|
||||
.saison(model.getSaison())
|
||||
.validate(true)
|
||||
.build();
|
||||
|
||||
@@ -36,10 +36,8 @@ public class SimpleClub {
|
||||
private String contact_intern;
|
||||
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris")
|
||||
private String address;
|
||||
@Schema(description = "RNA du club", example = "W123456789")
|
||||
private String RNA;
|
||||
@Schema(description = "Numéro SIRET du club", example = "12345678901234")
|
||||
private Long SIRET;
|
||||
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234")
|
||||
private String state_id;
|
||||
@Schema(description = "Numéro d'affiliation du club", example = "12345")
|
||||
private Long no_affiliation;
|
||||
@Schema(description = "Club international", example = "false")
|
||||
@@ -60,8 +58,7 @@ public class SimpleClub {
|
||||
.training_location(model.getTraining_location())
|
||||
.training_day_time(model.getTraining_day_time())
|
||||
.contact_intern(model.getContact_intern())
|
||||
.RNA(model.getRNA())
|
||||
.SIRET(model.getSIRET())
|
||||
.state_id(model.getStateId())
|
||||
.no_affiliation(model.getNo_affiliation())
|
||||
.international(model.isInternational())
|
||||
.address(model.getAddress())
|
||||
|
||||
@@ -20,8 +20,8 @@ public class SimpleClubList {
|
||||
String name;
|
||||
@Schema(description = "Pays du club", example = "FR")
|
||||
String country;
|
||||
@Schema(description = "Numéro SIRET du club", example = "12345678901234")
|
||||
Long siret;
|
||||
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234")
|
||||
String state_id;
|
||||
@Schema(description = "Numéro d'affiliation du club", example = "12345")
|
||||
Long no_affiliation;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SimpleClubList {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new SimpleClubList(model.getId(), model.getName(), model.getCountry(), model.getSIRET(),
|
||||
return new SimpleClubList(model.getId(), model.getName(), model.getCountry(), model.getStateId(),
|
||||
model.getNo_affiliation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ public class SimpleLicence {
|
||||
String certificate;
|
||||
@Schema(description = "Validation de la licence", example = "true")
|
||||
boolean validate;
|
||||
@Schema(description = "Licence payer", example = "true")
|
||||
boolean pay;
|
||||
|
||||
public static SimpleLicence fromModel(LicenceModel model) {
|
||||
if (model == null)
|
||||
@@ -33,6 +35,7 @@ public class SimpleLicence {
|
||||
.saison(model.getSaison())
|
||||
.certificate(model.getCertificate())
|
||||
.validate(model.isValidate())
|
||||
.pay(model.isPay())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
|
||||
import fr.titionfire.ffsaf.data.model.LicenceModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.utils.Categorie;
|
||||
import fr.titionfire.ffsaf.utils.Genre;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -18,19 +21,31 @@ public class SimpleRegisterComb {
|
||||
private long id;
|
||||
private String fname;
|
||||
private String lname;
|
||||
private String categorie;
|
||||
private Genre genre;
|
||||
private String country;
|
||||
private Categorie categorie;
|
||||
private SimpleClubModel club;
|
||||
private Integer licence;
|
||||
private Integer weight;
|
||||
private int overCategory;
|
||||
private boolean hasLicenceActive;
|
||||
private boolean lockEdit;
|
||||
|
||||
public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) {
|
||||
MembreModel membreModel = register.getMembre();
|
||||
return new SimpleRegisterComb(membreModel.getId(), membreModel.getFname(), membreModel.getLname(),
|
||||
(register.getCategorie() == null) ? "Catégorie inconnue" : register.getCategorie().getName(),
|
||||
membreModel.getGenre(), membreModel.getCountry(),
|
||||
(register.getCategorie() == null) ? null : register.getCategorie(),
|
||||
SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(),
|
||||
register.getOverCategory(),
|
||||
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()));
|
||||
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()),
|
||||
register.isLockEdit());
|
||||
}
|
||||
|
||||
public static SimpleRegisterComb fromModel(CompetitionGuestModel guest) {
|
||||
return new SimpleRegisterComb(guest.getId() * -1, guest.getFname(), guest.getLname(),
|
||||
guest.getGenre(), guest.getCountry(), guest.getCategorie(),
|
||||
new SimpleClubModel(null, guest.getClub(), "fr", null),
|
||||
null, guest.getWeight(), 0, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,8 @@ public class SimpleReqAffiliation {
|
||||
Long club_no_aff;
|
||||
@Schema(description = "Nom du club demander", example = "Association sportive")
|
||||
String name;
|
||||
@Schema(description = "Numéro SIRET de l'association", example = "12345678901234")
|
||||
long siret;
|
||||
@Schema(description = "Numéro RNA de l'association", example = "W123456789")
|
||||
String RNA;
|
||||
@Schema(description = "Numéro SIRET ou RNA de l'association", example = "12345678901234")
|
||||
String stateId;
|
||||
@Schema(description = "Adresse de l'association", example = "1 rue de l'exemple, 75000 Paris")
|
||||
String address;
|
||||
@Schema(description = "Email de contact de l'association", example = "test@test.fr")
|
||||
@@ -45,8 +43,7 @@ public class SimpleReqAffiliation {
|
||||
return new SimpleReqAffiliation.SimpleReqAffiliationBuilder()
|
||||
.id(model.getId())
|
||||
.name(model.getName())
|
||||
.siret(model.getSiret())
|
||||
.RNA(model.getRNA())
|
||||
.stateId(model.getState_id())
|
||||
.address(model.getAddress())
|
||||
.saison(model.getSaison())
|
||||
.contact(model.getContact())
|
||||
|
||||
@@ -16,8 +16,8 @@ public class SimpleReqAffiliationResume {
|
||||
Long id;
|
||||
@Schema(description = "Le nom de l'association.", example = "Association sportive")
|
||||
String name;
|
||||
@Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234")
|
||||
long siret;
|
||||
@Schema(description = "Le numéro SIRET ou RNA de l'association.", example = "12345678901234")
|
||||
String stateId;
|
||||
@Schema(description = "La saison de l'affiliation.", example = "2025")
|
||||
int saison;
|
||||
|
||||
@@ -25,10 +25,10 @@ public class SimpleReqAffiliationResume {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new SimpleReqAffiliationResume.SimpleReqAffiliationResumeBuilder()
|
||||
return new SimpleReqAffiliationResumeBuilder()
|
||||
.id(model.getId())
|
||||
.name(model.getName())
|
||||
.siret(model.getSiret())
|
||||
.stateId(model.getState_id())
|
||||
.saison(model.getSaison())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import lombok.Data;
|
||||
@RegisterForReflection
|
||||
public class TreeData {
|
||||
private Long id;
|
||||
private Long poule;
|
||||
private Long category;
|
||||
private Integer level;
|
||||
private Long match;
|
||||
private TreeData left;
|
||||
@@ -20,7 +20,7 @@ public class TreeData {
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return new TreeData(model.getId(), model.getPoule(), model.getLevel(), model.getMatch().getId(),
|
||||
return new TreeData(model.getId(), model.getCategory(), model.getLevel(), model.getMatch().getId(),
|
||||
fromModel(model.getLeft()), fromModel(model.getRight()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ public class UniteLegaleRoot {
|
||||
public String etat_administratif;
|
||||
public String identifiant_association;
|
||||
public String nic_siege;
|
||||
public Object nom;
|
||||
public Object nom_usage;
|
||||
public String nom;
|
||||
public String nom_usage;
|
||||
public int nombre_periodes;
|
||||
public String nomenclature_activite_principale;
|
||||
public Object prenom_1;
|
||||
@@ -67,7 +67,7 @@ public class UniteLegaleRoot {
|
||||
private Object code_pays_etranger_2;
|
||||
private String code_postal;
|
||||
private Object code_postal_2;
|
||||
private Object complement_adresse;
|
||||
private String complement_adresse;
|
||||
private Object complement_adresse2;
|
||||
private String date_creation;
|
||||
private String date_debut;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package fr.titionfire.ffsaf.rest.data;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class VerySimpleMembre {
|
||||
@Schema(description = "Le nom du membre.", example = "Dupont")
|
||||
private String lname = "";
|
||||
@Schema(description = "Le prénom du membre.", example = "Jean")
|
||||
private String fname = "";
|
||||
@Schema(description = "Le numéro de licence du membre.", example = "12345")
|
||||
private Integer licence;
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
import org.jboss.resteasy.reactive.PartType;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@ToString(exclude = {"status", "logo"})
|
||||
public class AffiliationRequestForm {
|
||||
@Schema(description = "L'identifiant de l'affiliation. (null si nouvelle demande d'affiliation)")
|
||||
@FormParam("id")
|
||||
@@ -21,13 +21,9 @@ public class AffiliationRequestForm {
|
||||
@FormParam("name")
|
||||
private String name = null;
|
||||
|
||||
@Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234", required = true)
|
||||
@FormParam("siret")
|
||||
private Long siret = null;
|
||||
|
||||
@Schema(description = "Le numéro RNA de l'association. (peut être null)", example = "W123456789")
|
||||
@FormParam("rna")
|
||||
private String rna = null;
|
||||
@Schema(description = "Le numéro SIRET/RNA de l'association.", example = "12345678901234", required = true)
|
||||
@FormParam("state_id")
|
||||
private String state_id = null;
|
||||
|
||||
@Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true)
|
||||
@FormParam("adresse")
|
||||
@@ -114,8 +110,7 @@ public class AffiliationRequestForm {
|
||||
public AffiliationRequestModel toModel() {
|
||||
AffiliationRequestModel model = new AffiliationRequestModel();
|
||||
model.setName(this.getName());
|
||||
model.setSiret(this.getSiret());
|
||||
model.setRNA(this.getRna());
|
||||
model.setState_id(this.getState_id());
|
||||
model.setAddress(this.getAdresse());
|
||||
model.setSaison(this.getSaison());
|
||||
model.setContact(this.getContact());
|
||||
|
||||
@@ -4,12 +4,10 @@ import fr.titionfire.ffsaf.utils.RoleAsso;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
import org.jboss.resteasy.reactive.PartType;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class AffiliationRequestSaveForm {
|
||||
@Schema(description = "L'identifiant de l'affiliation.", example = "1", required = true)
|
||||
@FormParam("id")
|
||||
@@ -19,13 +17,9 @@ public class AffiliationRequestSaveForm {
|
||||
@FormParam("name")
|
||||
private String name = null;
|
||||
|
||||
@Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234", required = true)
|
||||
@FormParam("siret")
|
||||
private Long siret = null;
|
||||
|
||||
@Schema(description = "Le numéro RNA de l'association. (peut être null)", example = "W123456789")
|
||||
@FormParam("rna")
|
||||
private String rna = null;
|
||||
@Schema(description = "Le numéro SIRET ou RNA de l'association.", example = "12345678901234", required = true)
|
||||
@FormParam("state_id")
|
||||
private String state_id = null;
|
||||
|
||||
@Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true)
|
||||
@FormParam("address")
|
||||
@@ -171,4 +165,38 @@ public class AffiliationRequestSaveForm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AffiliationRequestSaveForm{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", state_id=" + state_id +
|
||||
", address='" + address + '\'' +
|
||||
", contact='" + contact + '\'' +
|
||||
", status_len=" + status.length +
|
||||
", logo_len=" + logo.length +
|
||||
", m1_mode=" + m1_mode +
|
||||
", m1_role=" + m1_role +
|
||||
", m1_lincence='" + m1_lincence + '\'' +
|
||||
", m1_lname='" + m1_lname + '\'' +
|
||||
", m1_fname='" + m1_fname + '\'' +
|
||||
", m1_email='" + m1_email + '\'' +
|
||||
", m1_email_mode=" + m1_email_mode +
|
||||
", m2_mode=" + m2_mode +
|
||||
", m2_role=" + m2_role +
|
||||
", m2_lincence='" + m2_lincence + '\'' +
|
||||
", m2_lname='" + m2_lname + '\'' +
|
||||
", m2_fname='" + m2_fname + '\'' +
|
||||
", m2_email='" + m2_email + '\'' +
|
||||
", m2_email_mode=" + m2_email_mode +
|
||||
", m3_mode=" + m3_mode +
|
||||
", m3_role=" + m3_role +
|
||||
", m3_lincence='" + m3_lincence + '\'' +
|
||||
", m3_lname='" + m3_lname + '\'' +
|
||||
", m3_fname='" + m3_fname + '\'' +
|
||||
", m3_email='" + m3_email + '\'' +
|
||||
", m3_email_mode=" + m3_email_mode +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,9 @@ public class FullClubForm {
|
||||
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris", required = true)
|
||||
private String address = null;
|
||||
|
||||
@FormParam("rna")
|
||||
@Schema(description = "RNA du club", example = "W123456789")
|
||||
private String rna = null;
|
||||
|
||||
@FormParam("siret")
|
||||
@Schema(description = "Numéro SIRET du club", example = "12345678901234", required = true)
|
||||
private String siret = null;
|
||||
@FormParam("state_id")
|
||||
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234", required = true)
|
||||
private String state_id = null;
|
||||
|
||||
@FormParam("international")
|
||||
@Schema(description = "Club international", example = "false", required = true)
|
||||
|
||||
@@ -21,10 +21,14 @@ public class LicenceForm {
|
||||
private int saison;
|
||||
|
||||
@FormParam("certificate")
|
||||
@Schema(description = "Nom du médecin sur certificat médical.", example = "M. Jean", required = true)
|
||||
@Schema(description = "Nom et date du médecin sur certificat médical.", example = "M. Jean¤2025-02-03", format = "<Nom>¤<yyyy-mm-dd>", required = true)
|
||||
private String certificate = null;
|
||||
|
||||
@FormParam("validate")
|
||||
@Schema(description = "Licence validée (seuls les admin pourrons enregistrer cette valeur)", example = "true", required = true)
|
||||
@Schema(description = "Licence validée (seuls les admin pourrons modifier cette valeur)", example = "true", required = true)
|
||||
private boolean validate;
|
||||
|
||||
@FormParam("pay")
|
||||
@Schema(description = "Paiement de la licence (seuls les admin pourrons modifier cette valeur)", example = "true", required = true)
|
||||
private boolean pay;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ public class MemberPermForm {
|
||||
@FormParam("safca_user")
|
||||
private boolean safca_user;
|
||||
|
||||
@Schema(description = "Indique si le membre peut créer des compétitions sur SAFCA.", example = "false", required = true)
|
||||
@FormParam("safca_create_compet")
|
||||
private boolean safca_create_compet;
|
||||
@Schema(description = "Indique si le membre peut créer des compétitions.", example = "false", required = true)
|
||||
@FormParam("create_compet")
|
||||
private boolean create_compet;
|
||||
|
||||
@Schema(description = "Indique si le membre est un super administrateur SAFCA.", example = "false", required = true)
|
||||
@FormParam("safca_super_admin")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package fr.titionfire.ffsaf.utils;
|
||||
|
||||
public enum CompetitionSystem {
|
||||
SAFCA,
|
||||
SAFCA, INTERNAL
|
||||
}
|
||||
|
||||
12
src/main/java/fr/titionfire/ffsaf/utils/RegisterMode.java
Normal file
12
src/main/java/fr/titionfire/ffsaf/utils/RegisterMode.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package fr.titionfire.ffsaf.utils;
|
||||
|
||||
public enum RegisterMode {
|
||||
FREE, CLUB_ADMIN, ADMIN, HELLOASSO
|
||||
}
|
||||
/*
|
||||
HELLOASSO:
|
||||
-> data1 = organizationSlug
|
||||
-> data2 = formSlug
|
||||
-> data3 = tarifs
|
||||
-> data4 = errorEmail
|
||||
*/
|
||||
@@ -31,6 +31,11 @@ public class SecurityCtx {
|
||||
return securityIdentity.getRoles().contains(role);
|
||||
}
|
||||
|
||||
public boolean isClubAdmin() {
|
||||
return this.roleHas("club_president") || this.roleHas("club_respo_intra")
|
||||
|| this.roleHas("club_secretaire") || this.roleHas("club_tresorier");
|
||||
}
|
||||
|
||||
public boolean isInClubGroup(long id) {
|
||||
if (idToken == null || idToken.getClaim("user_groups") == null)
|
||||
return false;
|
||||
|
||||
35
src/main/java/fr/titionfire/ffsaf/utils/TreeNode.java
Normal file
35
src/main/java/fr/titionfire/ffsaf/utils/TreeNode.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package fr.titionfire.ffsaf.utils;
|
||||
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@RegisterForReflection
|
||||
public class TreeNode<T> {
|
||||
private T data;
|
||||
private TreeNode<T> left;
|
||||
private TreeNode<T> right;
|
||||
|
||||
public TreeNode(T data) {
|
||||
this(data, null, null);
|
||||
}
|
||||
|
||||
public int death() {
|
||||
int dg = 0;
|
||||
int dd = 0;
|
||||
|
||||
if (this.right != null)
|
||||
dg = this.right.death();
|
||||
|
||||
if (this.left != null)
|
||||
dg = this.left.death();
|
||||
|
||||
return 1 + Math.max(dg, dd);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user