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; import fr.titionfire.ffsaf.data.repository.SequenceRepository; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.from.LicenceForm; import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.SequenceType; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.hibernate.reactive.panache.Panache; 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 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; @Inject CombRepository combRepository; @Inject SequenceRepository sequenceRepository; @Inject KeycloakService keycloakService; @Inject LoggerService ls; @Inject CheckoutService checkoutService; public Uni> getLicence(long id, Consumer checkPerm) { return combRepository.findById(id).invoke(checkPerm) .chain(combRepository -> Mutiny.fetch(combRepository.getLicences())); } public Uni> getCurrentSaisonLicence(SecurityCtx securityCtx) { if (securityCtx == null || securityCtx.getSubject() == null) return repository.find("saison = ?1", Utils.getSaison()).list(); return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().map(MembreModel::getClub) .chain(clubModel -> combRepository.find("club = ?1", clubModel).list()) .chain(membres -> repository.find("saison = ?1 AND membre IN ?2", Utils.getSaison(), membres).list()); } public Uni valideLicences(List ids) { Uni 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 validateLicences(LicenceModel model) { model.setValidate(true); return Panache.withTransaction(() -> repository.persist(model) .call(m -> Mutiny.fetch(m.getMembre()) .call(genLicenceNumberAndAccountIfNeed()) )); } public Uni validePaymentLicences(List ids) { Uni 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 validatePayLicences(LicenceModel model) { model.setPay(true); return Panache.withTransaction(() -> repository.persist(model)); } public Uni setLicence(long id, LicenceForm form) { if (form.getId() == -1) { return combRepository.findById(id).chain(membreModel -> { LicenceModel model = new LicenceModel(); model.setMembre(membreModel); model.setClub_id((membreModel.getClub() == null) ? null : membreModel.getClub().getId()); 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() ? 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(genLicenceNumberAndAccountIfNeed()) : Uni.createFrom().nullItem() )) .call(__ -> ls.append()); }); } } private Function> genLicenceNumberAndAccountIfNeed() { return membreModel -> ((membreModel.getLicence() == null || 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 payLicences(List ids, Consumer 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 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 -> Panache.withTransaction(() -> repository.delete(model))); } public Uni askLicence(long id, LicenceForm form, Consumer checkPerm) { return combRepository.findById(id).invoke(checkPerm).chain(membreModel -> { if (form.getId() == -1) { return repository.find("saison = ?1 AND membre = ?2", Utils.getSaison(), membreModel).count() .invoke(Unchecked.consumer(count -> { if (count > 0) throw new DBadRequestException("Licence déjà demandée"); })).chain(__ -> combRepository.findById(id).chain(membreModel2 -> { LicenceModel model = new LicenceModel(); model.setClub_id((membreModel2.getClub() == null) ? null : membreModel2.getClub().getId()); model.setMembre(membreModel2); model.setSaison(Utils.getSaison()); 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)) .call(__ -> ls.append()); }); } }); } public Uni deleteAskLicence(long id, Consumer 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))); } public Uni setImport(int licence, int saison, boolean valid) { return combRepository.find("licence = ?1", licence).firstResult() .chain(membreModel -> repository.find("saison = ?1 AND membre = ?2", saison, membreModel).firstResult() .chain(licenceModel -> { if (licenceModel != null) { if (licenceModel.getClub_id() == null) licenceModel.setClub_id( (membreModel.getClub() == null) ? null : membreModel.getClub() .getId()); licenceModel.setValidate(valid); return Panache.withTransaction(() -> repository.persist(licenceModel)); } else { LicenceModel model = new LicenceModel(); model.setClub_id( (membreModel.getClub() == null) ? null : membreModel.getClub().getId()); model.setMembre(membreModel); model.setSaison(saison); model.setCertificate("¤"); model.setValidate(valid); return Panache.withTransaction(() -> repository.persist(model)); } })) .map(__ -> "OK"); } }