-- ============================================================================
-- RÈGLES D'ARCHITECTURE : Plan comptable mutualisé
-- ============================================================================
-- Date : 23 octobre 2025
-- Objectif : Simplifier la gestion du plan comptable
-- ============================================================================

/**
 * PRINCIPE FONDAMENTAL
 * ====================
 * 
 * Le plan comptable est MUTUALISÉ pour tous les comptes généraux.
 * La séparation des données entre copros se fait au niveau des ÉCRITURES.
 * 
 * Exception : Les comptes tiers (401XXX, 450XXX) restent spécifiques à chaque copro.
 */

-- ============================================================================
-- RÈGLE 1 : Structure du plan_comptable
-- ============================================================================

/**
 * COMPTES GÉNÉRAUX (mutualisés) :
 * - id_copro = NULL
 * - id_entite = NULL
 * - type_entite = NULL
 * - Exemples : 512001 (banque), 706001 (appels de fonds), 628000 (charges)
 * 
 * COMPTES TIERS (spécifiques) :
 * - id_copro = [ID de la copro]
 * - id_entite = [ID du fournisseur/copropriétaire/banque]
 * - type_entite = 'fournisseur' | 'coproprietaire' | 'bank'
 * - Exemples : 401003ARKENDIA, 450001LOT1, 512001-2
 */

-- ============================================================================
-- RÈGLE 2 : Création de comptes dans plan_comptable
-- ============================================================================

-- ❌ MAUVAIS (avant) :
-- INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro)
-- VALUES ('706001', 'Appels de fonds', 7, '7', 2);
-- Problème : Crée un compte spécifique à la copro 2

-- ✅ BON (maintenant) :
-- INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro)
-- SELECT '706001', 'Appels de fonds', 7, '7', NULL
-- WHERE NOT EXISTS (SELECT 1 FROM plan_comptable WHERE numero_compte = '706001');
-- Solution : Compte mutualisé, créé une seule fois

-- Pour les comptes tiers (401XXX, 450XXX) :
-- INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
-- VALUES ('401003ARKENDIA', 'Arkendia', 4, '4', :id_copro, :id_fournisseur, 'fournisseur');

-- ============================================================================
-- RÈGLE 3 : Jointures avec plan_comptable
-- ============================================================================

-- ❌ MAUVAIS (avant) :
-- LEFT JOIN plan_comptable p ON l.numero_compte = p.numero_compte 
--     AND p.id_copro = e.id_copro
-- Problème : Ne trouve pas les comptes mutualisés (id_copro = NULL)

-- ✅ BON (maintenant) :
-- LEFT JOIN plan_comptable p ON l.numero_compte = p.numero_compte 
--     AND (p.id_copro IS NULL OR p.id_copro = e.id_copro)
-- Solution : Trouve d'abord les mutualisés, puis les spécifiques si nécessaire

-- ============================================================================
-- RÈGLE 4 : Sécurité et séparation des données
-- ============================================================================

/**
 * TOUJOURS filtrer sur ecritures_comptables.id_copro dans les WHERE
 * 
 * Exemples :
 * - WHERE e.id_copro = :id_copro
 * - AND e.id_copro = :id_copro_session
 * 
 * La sécurité ne doit JAMAIS reposer sur plan_comptable.id_copro
 * car les comptes généraux sont mutualisés.
 */

-- ============================================================================
-- RÈGLE 5 : Procédures SQL (generer_compte_xxx)
-- ============================================================================

/**
 * Les procédures qui génèrent des comptes tiers doivent :
 * 1. Vérifier si le compte existe déjà
 * 2. Créer avec id_copro, id_entite, type_entite
 * 
 * Exemple : generer_compte_fournisseur()
 * - Crée 401XXXNOM pour la copro courante
 * - Avec id_copro = p_id_copro
 * - Avec id_entite = p_id_fournisseur
 * - Avec type_entite = 'fournisseur'
 */

-- Exemple de procédure correcte :
DELIMITER //
CREATE PROCEDURE generer_compte_fournisseur(
    IN p_id_fournisseur INT,
    IN p_id_copro INT,
    OUT p_numero_compte VARCHAR(20)
)
BEGIN
    DECLARE v_numero_base VARCHAR(20);
    DECLARE v_nom VARCHAR(100);
    
    -- Récupérer info fournisseur
    SELECT nom INTO v_nom FROM fournisseurs WHERE id = p_id_fournisseur;
    
    -- Générer numéro de compte
    SET v_numero_base = CONCAT('401', LPAD(p_id_fournisseur, 3, '0'));
    SET p_numero_compte = CONCAT(v_numero_base, UPPER(LEFT(v_nom, 10)));
    
    -- Créer si n'existe pas
    INSERT INTO plan_comptable (
        numero_compte, libelle, type_compte, classe, 
        id_copro, id_entite, type_entite
    )
    SELECT 
        p_numero_compte,
        v_nom,
        4,
        '4',
        p_id_copro,  -- ⚠️ SPÉCIFIQUE à la copro
        p_id_fournisseur,
        'fournisseur'
    WHERE NOT EXISTS (
        SELECT 1 FROM plan_comptable 
        WHERE numero_compte = p_numero_compte 
        AND id_copro = p_id_copro
    );
