
    Jj|{                     J   d Z ddlZddlZddlZddlmc mZ ej        	                    ej        
                    e                    Zej        	                    e          Zej                            ed          Zej                            edd          ZdZg dZdd	gdd	gdd	gdd	gdd	gdd
gdZdZdZdZdhZdZdZg dZg dZdZdZd Zd Zg ddgdgdZ d Z!d Z"d Z#d Z$d Z%d  Z&d! Z'd" Z(d# Z)d$ Z*d% Z+d;d&Z,d<d(Z-d) Z.d* Z/d+ Z0d, Z1d- Z2d. Z3d/ Z4d0 Z5d1 Z6d2 Z7d3 Z8d4 Z9d5 Z:d6 Z;d7 Z<e=d8k    rhddl>Z> e            Z? e@e>jA                  d9k    re>jA        d9         d:k    r e,e?            eB e<e?                     e?C                                 dS dS )=a  
PLANNING TEAM - base de donnees et calculs.

Tout tient dans un fichier SQLite (travail/planning.db) : sauvegarde = copie du fichier.
Aucune dependance externe : sqlite3, zipfile et xml.etree sont dans la bibliotheque standard.

Le cycle de reference fait 2 semaines (S1 = semaines ISO impaires, S2 = paires). Il se
reconduit indefiniment ; le quotidien consiste a poser des exceptions par-dessus (lot 2).
    Nzplanning.dbdocsz@Emploi du temps BASE SEPTEMBRE 2026 planning sur 2 semaines.xlsxz;{http://schemas.openxmlformats.org/spreadsheetml/2006/main})lundimardimercredijeudivendredisamedi)  i  )H    )r   iV  )                  r
   r   
pharmacien
rayonnister   T))AAuroreLabroyr   g      @@z
2014-04-09Pharmaciensz#5271E0)NNicolasCouer        A@z
2018-01-02r   z#E5A33C)SaSariakaRakotoanadahyr   r   z
2024-01-01r   z#9C8F5B)MCzMarie-Cecile	Bartheletr   g      ;@z
2022-01-24r   z#6F9450)VValerieChantemessepreparateurr   z
2005-03-01Preparateursz#C75CAE)EElodieLescovecr%   r   z
2017-01-11r&   z#3CB3D4)G
GwendolineVenetr%         <@z
2023-09-18r&   z#E8814A)St	StephaniePassotr%   r   z
2025-01-06r&   z#9DBB5E)TThomasJametr%   r   z
2021-09-13r&   z#D9564F)CChloeConstantapprentig      2@z
2025-09-01	Apprentiez#8D6E4F)PPatriciazPognant-Grosr   r-   z
2016-06-08
Rayonnistez#8659BE)MManon	ChevalieretudiantNz
2023-09-09
Etudiantes#3EA895)LLilou r?   Nz
2026-09-01r@   rA   )r   r&   r8   r;   r@   )JJerome	Cuvillier	titulaireNN	Directionz#1F6763u!  
CREATE TABLE IF NOT EXISTS salarie (
    id              INTEGER PRIMARY KEY,
    initiale        TEXT NOT NULL UNIQUE,
    prenom          TEXT NOT NULL,
    nom             TEXT NOT NULL DEFAULT '',
    fonction        TEXT NOT NULL,
    groupe          TEXT NOT NULL,
    groupe_rang     INTEGER NOT NULL DEFAULT 0,
    couleur         TEXT NOT NULL DEFAULT '#5A5B5D',
    contrat_h_moyen REAL,
    date_entree     TEXT,
    paye_a_l_heure  INTEGER NOT NULL DEFAULT 0,
    ordre           INTEGER NOT NULL DEFAULT 0,
    actif           INTEGER NOT NULL DEFAULT 1,
    hors_planning   INTEGER NOT NULL DEFAULT 0
);

CREATE TABLE IF NOT EXISTS creneau_type (
    id            INTEGER PRIMARY KEY,
    salarie_id    INTEGER NOT NULL REFERENCES salarie(id) ON DELETE CASCADE,
    semaine_cycle INTEGER NOT NULL CHECK (semaine_cycle IN (1, 2)),
    jour          INTEGER NOT NULL CHECK (jour BETWEEN 1 AND 6),
    debut_min     INTEGER NOT NULL,
    fin_min       INTEGER NOT NULL,
    hors_comptoir INTEGER NOT NULL DEFAULT 0,
    ajpp          INTEGER NOT NULL DEFAULT 0,
    CHECK (fin_min > debut_min)
);

