Compare commits
2 Commits
a8565534e6
...
ecc9753237
| Author | SHA1 | Date | |
|---|---|---|---|
| ecc9753237 | |||
| 7c4addd525 |
@ -84,6 +84,26 @@ public class LicenceService {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Uni<?> validePaymentLicences(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.isPay())
|
||||||
|
ls.logUpdate("payment (admin) de la licence", model);
|
||||||
|
return validatePayLicences(model);
|
||||||
|
}))
|
||||||
|
.map(__ -> "OK");
|
||||||
|
}
|
||||||
|
return uni.call(__ -> ls.append());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Uni<LicenceModel> validatePayLicences(LicenceModel model) {
|
||||||
|
model.setPay(true);
|
||||||
|
return Panache.withTransaction(() -> repository.persist(model));
|
||||||
|
}
|
||||||
|
|
||||||
public Uni<LicenceModel> setLicence(long id, LicenceForm form) {
|
public Uni<LicenceModel> setLicence(long id, LicenceForm form) {
|
||||||
if (form.getId() == -1) {
|
if (form.getId() == -1) {
|
||||||
return combRepository.findById(id).chain(membreModel -> {
|
return combRepository.findById(id).chain(membreModel -> {
|
||||||
|
|||||||
@ -287,14 +287,14 @@ public class MembreService {
|
|||||||
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
if (model.getEmail() != null && !model.getEmail().isBlank()) {
|
||||||
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
if (StringSimilarity.similarity(model.getLname().toUpperCase(),
|
||||||
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
|
||||||
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
|
||||||
LOGGER.info("Similar membres found: " + model);
|
LOGGER.info("Similar membres found: " + model);
|
||||||
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
|
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utilisé");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +380,7 @@ public class MembreService {
|
|||||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0 && !membre.getEmail().isBlank())
|
if (c > 0 && !membre.getEmail().isBlank())
|
||||||
throw new DBadRequestException("Email déjà utiliser");
|
throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.chain(membreModel -> clubRepository.findById(membre.getClub())
|
.chain(membreModel -> clubRepository.findById(membre.getClub())
|
||||||
.map(club -> new Pair<>(membreModel, club)))
|
.map(club -> new Pair<>(membreModel, club)))
|
||||||
@ -402,7 +402,7 @@ public class MembreService {
|
|||||||
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0 && !membre.getEmail().isBlank())
|
if (c > 0 && !membre.getEmail().isBlank())
|
||||||
throw new DBadRequestException("Email déjà utiliser");
|
throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.invoke(Unchecked.consumer(membreModel -> {
|
.invoke(Unchecked.consumer(membreModel -> {
|
||||||
if (!securityCtx.isInClubGroup(membreModel.getClub().getId()))
|
if (!securityCtx.isInClubGroup(membreModel.getClub().getId()))
|
||||||
@ -492,7 +492,7 @@ public class MembreService {
|
|||||||
return clubRepository.findById(input.getClub())
|
return clubRepository.findById(input.getClub())
|
||||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
if (c > 0) throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.chain(clubModel -> {
|
.chain(clubModel -> {
|
||||||
MembreModel model = getMembreModel(input, clubModel);
|
MembreModel model = getMembreModel(input, clubModel);
|
||||||
@ -508,7 +508,7 @@ public class MembreService {
|
|||||||
return repository.find("userId = ?1", subject).firstResult()
|
return repository.find("userId = ?1", subject).firstResult()
|
||||||
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
.call(__ -> repository.count("email LIKE ?1", input.getEmail())
|
||||||
.invoke(Unchecked.consumer(c -> {
|
.invoke(Unchecked.consumer(c -> {
|
||||||
if (c > 0) throw new DBadRequestException("Email déjà utiliser");
|
if (c > 0) throw new DBadRequestException("Email déjà utilisé");
|
||||||
})))
|
})))
|
||||||
.call(membreModel ->
|
.call(membreModel ->
|
||||||
repository.count(
|
repository.count(
|
||||||
|
|||||||
@ -118,7 +118,7 @@ public class LicenceEndpoints {
|
|||||||
@RolesAllowed("federation_admin")
|
@RolesAllowed("federation_admin")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(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)")
|
@Operation(summary = "Validation licence", description = "Valide en masse les licences de l'année en cours (pour les administrateurs)")
|
||||||
@APIResponses(value = {
|
@APIResponses(value = {
|
||||||
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
@APIResponse(responseCode = "200", description = "Les licences ont été mise à jour avec succès"),
|
||||||
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
@APIResponse(responseCode = "403", description = "Accès refusé"),
|
||||||
@ -128,6 +128,21 @@ public class LicenceEndpoints {
|
|||||||
return licenceService.valideLicences(ids);
|
return licenceService.valideLicences(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("validate-pay")
|
||||||
|
@RolesAllowed("federation_admin")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Operation(summary = "Validation du payment des licences", description = "Valide en masse le payment des licences 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<?> validePaymentLicences(@Parameter(description = "Id des membres a valider") List<Long> ids) {
|
||||||
|
return licenceService.validePaymentLicences(ids);
|
||||||
|
}
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@RolesAllowed("federation_admin")
|
@RolesAllowed("federation_admin")
|
||||||
|
|||||||
@ -4,13 +4,14 @@ import {AxiosError} from "../components/AxiosError.jsx";
|
|||||||
import {ThreeDots} from "react-loader-spinner";
|
import {ThreeDots} from "react-loader-spinner";
|
||||||
import {useEffect, useRef, useState} from "react";
|
import {useEffect, useRef, useState} from "react";
|
||||||
import {useLocation, useNavigate} from "react-router-dom";
|
import {useLocation, useNavigate} from "react-router-dom";
|
||||||
import {apiAxios, errFormater} from "../utils/Tools.js";
|
import {apiAxios, errFormater, getCatName} from "../utils/Tools.js";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {SearchBar} from "../components/SearchBar.jsx";
|
import {SearchBar} from "../components/SearchBar.jsx";
|
||||||
import {ConfirmDialog} from "../components/ConfirmDialog.jsx";
|
import {ConfirmDialog} from "../components/ConfirmDialog.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faCircleInfo, faEuroSign} from "@fortawesome/free-solid-svg-icons";
|
import {faCircleInfo, faEuroSign} from "@fortawesome/free-solid-svg-icons";
|
||||||
import "./PayAndValidateList.css";
|
import "./PayAndValidateList.css";
|
||||||
|
import * as Tools from "../utils/Tools.js";
|
||||||
|
|
||||||
export function PayAndValidateList({source}) {
|
export function PayAndValidateList({source}) {
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ export function PayAndValidateList({source}) {
|
|||||||
const [memberData, setMemberData] = useState([]);
|
const [memberData, setMemberData] = useState([]);
|
||||||
const [licenceData, setLicenceData] = useState([]);
|
const [licenceData, setLicenceData] = useState([]);
|
||||||
const [clubFilter, setClubFilter] = useState("");
|
const [clubFilter, setClubFilter] = useState("");
|
||||||
|
const [catFilter, setCatFilter] = useState("");
|
||||||
const [stateFilter, setStateFilter] = useState((source === "club") ? 1 : 2)
|
const [stateFilter, setStateFilter] = useState((source === "club") ? 1 : 2)
|
||||||
const [lastSearch, setLastSearch] = useState("");
|
const [lastSearch, setLastSearch] = useState("");
|
||||||
const [paymentFilter, setPaymentFilter] = useState((source === "club") ? 0 : 2);
|
const [paymentFilter, setPaymentFilter] = useState((source === "club") ? 0 : 2);
|
||||||
@ -34,15 +36,15 @@ export function PayAndValidateList({source}) {
|
|||||||
data,
|
data,
|
||||||
error,
|
error,
|
||||||
refresh
|
refresh
|
||||||
} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}`, setLoading, 1)
|
} = useFetch(`/member/find/${source}?page=${page}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`, setLoading, 1)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
sessionStorage.setItem("selectedMembers", JSON.stringify(selectedMembers));
|
sessionStorage.setItem("selectedMembers", JSON.stringify(selectedMembers));
|
||||||
}, [selectedMembers]);
|
}, [selectedMembers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}`);
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter]);
|
}, [hash, clubFilter, stateFilter, lastSearch, paymentFilter, catFilter]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -62,7 +64,7 @@ export function PayAndValidateList({source}) {
|
|||||||
setMemberData(data2);
|
setMemberData(data2);
|
||||||
}, [data, licenceData]);
|
}, [data, licenceData]);
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchLicenceData = () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
apiAxios.get(`/licence/current/${source}`),
|
apiAxios.get(`/licence/current/${source}`),
|
||||||
{
|
{
|
||||||
@ -77,6 +79,10 @@ export function PayAndValidateList({source}) {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
setLicenceData(data.data);
|
setLicenceData(data.data);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLicenceData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const search = (search) => {
|
const search = (search) => {
|
||||||
@ -104,7 +110,31 @@ export function PayAndValidateList({source}) {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
setSelectedMembers([]);
|
setSelectedMembers([]);
|
||||||
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}`);
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePayment = () => {
|
||||||
|
if (selectedMembers.length === 0) {
|
||||||
|
toast.error("Aucun membre sélectionné");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.promise(
|
||||||
|
apiAxios.post(`/licence/validate-pay`, selectedMembers),
|
||||||
|
{
|
||||||
|
pending: "Validation des licences en cours...",
|
||||||
|
success: "Licences validées avec succès 🎉",
|
||||||
|
error: {
|
||||||
|
render({data}) {
|
||||||
|
return errFormater(data, "Échec de la validation des licences")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
setSelectedMembers([]);
|
||||||
|
fetchLicenceData();
|
||||||
|
refresh(`/member/find/${source}?page=${page}&search=${lastSearch}&club=${clubFilter}&licenceRequest=${stateFilter}&payment=${paymentFilter}&categorie=${catFilter}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,13 +183,20 @@ export function PayAndValidateList({source}) {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} source={source}
|
<FiltreBar data={data} clubFilter={clubFilter} setClubFilter={setClubFilter} source={source}
|
||||||
stateFilter={stateFilter} setStateFilter={setStateFilter} paymentFilter={paymentFilter}
|
stateFilter={stateFilter} setStateFilter={setStateFilter} paymentFilter={paymentFilter}
|
||||||
setPaymentFilter={setPaymentFilter}/>
|
setPaymentFilter={setPaymentFilter} setCatFilter={setCatFilter} catFilter={catFilter}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
{source === "admin" && <>
|
{source === "admin" && <>
|
||||||
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-validation">Valider
|
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-pay">Valider le payement
|
||||||
|
des {selectedMembers.length} licences sélectionnée
|
||||||
|
</button>
|
||||||
|
<ConfirmDialog title="Payment des licences"
|
||||||
|
message={"Êtes-vous sûr de vouloir marquer comme payées les " + selectedMembers.length + " licences ?"}
|
||||||
|
onConfirm={handlePayment} id="confirm-pay"/>
|
||||||
|
|
||||||
|
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#confirm-validation" style={{marginTop: "0.5em"}}>Valider
|
||||||
les {selectedMembers.length} licences sélectionnée
|
les {selectedMembers.length} licences sélectionnée
|
||||||
</button>
|
</button>
|
||||||
<ConfirmDialog title="Validation des licences"
|
<ConfirmDialog title="Validation des licences"
|
||||||
@ -385,7 +422,7 @@ function MakeRow({member, source, isChecked, onCheckboxClick, onRowClick}) {
|
|||||||
|
|
||||||
let allClub = []
|
let allClub = []
|
||||||
|
|
||||||
function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setStateFilter, paymentFilter, setPaymentFilter}) {
|
function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setStateFilter, paymentFilter, setPaymentFilter, setCatFilter, catFilter}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
@ -395,6 +432,14 @@ function FiltreBar({data, clubFilter, setClubFilter, source, stateFilter, setSta
|
|||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
{source !== "club" && <ClubSelectFilter clubFilter={clubFilter} setClubFilter={setClubFilter}/>}
|
{source !== "club" && <ClubSelectFilter clubFilter={clubFilter} setClubFilter={setClubFilter}/>}
|
||||||
|
<div className="mb-3">
|
||||||
|
<select className="form-select" value={catFilter} onChange={event => setCatFilter(event.target.value)}>
|
||||||
|
<option value="">--- toute les catégories ---</option>
|
||||||
|
{Tools.CatList.map(cat => (
|
||||||
|
<option key={cat} value={cat}>{getCatName(cat)}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<select className="form-select" value={stateFilter} onChange={event => setStateFilter(Number(event.target.value))}>
|
<select className="form-select" value={stateFilter} onChange={event => setStateFilter(Number(event.target.value))}>
|
||||||
<option value={1}>Avec demande ou licence validée</option>
|
<option value={1}>Avec demande ou licence validée</option>
|
||||||
|
|||||||
@ -67,10 +67,10 @@ export function InformationForm({data}) {
|
|||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
}
|
}
|
||||||
}).then(_ => {
|
}).then(_ => {
|
||||||
toast.success('Profile mis à jours avec succès 🎉');
|
toast.success('Profil mis à jours avec succès 🎉');
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.log(e.response)
|
console.log(e.response)
|
||||||
toast.error(errFormater(e,'Échec de la mise à jours du profile 😕'));
|
toast.error(errFormater(e,'Échec de la mise à jours du profil 😕'));
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
if (setLoading)
|
if (setLoading)
|
||||||
setLoading(0)
|
setLoading(0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user