END//
DELIMITER ;

-- ============================================================================
-- RÈGLE 6 : Migration d'une nouvelle copro
-- ============================================================================

/**
 * Lors de l'ajout d'une nouvelle copro :
 * 1. Ne PAS copier les comptes généraux (ils sont mutualisés)
 * 2. Créer uniquement les comptes tiers spécifiques (banques, copropriétaires)
 * 3. Les comptes fournisseurs seront créés à la volée
 */

-- Script d'initialisation d'une nouvelle copro :
-- 1. Créer le compte banque principal
INSERT INTO plan_comptable (numero_compte, libelle, type_compte, classe, id_copro, id_entite, type_entite)
VALUES (
    CONCAT('512001-', NEW.id), 
    'Compte banque principal',
    5,
    '5',
    NEW.id,  -- Spécifique à cette copro
    NEW.id_bank_account,
    'bank'
);

-- 2. Créer les comptes copropriétaires (un par lot)
-- Cela sera fait par la procédure generer_compte_coproprietaire()

-- 3. C'EST TOUT ! Les comptes généraux sont déjà disponibles.

-- ============================================================================
-- RÈGLE 7 : Vérification de cohérence
-- ============================================================================

-- Requête pour détecter les comptes généraux dupliqués (à éviter) :
SELECT 
    numero_compte,
    COUNT(*) as nb_duplicatas,
    GROUP_CONCAT(id_copro) as copros
FROM plan_comptable
WHERE numero_compte NOT LIKE '401%'
  AND numero_compte NOT LIKE '450%'
  AND numero_compte NOT LIKE '512%'
  AND id_copro IS NOT NULL  -- ⚠️ Ne devrait pas exister !
GROUP BY numero_compte
HAVING COUNT(*) > 1;

-- Si cette requête retourne des résultats, exécuter le script de nettoyage :
-- refactor_plan_comptable_mutualise.sql

-- ============================================================================
-- RÈGLE 8 : Tests à effectuer après modification
-- ============================================================================

/**
 * Checklist de vérification :
 * 
 * 1. ✓ Les comptes généraux ont id_copro = NULL
 * 2. ✓ Les comptes 401XXX, 450XXX ont id_copro spécifique
 * 3. ✓ Le Grand Livre affiche les bons libellés pour tous les comptes
 * 4. ✓ Les écritures d'une copro ne sont visibles que pour cette copro
 * 5. ✓ La création d'un nouvel appel de fonds n'utilise que 706001 mutualisé
 * 6. ✓ La création d'une facture avec nouveau fournisseur crée un 401XXX spécifique
 */

-- Test 1 : Vérifier les comptes mutualisés
SELECT numero_compte, libelle, id_copro
FROM plan_comptable
WHERE numero_compte IN ('706001', '628000', '791000', '512001')
ORDER BY numero_compte;
-- Résultat attendu : id_copro = NULL pour 706001, 628000, 791000

-- Test 2 : Vérifier le Grand Livre
-- Aller sur l'interface Grand Livre, filtrer sur 706001
-- Vérifier que le libellé affiché est "Appels de fonds - charges courantes"
-- et NON "Compte 706001"

-- Test 3 : Vérifier la séparation des copros
SELECT 
    e.id_copro,
    COUNT(*) as nb_ecritures,
    SUM(l.debit) as total_debit,
    SUM(l.credit) as total_credit
FROM lignes_ecritures l
INNER JOIN ecritures_comptables e ON l.id_ecriture = e.id
WHERE l.numero_compte = '706001'
GROUP BY e.id_copro;
-- Doit montrer des totaux différents par copro

-- ============================================================================
-- ANNEXE : Comptes standards mutualisés
-- ============================================================================

/**
 * Liste des comptes qui DOIVENT être mutualisés (id_copro = NULL) :
 * 
 * Classe 1 - Capitaux :
 * - 102000 : Fonds de travaux
 * - 105000 : Réserves
 * 
 * Classe 4 - Tiers (partiellement) :
 * - 400000 : Fournisseurs généraux (sans 401XXX qui sont spécifiques)
 * - 445000 : TVA
 * 
 * Classe 5 - Financier :
 * - 512001 : Compte banque GÉNÉRIQUE (les 512001-X sont spécifiques)
 * - 530000 : Caisse
 * 
 * Classe 6 - Charges :
 * - 606000 : Fournitures
 * - 615000 : Entretien
 * - 622000 : Honoraires
 * - 628000 : Divers
 * 
 * Classe 7 - Produits :
 * - 706001 : Appels de fonds charges courantes
 * - 706002 : Appels de fonds exceptionnels
 * - 791000 : Transferts de charges
 */

-- ============================================================================
-- FIN DU DOCUMENT
-- ============================================================================