-- Copie figee du cycle tel qu'il sort du classeur. Elle ne bouge qu'a l'import et sert
-- au bouton « revenir a l'emploi du temps de base », ligne par ligne.
CREATE TABLE IF NOT EXISTS creneau_base (
    id            INTEGER PRIMARY KEY,
    salarie_id    INTEGER NOT NULL,
    semaine_cycle INTEGER NOT NULL,
    jour          INTEGER NOT NULL,
    debut_min     INTEGER NOT NULL,
    fin_min       INTEGER NOT NULL,
    hors_comptoir INTEGER NOT NULL DEFAULT 0,
    ajpp          INTEGER NOT NULL DEFAULT 0
);

CREATE INDEX IF NOT EXISTS idx_creneau_cycle
    ON creneau_type (semaine_cycle, jour, salarie_id);
CREATE INDEX IF NOT EXISTS idx_base_cycle
    ON creneau_base (semaine_cycle, jour, salarie_id);
c                      t          j        t                    } t           j        | _        |                     d           | S )NzPRAGMA foreign_keys = ON)sqlite3connect	CHEMIN_DBRowrow_factoryexecutecxs    "/opt/planning-team/travail/base.py	connexionrT      s2    		#	#B[BNJJ)***I    c                     |                      t                     t          |            |                                  d S N)executescriptSCHEMA_migrercommitrQ   s    rS   creer_schemar\      s2    VBKKKIIKKKKKrU   ))groupezTEXT NOT NULL DEFAULT '')groupe_rangINTEGER NOT NULL DEFAULT 0)couleurzTEXT NOT NULL DEFAULT '#5A5B5D')hors_planningr_   )ajppr_   )salariecreneau_typecreneau_basec                 F    d |                      d|z            D             S )Nc                     h | ]
}|d          S )r    .0ls     rS   	<setcomp>z_colonnes.<locals>.<setcomp>   s    FFFQAaDFFFrU   zPRAGMA table_info(%s))rP   )rR   tables     rS   	_colonnesrn      s(    FF"**%<u%DEEFFFFrU   c           
          t                                           D ]B\  }}t          | |          }|s|D ]'\  }}||vr|                     d|d|d|           (Cd S )NzALTER TABLE z ADD COLUMN  )
MIGRATIONSitemsrn   rP   )rR   rm   colonnes
existantesnom
definitions         rS   rZ   rZ      s    %++-- Y Yxr5))
 	' 	Y 	YOC*$$


sssJJWXXX	Y	Y YrU   c                 R   g }|                      d          5 }t          j        |                                          D ]O}|                    d                    d |                    t          dz             D                                  P	 d d d            n# 1 swxY w Y   |S )Nzxl/sharedStrings.xmlrD   c              3   (   K   | ]}|j         pd V  dS )rD   N)text)rj   ts     rS   	<genexpr>z%_chaines_partagees.<locals>.<genexpr>   s(      "K"KA16<R"K"K"K"K"K"KrU   rz   )openETparsegetrootappendjoiniterNS)zfchainesfsis       rS   _chaines_partageesr      s    G	'	(	( MA(1++%%'' 	M 	MBNN277"K"Kc9J9J"K"K"KKKLLLL	MM M M M M M M M M M M M M M M Ns   A7BB #B c                    |                      d          5 }d t          j        |                                                              t
          dz             D             }d d d            n# 1 swxY w Y   ||vr)t          d|dd                    |          d          d|                    |          d	z   z  S )
Nzxl/workbook.xmlc                 8    g | ]}|                     d           S )namegetrj   ss     rS   
<listcomp>z_feuille.<locals>.<listcomp>   s"    PPP!fPPPrU   sheetzFeuille introuvable : z (feuilles : , )zxl/worksheets/sheet%d.xmlr   )	r|   r}   r~   r   r   r   
ValueErrorr   index)r   nom_chercher   nomss       rS   _feuiller      s   	"	#	# QqPPrx{{':':'<'<'A'A"w,'O'OPPPQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q$j'KK4: ; ; 	;&$**[*A*AA*EFFs   AA..A25A2c                    |                      d          5 }t          j        |                                          }ddd           n# 1 swxY w Y   g }|                    t
          dz             D ]Z}|                    t
          dz             }|                    t          |duo|                    d          dv                     [t                      }t          |                    t
          dz                       D ]C\  }}|t          |                    dd	                             r|                    |           D|S )
