Compare commits

...

4 Commits

9 changed files with 54 additions and 36 deletions
@@ -1,16 +1,16 @@
CREATE TABLE role (
CREATE TABLE IF NOT EXISTS role (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE NOT NULL
);
CREATE TABLE app_user (
CREATE TABLE IF NOT EXISTS app_user (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE
);
CREATE TABLE user_role (
CREATE TABLE IF NOT EXISTS user_role (
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
PRIMARY KEY (user_id, role_id),
@@ -18,7 +18,7 @@ CREATE TABLE user_role (
CONSTRAINT fk_role FOREIGN KEY (role_id) REFERENCES role(id) ON DELETE CASCADE
);
CREATE TABLE adherent (
CREATE TABLE IF NOT EXISTS adherent (
id BIGSERIAL PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
prenom VARCHAR(100) NOT NULL,
@@ -29,7 +29,7 @@ CREATE TABLE adherent (
representant_legal VARCHAR(150)
);
CREATE TABLE categorie (
CREATE TABLE IF NOT EXISTS categorie (
id BIGSERIAL PRIMARY KEY,
nom VARCHAR(20) UNIQUE NOT NULL,
annee_min INT,
@@ -37,7 +37,7 @@ CREATE TABLE categorie (
tarif_base DECIMAL(10,2) NOT NULL
);
CREATE TABLE licence (
CREATE TABLE IF NOT EXISTS licence (
id BIGSERIAL PRIMARY KEY,
adherent_id BIGINT NOT NULL,
categorie_id BIGINT NOT NULL,
@@ -47,7 +47,7 @@ CREATE TABLE licence (
CONSTRAINT fk_licence_categorie FOREIGN KEY (categorie_id) REFERENCES categorie(id)
);
CREATE TABLE paiement (
CREATE TABLE IF NOT EXISTS paiement (
id BIGSERIAL PRIMARY KEY,
licence_id BIGINT NOT NULL,
montant DECIMAL(10,2) NOT NULL,
@@ -56,14 +56,14 @@ CREATE TABLE paiement (
CONSTRAINT fk_paiement_licence FOREIGN KEY (licence_id) REFERENCES licence(id) ON DELETE CASCADE
);
CREATE TABLE equipement (
CREATE TABLE IF NOT EXISTS equipement (
id BIGSERIAL PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
description TEXT,
obligatoire BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE TABLE dotation (
CREATE TABLE IF NOT EXISTS dotation (
id BIGSERIAL PRIMARY KEY,
licence_id BIGINT NOT NULL,
equipement_id BIGINT NOT NULL,
@@ -1,12 +1,18 @@
CREATE TABLE mode_paiement (
CREATE TABLE IF NOT EXISTS mode_paiement (
id BIGSERIAL PRIMARY KEY,
nom VARCHAR(50) UNIQUE NOT NULL
);
INSERT INTO mode_paiement (nom) VALUES ('Espèces'), ('Chèque'), ('Pass Sport'), ('Virement');
INSERT INTO mode_paiement (nom) VALUES ('Espèces'), ('Chèque'), ('Pass Sport'), ('Virement')
ON CONFLICT (nom) DO NOTHING;
ALTER TABLE paiement ADD COLUMN mode_paiement_id BIGINT;
ALTER TABLE paiement ADD COLUMN IF NOT EXISTS mode_paiement_id BIGINT;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_paiement_mode') THEN
ALTER TABLE paiement ADD CONSTRAINT fk_paiement_mode FOREIGN KEY (mode_paiement_id) REFERENCES mode_paiement(id);
END IF;
END $$;
ALTER TABLE paiement DROP COLUMN mode_paiement;
ALTER TABLE paiement DROP COLUMN IF EXISTS mode_paiement;
@@ -1,9 +1,11 @@
INSERT INTO role (name) VALUES ('ROLE_ADMIN'), ('ROLE_USER');
INSERT INTO role (name) VALUES ('ROLE_ADMIN'), ('ROLE_USER') ON CONFLICT (name) DO NOTHING;
-- Password is "Talange2026!" hashed with Argon2id
INSERT INTO app_user (username, password, enabled) VALUES ('Ucef', '$argon2id$v=19$m=65536,t=3,p=4$q29E/VM1esZVxo9HufgILQ$Nzb+rwwsZUMy04BbewYum2A8L8ujs9VZj9VJ/609Am0', true);
INSERT INTO app_user (username, password, enabled) VALUES ('Ucef', '$argon2id$v=19$m=65536,t=3,p=4$q29E/VM1esZVxo9HufgILQ$Nzb+rwwsZUMy04BbewYum2A8L8ujs9VZj9VJ/609Am0', true)
ON CONFLICT (username) DO NOTHING;
INSERT INTO user_role (user_id, role_id) VALUES ((SELECT id FROM app_user WHERE username = 'Ucef'), (SELECT id FROM role WHERE name = 'ROLE_ADMIN'));
INSERT INTO user_role (user_id, role_id) VALUES ((SELECT id FROM app_user WHERE username = 'Ucef'), (SELECT id FROM role WHERE name = 'ROLE_ADMIN'))
ON CONFLICT (user_id, role_id) DO NOTHING;
INSERT INTO categorie (nom, annee_min, annee_max, tarif_base) VALUES
('U6', 2020, 2020, 100.00),
@@ -14,10 +16,14 @@ INSERT INTO categorie (nom, annee_min, annee_max, tarif_base) VALUES
('U11', 2015, 2015, 130.00),
('U12', 2014, 2014, 140.00),
('U13', 2013, 2013, 140.00),
('Senior', 1900, 2005, 180.00);
('Senior', 1900, 2005, 180.00)
ON CONFLICT (nom) DO NOTHING;
INSERT INTO equipement (nom, obligatoire) VALUES
('Maillot', true),
('Short', true),
('Chaussettes', true),
('Survêtement', false);
INSERT INTO equipement (nom, obligatoire)
SELECT 'Maillot', true WHERE NOT EXISTS (SELECT 1 FROM equipement WHERE nom = 'Maillot');
INSERT INTO equipement (nom, obligatoire)
SELECT 'Short', true WHERE NOT EXISTS (SELECT 1 FROM equipement WHERE nom = 'Short');
INSERT INTO equipement (nom, obligatoire)
SELECT 'Chaussettes', true WHERE NOT EXISTS (SELECT 1 FROM equipement WHERE nom = 'Chaussettes');
INSERT INTO equipement (nom, obligatoire)
SELECT 'Survêtement', false WHERE NOT EXISTS (SELECT 1 FROM equipement WHERE nom = 'Survêtement');
@@ -1,8 +1,8 @@
-- Ajouter la colonne pour savoir si l'adhérent est résident de Talange (par défaut oui pour les existants)
ALTER TABLE adherent ADD COLUMN resident_talange BOOLEAN DEFAULT TRUE;
ALTER TABLE adherent ADD COLUMN IF NOT EXISTS resident_talange BOOLEAN DEFAULT TRUE;
-- Ajouter le tarif extérieur aux catégories
ALTER TABLE categorie ADD COLUMN tarif_exterieur DECIMAL(10,2);
ALTER TABLE categorie ADD COLUMN IF NOT EXISTS tarif_exterieur DECIMAL(10,2);
-- Par défaut, mettre le tarif extérieur égal au tarif de base pour ne pas casser les licences existantes
UPDATE categorie SET tarif_exterieur = tarif_base;
UPDATE categorie SET tarif_exterieur = tarif_base*1.2 WHERE tarif_exterieur IS NULL;
@@ -1 +1 @@
ALTER TABLE licence ADD COLUMN numero_licence VARCHAR(50);
ALTER TABLE licence ADD COLUMN IF NOT EXISTS numero_licence VARCHAR(50);
@@ -48,6 +48,12 @@ public class LicenceController {
Adherent adherent = adherentRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid Adherent ID"));
List<Licence> existingLicences = licenceRepository.findByAdherentId(id);
if (!existingLicences.isEmpty()) {
return "redirect:/adherents/" + id + "/edit";
}
Categorie categorie = categorieRepository.findById(categorieId)
.orElseThrow(() -> new IllegalArgumentException("Invalid Categorie ID"));
@@ -16,7 +16,7 @@ spring:
flyway:
enabled: true
locations: classpath:db/migration
ignore-migration-patterns: "*:mismatch"
validate-on-migrate: false
server:
port: 8080
@@ -144,7 +144,7 @@
<div th:if="${adherent.id != null}" class="max-w-3xl mx-auto bg-white rounded-xl shadow-sm border border-gray-100 p-8 mt-6">
<div class="flex justify-between items-center mb-6">
<h3 class="text-xl font-bold text-gray-900">Licences de l'adhérent</h3>
<button onclick="openLicenceModal()" class="bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-green-700 transition-colors">
<button th:if="${#lists.isEmpty(licences)}" onclick="openLicenceModal()" class="bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:bg-green-700 transition-colors">
+ Ajouter une Licence
</button>
</div>
@@ -51,17 +51,17 @@
<tr th:if="${#lists.isEmpty(equipements)}">
<td colspan="4" class="py-8 text-center text-gray-500">Aucun équipement n'est paramétré.</td>
</tr>
<tr th:each="eq : ${equipements}" class="hover:bg-gray-50 transition-colors">
<td class="py-4 px-6 font-medium text-gray-900" th:text="${eq.nom}">Maillot</td>
<td class="py-4 px-6 text-gray-600" th:text="${eq.description != null ? eq.description : '-'}">Maillot de match officiel</td>
<tr th:each="equip : ${equipements}" class="hover:bg-gray-50 transition-colors">
<td class="py-4 px-6 font-medium text-gray-900" th:text="${equip.nom}">Maillot</td>
<td class="py-4 px-6 text-gray-600" th:text="${equip.description != null ? equip.description : '-'}">Maillot de match officiel</td>
<td class="py-4 px-6 text-center">
<span class="px-2.5 py-1 text-xs font-semibold rounded-full"
th:classappend="${eq.obligatoire ? 'bg-red-100 text-red-800' : 'bg-gray-100 text-gray-800'}"
th:text="${eq.obligatoire ? 'Oui' : 'Non'}">Oui</span>
th:classappend="${equip.obligatoire ? 'bg-red-100 text-red-800' : 'bg-gray-100 text-gray-800'}"
th:text="${equip.obligatoire ? 'Oui' : 'Non'}">Oui</span>
</td>
<td class="py-4 px-6 text-right flex justify-end space-x-3 items-center">
<a th:href="@{/equipements/{id}/edit(id=${eq.id})}" class="text-indigo-600 hover:text-indigo-900 font-medium bg-indigo-50 px-3 py-1 rounded-lg">Modifier</a>
<form th:action="@{/equipements/{id}/delete(id=${eq.id})}" method="post" onsubmit="return confirm('Supprimer cet équipement ? Cela supprimera également les dotations associées de toutes les licences.');">
<a th:href="@{/equipements/{id}/edit(id=${equip.id})}" class="text-indigo-600 hover:text-indigo-900 font-medium bg-indigo-50 px-3 py-1 rounded-lg">Modifier</a>
<form th:action="@{/equipements/{id}/delete(id=${equip.id})}" method="post" onsubmit="return confirm('Supprimer cet équipement ? Cela supprimera également les dotations associées de toutes les licences.');">
<button type="submit" class="text-red-600 hover:text-red-800 font-medium">Supprimer</button>
</form>
</td>