
    Jjm+                     n   d Z ddlZddlZddlZej                            ej                            e                    Zej        	                    de           ddl
ZddlZddlZddlZddddZdZd Zd	 Zd
 Zd Zd Z	 	 d(dZd Zd)dZd Zd Zd)dZd Zedk    r ej                     Z! ee!           e!"                    d          #                                d         Z$ e%d            ee!e$dd          Z& e%de&d         z             e&d         D ]Z' e%de'd         e'd         fz             e&d          D ]@Z(d!)                    d" e(d#         D                       Z* e%d$e(d         d%e*pd&           A e%d' ee!          z             e!+                                 dS dS )*a  
PLANNING TEAM - les demandes de l'equipe.

Trois choses qu'un salarie peut demander depuis sa page :

  * un CONGE          -> devient une absence en CP une fois accepte ;
  * une ABSENCE       -> maladie, evenement familial... decomptee en heures ;
  * un ECHANGE        -> il propose d'echanger une journee avec un collegue.
                         Le collegue doit accepter AVANT que la demande arrive sur le
                         bureau de Jerome : trois etapes, comme dans la vraie vie.

Toute demande est confrontee aux deux regles (un pharmacien en permanence, trois
personnes au comptoir) DES SA CREATION : le salarie voit tout de suite si ce qu'il
demande cree un trou, et peut choisir d'autres dates de lui-meme.
    Nu   Demande de congéu   Signalement d’absenceu   Échange de créneau)congeabsenceechangea  
CREATE TABLE IF NOT EXISTS demande (
    id              INTEGER PRIMARY KEY,
    type            TEXT NOT NULL,
    salarie_id      INTEGER NOT NULL REFERENCES salarie(id) ON DELETE CASCADE,
    date_debut      TEXT NOT NULL,
    date_fin        TEXT NOT NULL,
    motif           TEXT,          -- motif d'absence : cp, maladie, formation...
    commentaire     TEXT,          -- le mot du salarie
    collegue_id     INTEGER REFERENCES salarie(id) ON DELETE SET NULL,
    statut_collegue TEXT,          -- attente | accepte | refuse   (echanges)
    statut          TEXT NOT NULL DEFAULT 'attente',  -- attente | acceptee | refusee
    reponse         TEXT,          -- motif du refus, facultatif
    traite_par      TEXT,
    absence_id      INTEGER,
    cree_le         TEXT NOT NULL,
    traite_le       TEXT
);

CREATE INDEX IF NOT EXISTS idx_demande_statut ON demande (statut, cree_le);
c                     t          j        | d          rd S |                     t                     |                                  d S )N)demande)cgtables_completesexecutescriptSCHEMAcommitcxs    &/opt/planning-team/travail/demandes.pycreer_schemar   ;   sA    	2|,, VIIKKKKK    c                  f    t           j                                                             d          S )Nseconds)timespec)datetimenow	isoformat r   r   _maintenantr   B   s(      "",,i,@@@r   c                    i }t                      }|}||k    rt          j        |          \  }}||f|vr}|                    ||f           t	          j        | ||          }t          |d                   D ]:\  }	}
t          d |d         |	dz            D                       }|r|||
d         <   ;|t          j	        d          z  }||k    |S )z8{ date : nombre de creneaux en alerte } sur une periode.joursc              3   :   K   | ]}|d          s|d         dV  dS )sous_effectifmanque_pharmacien   Nr   ).0ps     r   	<genexpr>z#_alertes_periode.<locals>.<genexpr>S   sW       I Ia_-I123F1GI I I I I I Ir   presencer   date)
setcal
semaine_deaddreelsemaine	enumeratesumr   	timedelta)r   debutfinresultatvuesjour	annee_isonumerobloci	jour_blocns               r   _alertes_perioder9   H   s	   H55DD
#++N400	6vd**HHi()))<Iv66D )$w- 8 8 4 49 I I4
#3AE#: I I I I I 423HYv./"1%%% #++ Or   c                 d   t           j                            |          }t           j                            |          }t          j        |            t          j        |            t	          |            t          | ||          }	 |                     d||                                |                                t                      f           t          | ||          }t          | ||||          }|                                  n# |                                  w xY wi }	|                                D ])\  }
}||                    |
d          z
  }|dk    r||	|