zKL'ensemble des index de style dont la cellule porte un remplissage visible.zxl/styles.xmlNfillspatternFillpatternType)Nnonegray125cellXfsfillIdr   )r|   r}   r~   r   findr   r   boolr   set	enumerateintadd)	r   r   racineremplisfillmotifresultatixfs	            rS   _styles_remplisr      sz   		!	! 'Q!$$&&' ' ' ' ' ' ' ' ' ' ' ' ' ' ' GBL)) \ \		"},--tE- Z %		- 8 8@Y Y[ [ 	\ 	\ 	\ 	\ uuH6;;rI~6677  23rvvh**++, 	LLOOOOs   'A		AAc                 d   i }|                      |          5 }t          j        |                                                              t
          dz             D ]}|                    t
          dz             }||j        )|                    d          dk    r|t          |j                           n|j        }|pd
                                }|rB|                    d          }	||	duot          |	          |v f||                    d          <   	 ddd           n# 1 swxY w Y   |S )z?{ 'C4': (valeur, remplie) } pour toutes les cellules non vides.cvNrz   r   rD   r)r|   r}   r~   r   r   r   r   ry   r   r   strip)
r   cheminr   styles_remplisvaleursr   r   r   textestyles
             rS   	_cellulesr      sm   G	 
[A!$$&&++BH55 		[ 		[ArCx  AyAFN,-EE#JJ#,=,=GCKK((16E[b''))E [c

',',D'8'YSZZ>=Y'[c

#		[
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ 
[ Ns   D D%%D),D)c                 D    d}| D ]}|dz  t          |          dz
  z   }|S )Nr      @   )ord)lettresnchs      rS   _num_colonner      s5    	A $ $Fc"ggl#HrU   c                 x    d}| dk    r1t          | dz
  d          \  } }t          d|z             |z   }| dk    1|S )NrD   r   r   r   A   )divmodchr)r   r   r   s      rS   _lettres_colonner      sL    
A
a%%a!eR  1QKK!O a%% HrU   c           	      z   t          j        |           5 }t          |          }t          |t	          ||          |t          |                    }ddd           n# 1 swxY w Y   t          d          t          d          }}i }t          ||dz             D ]}t          |          }	|	                    |	dz             }
|
s,|
d         ||z
  dz  dz   }}t          dd	          D ]N}|	                    d
|	|fz            }|r0|d         |
                    |
d         |fi           d|dz
  dz  z   <   O|S )u  
    Lit une feuille du planning de base.

    La grille couvre les colonnes C a BP : six groupes de onze colonnes, un par jour,
    la ligne 2 donnant l'initiale de chaque colonne. Les lignes 4 a 25 sont les
    demi-heures de 8h30 a 19h30.

    Le remplissage de fond marque les heures d'AJPP (verifie sur Elodie : mardi et
    jeudi en S1, jeudi en S2, soit 17 h et 8,5 h — exactement l'ecart annonce entre
    « 35 h » et « 18 h / 26,5 h sans AJPP »).

    Renvoie { (initiale, jour) : { minute : ajpp } }
    Nr4   BPr   2r      r   r   z%s%dr
      )zipfileZipFiler   r   r   r   r   ranger   r   
setdefault)chemin_xlsxnom_feuiller   r   cellpremieredernieregriller   colenteteinitialejourlignecases                  rS   lire_griller     s    
	%	% V$R((Xb+66QSATATUUV V V V V V V V V V V V V V V &c**L,>,>hHF8X\** 	[ 	[q!!#)$$ 	Q\b$81$<$1b\\ 	[ 	[E88Fc5\122D [SWXYSZ!!6!9d"3R88	R?O9OP	[ Ms   =AA"%A"c                 H   g }t          |           D ]}| |         rdnd}t          ||          rdnd}|rE|d         d         |k    r3|d         d         |k    r!|d         d         |k    r|dz   |d         d<   i|                    ||dz   ||g           d |D             S )z
    Transforme { minute : ajpp } en plages continues (debut, fin, hors_comptoir, ajpp).
    Deux demi-heures ne sont recollees que si elles partagent le meme statut.
    r   r   r   r   r   c                 ,    g | ]}t          |          S rh   tuple)rj   ms     rS   r   z_plages.<locals>.<listcomp>3  s    '''E!HH'''rU   )sorted_dans_ouverturer   )minutes_ajppr   morceauxminuterb   horss         rS   _plagesr   %  s    
 H&& ? ? (/qqa#D&118qqq 	?"aF22RLOt++Q40G0G$rkHRLOOOOVVb[$=>>>>''h''''rU   c                 P    t          fdt          |          D                       S )Nc              3   >   K   | ]\  }}|cxk    o|k     nc V  d S rW   rh   )rj   debutfinr   s      rS   r{   z"_dans_ouverture.<locals>.<genexpr>7  sC      GGu$$$$$$$$GGGGGGrU   )any	OUVERTURE)r   r   s    `rS   r   r   6  s*    GGGGyGGGGGGrU   c                    |pt           }t          |            |                     d           |                     d           d |                     d          D             }t          t                    D ]{\  }}|\  }}}}	}
}}}|||	|t
                              |          ||
||
dnd|f
}||v r|                     d||fz              W|                     d	||fz             }|j        ||<   |t          \  }}}}	}}}}||v r|                     d
|||	|||f           n:|                     d||||	|t          t
                    |df          }|j        ||<   d t          D             t          d         gz   }|                     dd
                    dt          |          z            z  |           ddt                      }}}dD ]\  }}t          ||                                          D ]|\  \  }}}|                    |          }||                    |           5t!          ||          D ]6\  }}}}|                     d|||||||f           |dz  }|r|||z
  dz  z  }7}|                     d           |                                  |r[t%          dt          t                    ||fz             |r2t%          dd
                    t'          |                    z             |S )z8(Re)construit la base a partir du classeur de reference.zDELETE FROM creneau_typezDELETE FROM creneau_basec                 ,    i | ]}|d          |d         S )r   idrh   ri   s     rS   
<dictcomp>zimporter.<locals>.<dictcomp>M  s8     M M M jM1T7 M M MrU   z SELECT id, initiale FROM salarieNr   r   a  UPDATE salarie
                      SET prenom = ?, nom = ?, fonction = ?, groupe = ?, groupe_rang = ?,
                          couleur = ?, contrat_h_moyen = ?, date_entree = ?,
                          paye_a_l_heure = ?, ordre = ?, actif = 1
                    WHERE initiale = ?zINSERT INTO salarie
                     (prenom, nom, fonction, groupe, groupe_rang, couleur,
                      contrat_h_moyen, date_entree, paye_a_l_heure, ordre, initiale)
                   VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)zUPDATE salarie SET prenom = ?, nom = ?, fonction = ?, groupe = ?,
                             couleur = ?, hors_planning = 1, actif = 1
                       WHERE initiale = ?zINSERT INTO salarie (initiale, prenom, nom, fonction, groupe,
                                    groupe_rang, couleur, ordre, hors_planning)
               VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)c   c                     g | ]
}|d          S )r   rh   ri   s     rS   r   zimporter.<locals>.<listcomp>t  s    %%%qad%%%rU   z7UPDATE salarie SET actif = 0 WHERE initiale NOT IN (%s),?))r   u   S1 (Gwen à 80%))r   u   S2 (Gwen à 80%)zINSERT INTO creneau_type
                         (salarie_id, semaine_cycle, jour, debut_min, fin_min,
                          hors_comptoir, ajpp)
                       VALUES (?, ?, ?, ?, ?, ?, ?)      N@zINSERT INTO creneau_base
             (salarie_id, semaine_cycle, jour, debut_min, fin_min, hors_comptoir, ajpp)
           SELECT salarie_id, semaine_cycle, jour, debut_min, fin_min, hors_comptoir, ajpp
             FROM creneau_typez9Import termine : %d salaries, %d creneaux, %.1f h d'AJPP.z-Initiales du classeur sans salarie connu : %sr   )CLASSEURr\   rP   r   EFFECTIFGROUPESr   	lastrowid	TITULAIRElenr   r   r   rr   r   r   r   r[   printr   )rR   r   bavardpar_initialeordrer   r   prenomru   fonctioncontratentreer]   r`   champscur_connustotal
ajpp_totalignoressemainefeuiller   minutessidr   r   r   rb   s                                 rS   importerr  <  s   )K JJ)***JJ)***M MZZ(JKKM M ML "(++ 3 3uLQI&#x&&'#xv1F1F611QG|##JJ* ,2XK+?A A A A **? AG(@T	V VC
 &)]L"" >G:Hfc8Q67<


 - C67HE	G 	G 	G 	G
 jj5 vsHfc'llGRP	R R
 "%X &%H%%%16FJJH#F+,,-.46 6 6 "#Asuuw:ET 7 7)4[')J)J)P)P)R)R 	7 	7%Xtg""8,,C{H%%%*1'4*@*@ 	7 	7&sD$