<   *t          |	                                          d t!          |	                                          D             |dS )a$  
    Ce que couterait cette absence si elle etait accordee : les creneaux qui
    passeraient en alerte, et qui pourrait couvrir.

    On simule vraiment : l'absence est inseree, on recalcule, puis on annule. Le
    resultat est donc exactement ce qui se produira, pas une approximation.
    zINSERT INTO absence
                 (salarie_id, date_debut, date_fin, motif, decompte, statut,
                  origine, cree_le)
               VALUES (?, ?, ?, 'cp', 'cp', 'validee', 'simulation', ?)r   c                     g | ]
\  }}||d S ))r$   creneauxr   )r    dr8   s      r   
<listcomp>zimpact.<locals>.<listcomp>   s$    RRRA1!,,RRRr   )creneaux_en_alerter   remplacants)r   r$   fromisoformatr   r   r)   r9   executer   r   _remplacants_perioderollbackitemsgetr,   valuessorted)r   
salarie_id
date_debutdate_finr.   r/   avantapresr@   nouveauxr$   r8   ecarts                r   impactrP   [   s    M''
33E
-
%
%h
/
/C OBbR,,E



K **CMMOO[]]K	M 	M 	M !UC00*2uc5%HH
H;;== # #aEIIdA&&&199"HTN "(//"3"344RR@P@P9Q9QRRR"  s   A.D D!c                    g t                      }}|}||k    rt          j        |          \  }}	||	f|vr|                    ||	f           t	          j        | ||	          }
|
d         D ]Q}|                    |d         d          |                    |d         d          k    r|                    |           R|t          j	        d          z  }||k    |S )z9Les remplacants proposes pour les jours qui se degradent.r@   r$   r   r   )
r%   r&   r'   r(   r)   r*   rF   appendr   r-   )r   r.   r/   rL   rM   propositionsr1   r2   r3   r4   r5   rs               r   rC   rC      s    SUU$LD
#++N400	6vd**HHi()))<Iv66D-( + +99QvY**UYYqy!-D-DDD ''***"1%%% #++ r   c                 "   t          |            |t          vrt          d|z            |dk    r|st          d          t          j                            |          }t          j                            |          }	|	|k     rt          d          |                     d|||                                |	                                |p	|dk    rdnd|||dk    rd	ndt                      f	          }
| 	                                 |
j
        S )
zCEnregistre une demande, avec son impact calcule au moment du depot.ztype de demande inconnu : %sr   u'   un échange doit désigner un collègueu*   la date de fin précède la date de débutzINSERT INTO demande
             (type, salarie_id, date_debut, date_fin, motif, commentaire,
              collegue_id, statut_collegue, statut, cree_le)
           VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'attente', ?)r   cpNattente)r   TYPES