7 '4T4@B B B 
 73;$"66J	7	7  JJ	"# # #
 IIKKK 0KXz23 	4 	4 	4 	0BIIfWoo../ 0 0 0LrU   Fc                 z    |rdnd}|                      d|z                                            }d |D             S )z
    Les gens du planning. Le titulaire en est exclu : il a un compte, pas de creneaux.
    `tous=True` le ramene, pour la gestion des acces.
    z	actif = 1zactif = 1 AND hors_planning = 0zSELECT id, initiale, prenom, nom, fonction, groupe, groupe_rang, couleur,
                  contrat_h_moyen, date_entree, paye_a_l_heure, hors_planning
             FROM salarie WHERE %s
            ORDER BY groupe_rang, ordrec                 ,    g | ]}t          |          S rh   dictri   s     rS   r   zsalaries.<locals>.<listcomp>      $$$DGG$$$rU   rP   fetchall)rR   tous	conditionligness       rS   salariesr    sZ    
  $J)JIZZ	+ .7	78 8 9A

	 
 %$V$$$$rU   c                 l    |                      d|f                                          }d |D             S )NzSELECT id, salarie_id, jour, debut_min, fin_min, hors_comptoir, ajpp
             FROM creneau_type WHERE semaine_cycle = ?
            ORDER BY jour, debut_minc                 ,    g | ]}t          |          S rh   r  ri   s     rS   r   zcreneaux.<locals>.<listcomp>  r  rU   r  )rR   semaine_cycler  s      rS   creneauxr!    sE    ZZ	(*7)9; ; <D8::  %$V$$$$rU   c                     i }|                      d          D ];}|d         dz  |d         dz  f|                    |d         i           |d         <   <|S )z4{ salarie_id: {1: (total, ajpp), 2: (total, ajpp)} }a   SELECT salarie_id, semaine_cycle,
                      SUM(fin_min - debut_min) AS minutes,
                      SUM(CASE WHEN ajpp THEN fin_min - debut_min ELSE 0 END) AS minutes_ajpp
                 FROM creneau_type GROUP BY salarie_id, semaine_cycler  r   r   
salarie_idr   )rP   r   )rR   r   rk   s      rS   heures_par_semainer$    st    HZZIJ J ; ; iL4>!2T!9H;AlOR00?1CDDOrU   c                  R    t          t          t          t          d                    S )zGLes 22 demi-heures affichees, 8h30 -> 19h30, communes a tous les jours.r   )listr   GRILLE_DEBUT
GRILLE_FINrh   rU   rS   creneaux_griller)    s    lJ33444rU   c                 x    g }t           |          D ])\  }}|                    t          ||d                     *|S )z5Les demi-heures ou l'officine est ouverte ce jour-la.r   )r   extendr   )r   pasr   r   s       rS   creneaux_ouverturer-    sD    
Co * *
s

5R(())))JrU   c                 8    t          |           }|r|d         ndS )zILa derniere demi-heure d'ouverture, toleree sous le seuil de 3 personnes.r   N)r-  )r   r,  s     rS   derniere_demi_heurer/    s"    
T
"
"C#3r77t#rU   c                 \   t          |           }d |D             d |D             i }t          | |          D ]b}|d         rt          |d         |d         d          D ]9}|                    |d         |fg                               |d                    :ci }t          d	d
          D ]}t          t          |                    }t          |          }	g }
t                      D ]}||v }|	                    ||fg           }t          fd|D                       }fd|D             }|
                    ||fd|D             t          |          t          |          ||o|dk    |o%t          |          t          k     ot          o||	k     d           |
||<   |S )z
    Pour chaque demi-heure d'ouverture : qui tient le comptoir, combien, combien de
    pharmaciens, et si une regle est enfreinte.
    c                 ,    i | ]}|d          |d         S )r   r  rh   r   s     rS   r   zpresence.<locals>.<dictcomp>  "    666A4!J-666rU   c                 ,    i | ]}|d          |d         S )r   r   rh   r   s     rS   r   zpresence.<locals>.<dictcomp>  r2  rU   hors_comptoir	debut_minfin_minr   r   r#  r      c              3   X   K   | ]$}                     |          t          k     d V  %dS )r   N)r   PHARMACIENSrj   r   	fonctionss     rS   r{   zpresence.<locals>.<genexpr>  s9       S Sq9==3C3C{3R3R3R3R3R3R S SrU   c                 L    g | ] }                     |          t          v|!S rh   )r   HORS_COMPTOIRr:  s     rS   r   zpresence.<locals>.<listcomp>  s/    SSSY]]1-=-=]-R-R1-R-R-RrU   c                      g | ]
}|         S rh   rh   )rj   r   	initialess     rS   r   zpresence.<locals>.<listcomp>  s    888qil888rU   r   )r   ouvertr?  nbcomptoirpharmaciensmanque_pharmaciensous_effectif)r  r!  r   r   r   r   r-  r/  r)  r   sumr   MINI_COMPTOIRDERNIERE_DEMI_HEURE)rR   r   gensoccuper   r   r   r   ouvertsr   jour_resultatr@  idsnb_pharmaciensau_comptoirr;  r?  s                  @@rS   presencerP    s'   
 B<<D66666I66666IFb-(( O O_ 	AkNAiL"== 	O 	OFqy&1266==aoNNNN	O Ha ' '(..//&t,,%'' 	 	Fw&F**dF^R00C  S S S SC S S SSSNSSSScSSSK    8888C888#hh,,- &,%C!0C"( #WS-=-=-M #W+>+U6XCU&V" "     'OrU   c                 V   t          |           }i }|                     d          D ]C}|                    |d         t                                                    |d                    Dg }t          |           D ]+}|                    |d         i           }|                    dd          \  }}|                    dd          \  }	}
||	z   dz  }|d	         }|                    |d         |d
         |d         |d         |d         |d         |t          |d          t          |	d          t          |d          |dnt          ||z
  d          t          |d          t          |
d          t          |                    |d         g                     d           -|S )zOPar salarie : heures S1, S2, moyenne du cycle, ecart au contrat, AJPP, samedis.ztSELECT salarie_id, semaine_cycle FROM creneau_type
                WHERE jour = 6 GROUP BY salarie_id, semaine_cycler#  r   r   r   )        rR  r   g       @contrat_h_moyenr   r  r  r]   r`   N)r#  r   r  r  r]   r`   r  s1s2moyenneecartajpp_s1ajpp_s2samedis)
r$  rP   r   r   r   r  r   r   roundr   )rR   heuresrZ  rk   r   r   hh1a1h2a2rV  r  s                rS   	compteursrb    s   ##FGZZEF F K K 	1\?CEE2266q7IJJJJHb\\  JJqw##q*%%Bq*%%B7c/%&D'*k*k|A,,A,,Wa(($_TT%'8I12M2MR||R||gkk!D'26677
 
 	 	 	 	  OrU   c           
      p   |                      d|||||f                                          }|r|                      d|d         f           |d         |k     r!t          | ||||d         ||d                    |dz   |d         k     r$t          | ||||dz   |d         |d                    |                                  dS |                      d	|||f                                          d
         }t          | |||||dz   |rdnd           t	          | |||           |                                  dS )z
    Ajoute ou retire une demi-heure, puis refusionne les plages contigues de meme
    statut. Renvoie True si la demi-heure est desormais travaillee.
    zSELECT id, debut_min, fin_min, ajpp FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?
              AND debut_min <= ? AND fin_min > ?%DELETE FROM creneau_type WHERE id = ?r   r5  rb   r   r6  FznSELECT MIN(ajpp) AS tous FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?r  r   r   T)rP   fetchone_insererr[   
_fusionner)rR   r#  r   r   r   r   	jour_ajpps          rS   basculer_creneauri  "  s   
 JJ	4 
]D&&9	; ; <D8::	 
  	