ValueErrorr   r$   rA   rB   r   r   r   	lastrowid)r   type_demanderI   rJ   rK   motifcommentairecollegue_idr.   r/   curs              r   deposerr`      s    5  8<GHHHy   IJJJM''
33E
-
%
%h
/
/C
U{{LMMM
**	< 
z5??#4#4cmmoo		=<72244{	<9#<#<ii$		 C IIKKK=r   c                 *   t          | |          }||d         dk    rt          d          |                     d|rdnd|f           |s%|                     dd	t                      |f           |                                  t          | |          S )
zKLe collegue accepte ou refuse un echange. Sans son accord, rien ne remonte.Ntyper   u%   cette demande n’est pas un échangez3UPDATE demande SET statut_collegue = ? WHERE id = ?accepterefusez^UPDATE demande SET statut = 'refusee', reponse = ?, traite_le = ?
                WHERE id = ?u   refusé par le collègue)unerY   rB   r   r   )r   
demande_idrc   r=   s       r   repondre_colleguerg      s    B
AyAfI**CDDDJJD$2		(J?A A A J


 ,kmmZH	J 	J 	J IIKKKr:r   c           
      8   t          | |          }|t          d          |d         dk    rt          d          |d         dk    r|d         d	k    rt          d
          d}|r|d         dv rt          j        | |d         |d         |d         |d         pd|d         pddk    rdnd|d                   }|d         pddk    rt	          j        | |d         t          j                            |d                   t          j                            |d                             d         }| 	                    d||f           | 	                    d|rdnd||t                      ||f           |                                  t          | |          S )z
    Jerome ou Aurore tranche. Une demande acceptee devient immediatement une
    absence reelle, decomptee selon son motif.
    Nzdemande introuvablestatutrW   u%   cette demande a déjà été traitéerb   r   statut_colleguerc   u3   le collègue n’a pas encore accepté cet échange)r   r   rI   rJ   rK   r\   rV   heuresr]   )decomptelibellez*UPDATE absence SET heures = ? WHERE id = ?zUPDATE demande
              SET statut = ?, reponse = ?, traite_par = ?, traite_le = ?, absence_id = ?
            WHERE id = ?accepteerefusee)re   rY   r   poser_absencer)   heures_prevuesr   r$   rA   rB   r   r   )r   rf   rc   reponseparr=   
absence_idrk   s           r   repondreru      s   
 	B
Ay/000{iKLLLyI!$5"6)"C"CUVVVJ -1V9 444%,<!J-gJ$j0DT99TTxm$	& & &

 gJ$4''(AlO++AlO<<++AjM::< < =EFF JJC
+- - - JJ	 	-Iw[]]	Z	!	" " " IIKKKr:r   c                 \    |                      d|f           |                                  d S )Nz DELETE FROM demande WHERE id = ?)rB   r   )r   rf   s     r   	supprimerrw      s*    JJ1J=AAAIIKKKKKr   c                 z    |                      d|f                                          }|rt          |          nd S )Nz"SELECT * FROM demande WHERE id = ?)rB   fetchonedict)r   rf   ls      r   re   re      s9    


7*GGPPRRA!4777T!r   c                    t          |            dgg }}|r*|                    d           |                    |           |r,|                    d           |                    ||g           |                     dd                    |          z  |                                          }g }|D ]P}t          |          }t                              |d         |d                   |d<   |                    |           Q|S )zDLes demandes, les plus recentes d'abord, avec les noms deja resolus.z1 = 1zd.statut = ?z'(d.salarie_id = ? OR d.collegue_id = ?)ai  SELECT d.*,
                  s.prenom AS prenom, s.initiale AS initiale, s.couleur AS couleur,
                  c.prenom AS prenom_collegue
             FROM demande d
             JOIN salarie s ON s.id = d.salarie_id
             LEFT JOIN salarie c ON c.id = d.collegue_id
            WHERE %s
            ORDER BY d.statut = 'attente' DESC, d.cree_le DESCz AND rb   libelle_type)	r   rR   extendrB   joinfetchallrz   rX   rF   )	r   ri   rI   
conditionsparamslignesr0   r{   r5   s	            r   lister      s   !BJ .)))f 0CDDDz:.///ZZ	B ,,z
"
"	# %+	, 	, -5HJJ  H  Aww$yyftF|DD^Or   c                 z    t          |            |                     d                                          d         S )zICombien de demandes attendent une reponse - pour la pastille de l'onglet.zSELECT COUNT(*) AS n FROM demande
            WHERE statut = 'attente'
              AND (type <> 'echange' OR statut_collegue = 'accepte')r8   )r   rB   ry   r   s    r   
en_attenter     sE    ::	HI I JRTWY Yr   __main__z,SELECT id FROM salarie WHERE initiale = 'Sa'idu5   Impact d’un congé de Sariaka du 07 au 12/09/2026 :z
2026-09-07z
2026-09-12u&     %d créneau(x) passeraient en alerter?   r   z    %s : %dr$   r<   r@   z, c              #   &   K   | ]}|d          V  dS )prenomNr   )r    cs     r   r"   r"   %  s&      ==8======r   	candidatsu       remplaçants le z : aucunz
Demandes en attente : %d)NNN)NN),__doc__r   ossyspathdirnameabspath__file__BASEinsertbasebd
calendrierr&   congesr   r)   rX   r   r   r   r9   rP   rC   r`   rg   ru   rw   re   r   r   __name__	connexionr   rB   ry   sidprintr6   jrT   r   nomscloser   r   r   <module>r      s      				 



	wrwx0011 4                 &)*	 	
.  A A A  &( ( (V  $ GK*.   6   # # # #L  
" " "
   <Y Y Y z	BL
**C
D
D
M
M
O
OPT
UC	E
DEEEr3l33A	E
5:N8O
OPPPwZ ; ;n&	1Z=99::::} P Pyy==an=====!F)))T=MX=MNOOOO	E
'**R..
8999HHJJJJJ r   