:U4[NKKK&&R]D;'v@ @ @B;y)))R]Db[%	"2E&MC C C
		u
 

	G	]D)+ + ,48::f>I
 R]D&&2+"QQ$ $ $r:}d333IIKKK4rU   c                    |                      d|||f                                          }|sdS t          d |D                       rdnd}|                      d||||f           t          | |||           |                                  |S )u   
    Marque ou demarque une JOURNEE entiere en AJPP.

    L'AJPP se compte en jours, pas en creneaux : le cabinet attend « Lu 24/08 +
    Je 27/08, 2 jours, 17,5 h ». On bascule donc tout ce que la personne travaille
    ce jour-la, d'un coup.
    zeSELECT id, ajpp FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?Nc              3   &   K   | ]}|d          V  dS )rb   Nrh   ri   s     rS   r{   z basculer_ajpp.<locals>.<genexpr>U  s&      11Qqy111111rU   r   r   zdUPDATE creneau_type SET ajpp = ?
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?)rP   r  allrg  r[   )rR   r#  r   r   r  nouveaus         rS   basculer_ajpprn  G  s     ZZ	G	]D)+ + ,48::   t11&111118aaqGJJ	G	*mT24 4 4 r:}d333IIKKKNrU   c                    |                      d|||f                                          }|                      d|||f                                          }|                      d|||f           |D ]7}|                      d||||d         |d         |d         |d         f           8|                                  d	 |D             d
 |D             k    S )u   
    Remet une ligne — une personne, un jour — telle qu'elle sort du classeur.
    Renvoie True si quelque chose a change.
    zSELECT debut_min, fin_min, hors_comptoir, ajpp FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ? ORDER BY debut_minzSELECT debut_min, fin_min, hors_comptoir, ajpp FROM creneau_base
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ? ORDER BY debut_minz\DELETE FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?INSERT INTO creneau_type
                 (salarie_id, semaine_cycle, jour, debut_min, fin_min, hors_comptoir, ajpp)
               VALUES (?, ?, ?, ?, ?, ?, ?)r5  r6  r4  rb   c                 ,    g | ]}t          |          S rh   r   ri   s     rS   r   z'reinitialiser_ligne.<locals>.<listcomp>y  s    $$$E!HH$$$rU   c                 ,    g | ]}t          |          S rh   r   ri   s     rS   r   z'reinitialiser_ligne.<locals>.<listcomp>y  s    (A(A(Aaq(A(A(ArU   )rP   r  r[   )rR   r#  r   r   avantapresrk   s          rS   reinitialiser_ligneru  _  s'   
 JJ	Z	]D)+ + ,48:: 
 JJ	Z	]D)+ + ,48:: 

 JJ	G	]D)+ + +  K K


/ {^Qy\1_+=qyJ		K 	K 	K 	K IIKKK$$e$$$(A(A5(A(A(AAArU   c                    d}d |                      |dz  |f          D             d |                      |dz  |f          D             t                    t                    z  }fdt          |          D             S )u   
    Les couples (salarie, jour) qui different du classeur — pour signaler dans la
    grille ce qui a ete retouche a la main.
    z
        SELECT salarie_id, jour, GROUP_CONCAT(debut_min || '-' || fin_min || ':' || ajpp) AS empreinte
          FROM %s WHERE semaine_cycle = ? GROUP BY salarie_id, jourc                 <    i | ]}|d          |d         f|d         S r#  r   	empreinterh   ri   s     rS   r   z$lignes_modifiees.<locals>.<dictcomp>  sA     O O O &	*AkN O O OrU   rd   c                 <    i | ]}|d          |d         f|d         S rx  rh   ri   s     rS   r   z$lignes_modifiees.<locals>.<dictcomp>  sA     P P P ,6+Q{^ P P PrU   re   c                 r    g | ]3}                     |                               |          k    .d |z  4S )z%d|%dr   )rj   cleactuelorigines     rS   r   z$lignes_modifiees.<locals>.<listcomp>  sG     4 4 4czz#'++c"2"222 cM222rU   )rP   r   r   )rR   r   requeteclesr}  r~  s       @@rS   lignes_modifieesr  |  s    
GGO Ozz'N":]<LMMO O OFP P

7^#;m=MNNP P PGv;;W%D4 4 4 4 4VD\\ 4 4 4 4rU   c                     i }|                      d|f          D ]Y}|d         rO|                    |d         g                               |d         t          |d         dz  d          d           Z|S )	zG{ salarie_id : [jours entierement en AJPP] } pour une semaine du cycle.zSELECT salarie_id, jour,
                      MIN(ajpp) AS tous, SUM(fin_min - debut_min) AS minutes
                 FROM creneau_type WHERE semaine_cycle = ?
                GROUP BY salarie_id, jourr  r#  r   r  r   r   )r   r\  )rP   r   r   r[  )rR   r   r   rk   s       rS   
jours_ajppr    s    HZZ- 0=.>	@ @ N N
 V9 	N,44;;6eAiL44G.K.KLLN N NOrU   c                     fdt          ||d          D             }t          ||          D ]$\  }}	}
}|                     d|||||	|
|f           %d S )Nc                 0    i | ]}|t                    S rh   )r   )rj   r   rb   s     rS   r   z_inserer.<locals>.<dictcomp>  s!    <<<q$t**<<<rU   r   rp  )r   r   rP   )rR   r#  r   r   r   r   rb   r  dr   r   marques         `     rS   rf  rf    s    <<<<eE3&;&;<<<G%gt44 C C1dF


/ aD&A		C 	C 	C 	CC CrU   c                    |                      d|||f                                          }d}|D ]}|r|d         |d         k    r|d         |d         k    rz|d         |d         k    rh|                      d|d         |d         f           |                      d	|d         f           |d         |d         |d         |d         |d         d
}|}dS )z?Recolle les plages qui se touchent et partagent le meme statut.zSELECT id, debut_min, fin_min, hors_comptoir, ajpp FROM creneau_type
            WHERE salarie_id = ? AND semaine_cycle = ? AND jour = ?
            ORDER BY debut_minNr6  r5  r4  rb   z0UPDATE creneau_type SET fin_min = ? WHERE id = ?r   rd  )r   r5  r6  r4  rb   r  )rR   r#  r   r   r  
precedenterk   s          rS   rg  rg    s   ZZ	"$.t#DF F GOhjj  J   
	:i0AkNBB/1_3EEEv&!F)33JJI)j&679 9 9JJ>4
KKK *4 0z+?V%&y\AoDV"#F)- -JJ JJ rU   c                    dt           z  dg}|                    ddz             d}t          |           D ]}|d         |k    r |d         }|                    d|z             |d         d	n
d
|d         z  }d}|d         't          |d                   dk    r|d|d         z  z  }|d         s|d         r|d|d         |d         fz  z  }|                    d|d         |d         |d         |d         |d         |d         ||fz             dD ]}g }t	          | |                                          D ]c\  }}	|	D ][}
|
d         s|
d         rI|                    dt          |dz
           |
d         dz  |
d         dz  |
d         |
d         fz             \d|                    d           |                    d ||sd!nd"t          |          z  fz             |                    |           d#	                    |          S )$zFUn resume lisible, pour verifier l'import depuis la ligne de commande.z	Base : %srD   z %-4s %-13s %-13s %7s %7s %9s %8s)IniPrenomGroupeS1S2MoyenneContratNr]   z-- %sr  -z%.2frW  g{Gz?z   ecart %+0.2f hrX  rY  z   AJPP %.1f h / %.1f hz(%-4s %-13s %-13s %7.2f %7.2f %9.2f %8s%sr   r  rT  rU  rV  )r   r   rD  rE  z$  %-9s %02dh%02d : %d pers, %d pharmr   r   <   rA  rC  zSemaine %d : %szaucune alertez
%d alertes
)
rM   r   rb  absrP  rr   JOURSr   r+  r   )rR   r  groupe_courantr   r  notesr  alertesr   r,  ps              rS   etatr    s   Y&,F
MM5XY Z Z ZNr]] J JX;.((x[NMM(^3444I,.$$Ga	l4JW:!c!G*oo&=&=)AgJ66EY< 	O1Y< 	O/1Y<92NNNEA:(Qx[4!D'1Y<%II 	J 	J 	J 	J   !"g..4466 	T 	TID# T T() TQ-? TNN#J&+D1Hoq{b7H&'kB&6$=AQ&S$S T T TT
 	c(GW 6N5E5E1>W1M,O O 	P 	P 	Pg::frU   __main__r   import)NT)F)D__doc__osrK   r   xml.etree.ElementTreeetreeElementTreer}   pathdirnameabspath__file__BASEPROJETr   rM   r   r   r  r   r'  r(  r9  r=  rG  rH  r   r   r   rY   rT   r\   rq   rn   rZ   r   r   r   r   r   r   r   r   r   r  r  r!  r$  r)  r-  r/  rP  rb  ri  rn  ru  r  r  rf  rg  r  __name__sysrR   r   argvr   closerh   rU   rS   <module>r     s    
			   " " " " " " " " "	wrwx0011			GLL}--	7<<
FFH H CEEE
 	K K K K K K  	 

  "  ( S
R
R
 Z	/
h       <<;<	 	
G G GY Y Y  G G G  $  "      B( ( ("H H H[ [ [ [@% % % %% % %
 
 
5 5 5
  $ $ $( ( (V     J" " "J  0B B B:4 4 4"  C C C  .     F zJJJ	B
s38}}qSXa[H44	E$$r((OOOHHJJJJJ rU   