Ejemplo n.º 1
0
    def InitParametres(self):
        """ Récupération des paramètres d'impression """
        # DLG des paramètres d'impression
        dictOptions = {
            "titre" : self.titre,
            "introduction" : self.intro,
            "conclusion" : self.total,
            "orientation" : self.orientation,
            }
        dlg = DLG_Options_impression_listes.Dialog(None, dictOptions=dictOptions)
        if dlg.ShowModal() == wx.ID_OK:
            dictOptions = dlg.GetOptions()
            dlg.Destroy() 
        else :
            dlg.Destroy() 
            return False
        
        # Remplacement des mots-clés
        listeChamps = ["pied_page_texte_gauche", "pied_page_texte_milieu", "pied_page_texte_droite"]
        nomOrganisateur = self.GetNomOrganisateur()
        for key, valeur in dictOptions.items() :
            if key in listeChamps :
                valeur = valeur.replace("{DATE_JOUR}", UTILS_Dates.DateDDEnFr(datetime.date.today()))
                valeur = valeur.replace("{TITRE_DOCUMENT}", self.titre)
                valeur = valeur.replace("{NOM_ORGANISATEUR}", nomOrganisateur)
                valeur = valeur.replace("{NUM_PAGE}", "%(currentPage)d")
                valeur = valeur.replace("{NBRE_PAGES}", "%(totalPages)d")
                dictOptions[key] = valeur
                
        # Préparation du printout
        self.printer = ListCtrlPrinter.ListCtrlPrinter(self.listview, dictOptions["titre"])
        self.printer.printout.margins = (wx.Point(int(dictOptions["marge_gauche"]), int(dictOptions["marge_haut"])), wx.Point(int(dictOptions["marge_droite"]), int(dictOptions["marge_bas"])))
        self.printer.printout.printData.SetOrientation(dictOptions["orientation"])
        self.printer.printout.printData.SetQuality(int(dictOptions["qualite_impression"]))
        self.printer.PageFooter = (dictOptions["pied_page_texte_gauche"], dictOptions["pied_page_texte_milieu"], dictOptions["pied_page_texte_droite"])
        ListCtrlPrinter.LISTINTRO = dictOptions["introduction"]
        ListCtrlPrinter.LISTFOOTER = dictOptions["conclusion"]
        
        # Préparation du format
        fmt = ReportFormat()
        
        # Entête de page
    ##        fmt.PageHeader.Font = wx.FFont(10, wx.FONTFAMILY_DECORATIVE, wx.FONTFLAG_BOLD, face=headerFontName)
    ##        fmt.PageHeader.TextColor = wx.WHITE
    ##        fmt.PageHeader.Background(wx.GREEN, wx.RED, space=(16, 4, 0, 4))
    ##        fmt.PageHeader.Padding = (0, 0, 0, 12)
        
        # Titre de liste
        fmt.ListHeader.Font = wx.Font(int(dictOptions["titre_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["titre_style"]), faceName="Arial")
        fmt.ListHeader.TextColor = dictOptions["titre_couleur"]
        fmt.ListHeader.Padding = (0, 12, 0, 10)
        fmt.ListHeader.TextAlignment = dictOptions["titre_alignement"]
        fmt.ListHeader.Frame(wx.Pen(wx.BLACK, 0.25, wx.SOLID), space=10)
        
        # Intro
        fmt.ListIntro.Font = wx.Font(int(dictOptions["intro_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["intro_style"]), faceName="Arial")
        fmt.ListIntro.TextColor = dictOptions["intro_couleur"]
        fmt.ListIntro.Padding = (12, 2, 12, 2)
        fmt.ListIntro.TextAlignment = dictOptions["intro_alignement"]
        fmt.ListIntro.CanWrap = True
        
        # Titre de colonne
        fmt.ColumnHeader.Font = wx.Font(int(dictOptions["titre_colonne_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["titre_colonne_style"]), faceName="Arial")
        fmt.ColumnHeader.TextColor = dictOptions["titre_colonne_couleur"]
        fmt.ColumnHeader.Padding = (0, 15, 0, 0)
        fmt.ColumnHeader.Background(dictOptions["titre_colonne_couleur_fond"])
        fmt.ColumnHeader.CellPadding = 5
        fmt.ColumnHeader.TextAlignment = dictOptions["titre_colonne_alignement"]
        fmt.ColumnHeader.GridPen = wx.Pen(dictOptions["grille_trait_couleur"], dictOptions["grille_trait_epaisseur"], wx.SOLID)
        fmt.ColumnHeader.SetAlwaysCenter(True)
        
        # Titre d'un groupe
        fmt.GroupTitle.Font = wx.FFont(10, wx.FONTFAMILY_SWISS, wx.FONTFLAG_BOLD, faceName="Arial")
        fmt.GroupTitle.Padding = (2, 10, 2, 2)
        fmt.GroupTitle.CellPadding = 12
        fmt.GroupTitle.GridPen = wx.Pen(dictOptions["grille_trait_couleur"], dictOptions["grille_trait_epaisseur"], wx.SOLID)
        
##        fmt.GroupTitle.TextColor = wx.BLUE
##        fmt.GroupTitle.Padding = (0, 12, 0, 12)
##        fmt.GroupTitle.Line(wx.BOTTOM, wx.GREEN, 4, toColor=wx.WHITE, space=0)

        # Ligne
        fmt.Row.Font = wx.Font(int(dictOptions["ligne_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["ligne_style"]), faceName="Arial")
        fmt.Row.TextColor = dictOptions["ligne_couleur"]
        fmt.Row.CellPadding = 5
        fmt.Row.GridPen = wx.Pen(dictOptions["grille_trait_couleur"], dictOptions["grille_trait_epaisseur"], wx.SOLID)
        fmt.Row.CanWrap = dictOptions["ligne_multilignes"]
        
        # Pied de page
        fmt.PageFooter.Font = wx.Font(int(dictOptions["pied_page_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["pied_page_style"]), faceName="Arial")
        fmt.PageFooter.TextColor = dictOptions["pied_page_couleur"]
        fmt.PageFooter.Line(wx.TOP, wx.BLACK, 1, space=3)
        fmt.PageFooter.Padding = (0, 16, 0, 0)

        # Pied de colonne
        fmt.ColumnFooter.Font = wx.Font(int(dictOptions["pied_colonne_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["pied_colonne_style"]), faceName="Arial")
        fmt.ColumnFooter.TextColor = dictOptions["pied_colonne_couleur"]
        fmt.ColumnFooter.Padding = (0, 0, 0, 0)
        fmt.ColumnFooter.Background(dictOptions["pied_colonne_couleur_fond"])
        fmt.ColumnFooter.CellPadding = 5
        fmt.ColumnFooter.TextAlignment = dictOptions["pied_colonne_alignement"]
        fmt.ColumnFooter.GridPen = wx.Pen(dictOptions["grille_trait_couleur"], dictOptions["grille_trait_epaisseur"], wx.SOLID)
##        fmt.ColumnFooter.SetAlwaysCenter(True)

        # Conclusion
        fmt.ListFooter.Font = wx.Font(int(dictOptions["conclusion_taille_texte"]), wx.SWISS, wx.NORMAL, int(dictOptions["conclusion_style"]), faceName="Arial")
        fmt.ListFooter.TextColor = dictOptions["conclusion_couleur"]
        fmt.ListFooter.Padding = (12, 12, 0, 0)
        fmt.ListFooter.CellPadding = 5
##        fmt.ListFooter.Line(wx.TOP, wx.BLACK, 1, space=3)
        fmt.ListFooter.TextAlignment = dictOptions["conclusion_alignement"]
        fmt.ListFooter.CanWrap = True
        
        # Divers paramètres
        fmt.IsShrinkToFit = True
        fmt.IncludeImages = dictOptions["inclure_images"]
        fmt.IsColumnHeadingsOnEachPage = dictOptions["entetes_toutes_pages"]
        fmt.UseListCtrlTextFormat = True

        self.printer.ReportFormat = fmt
        return True
Ejemplo n.º 2
0
    def VerifieConsommations(self, listePeriodes=[]):
        # Récupération des unités
        DB = GestionDB.DB()
        req = """SELECT IDunite, nom, abrege, type, heure_debut, heure_fin
        FROM unites
        WHERE IDactivite=%d
        ORDER BY ordre;""" % self.IDactivite
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        dictUnites = {}
        for IDunite, nom, abrege, type, heure_debut, heure_fin in listeDonnees:
            dictUnites[IDunite] = {
                "nom": nom,
                "abrege": abrege,
                "type": type,
                "heure_debut": heure_debut,
                "heure_fin": heure_fin,
                "unites_incompatibles": []
            }

        # Récupère les incompatibilités entre unités
        req = """SELECT IDunite_incompat, IDunite, IDunite_incompatible
        FROM unites_incompat;"""
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        for IDunite_incompat, IDunite, IDunite_incompatible in listeDonnees:
            if dictUnites.has_key(IDunite):
                dictUnites[IDunite]["unites_incompatibles"].append(
                    IDunite_incompatible)
            if dictUnites.has_key(IDunite_incompatible):
                dictUnites[IDunite_incompatible][
                    "unites_incompatibles"].append(IDunite)

        # Récupération des ouvertures des unités
        req = """SELECT IDouverture, IDunite, IDgroupe, date
        FROM ouvertures 
        WHERE IDactivite=%d
        ORDER BY date; """ % self.IDactivite
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        dictOuvertures = {}
        for IDouverture, IDunite, IDgroupe, date in listeDonnees:
            date = UTILS_Dates.DateEngEnDateDD(date)
            dictOuvertures[(date, IDunite, IDgroupe)] = IDouverture

        # Récupération des consommations
        req = """SELECT IDconso, date, IDunite, heure_debut, heure_fin, etat
        FROM consommations 
        WHERE IDactivite=%d AND IDindividu=%d
        ORDER BY date; """ % (self.IDactivite, self.IDindividu)
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        dictConsommations = {}
        for IDconso, date, IDunite, heure_debut, heure_fin, etat in listeDonnees:
            date = UTILS_Dates.DateEngEnDateDD(date)
            if IDconso not in self.listeSuppressionConso:
                if dictConsommations.has_key(date) == False:
                    dictConsommations[date] = []
                dictConsommations[date].append({
                    "IDconso": IDconso,
                    "IDunite": IDunite,
                    "heure_debut": heure_debut,
                    "heure_fin": heure_fin,
                    "etat": etat
                })

        DB.Close()

        listeAnomalies = []
        for dictPeriode in listePeriodes:
            for dictConso in dictPeriode["listeConso"]:
                if dictConso["IDconso"] == None:
                    dateFr = UTILS_Dates.DateDDEnFr(dictConso["date"])
                    valide = True

                    # Vérifie si unité ouverte
                    if dictOuvertures.has_key(
                        (dictConso["date"], dictConso["IDunite"],
                         self.IDgroupe)) == False:
                        listeAnomalies.append(
                            _(u"%s : Unité %s fermée pour le groupe %s") %
                            (dateFr, dictUnites[dictConso["IDunite"]]["nom"],
                             self.nomGroupe))
                        valide = False

                    # Recherche si pas d'incompatibilités avec les conso déjà saisies
                    if dictConsommations.has_key(dictConso["date"]):
                        for dictConsoTemp in dictConsommations[
                                dictConso["date"]]:
                            nomUnite1 = dictUnites[dictConso["IDunite"]]["nom"]
                            nomUnite2 = dictUnites[
                                dictConsoTemp["IDunite"]]["nom"]

                            if self.VerifieCompatibilitesUnites(
                                    dictUnites, dictConsoTemp["IDunite"],
                                    dictConso["IDunite"]) == False:
                                listeAnomalies.append(
                                    _(u"%s : Unité %s incompatible avec unité %s déjà présente"
                                      ) % (dateFr, nomUnite1, nomUnite2))
                                valide = False

                            if dictConso["IDunite"] == dictConsoTemp[
                                    "IDunite"]:
                                if dictUnites[dictConso["IDunite"]][
                                        "type"] == "Multihoraire":
                                    if dictConso["heure_fin"] > dictConsoTemp[
                                            "heure_debut"] and dictConso[
                                                "heure_debut"] < dictConsoTemp[
                                                    "heure_fin"]:
                                        listeAnomalies.append(
                                            _(u"%s : L'unité multihoraires %s chevauche une consommation d'une unité identique"
                                              ) % (dateFr, nomUnite1))
                                        valide = False
                                else:
                                    listeAnomalies.append(
                                        _(u"%s : Unité %s déjà présente") %
                                        (dateFr, nomUnite1))
                                    valide = False

        # Signalement des anomalies
        if len(listeAnomalies):
            message1 = _(
                u"Validation du contrat impossible.\n\nLes %d anomalies suivantes ont été trouvées :"
            ) % len(listeAnomalies)
            message2 = u"\n".join(listeAnomalies)
            dlg = dialogs.MultiMessageDialog(
                self,
                message1,
                caption=_(u"Génération des consommations"),
                msg2=message2,
                style=wx.ICON_EXCLAMATION | wx.YES | wx.YES_DEFAULT,
                btnLabels={wx.ID_YES: _(u"Ok")})
            reponse = dlg.ShowModal()
            dlg.Destroy()
            return False

        return True
Ejemplo n.º 3
0
    def Importation(self, IDcontrat=None, mode_copie=False, copie_conso=True):
        """ Importation des données """
        DB = GestionDB.DB()

        # Importation des contrats
        req = """SELECT date_debut, date_fin, observations, IDtarif
        FROM contrats 
        WHERE IDcontrat=%d; """ % IDcontrat
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        if len(listeDonnees) == 0:
            DB.Close()
            return
        date_debut, date_fin, observations, IDtarif = listeDonnees[0]
        self.ctrl_date_debut.SetDate(date_debut)
        self.ctrl_date_fin.SetDate(date_fin)
        self.ctrl_observations.SetValue(observations)
        self.ctrl_tarif.SetID(IDtarif)

        # Importation des consommations liées au contrat
        req = """SELECT IDconso, consommations.IDindividu, IDinscription, consommations.IDactivite, consommations.date, IDunite, IDgroupe, heure_debut, heure_fin, etat, verrouillage, date_saisie, IDutilisateur, quantite, consommations.IDcategorie_tarif, consommations.IDcompte_payeur, consommations.IDprestation
        FROM consommations
        LEFT JOIN prestations ON prestations.IDprestation = consommations.IDprestation 
        WHERE prestations.IDcontrat=%d; """ % IDcontrat
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        dictConso = {}
        for IDconso, IDindividu, IDinscription, IDactivite, date, IDunite, IDgroupe, heure_debut, heure_fin, etat, verrouillage, date_saisie, IDutilisateur, quantite, IDcategorie_tarif, IDcompte_payeur, IDprestation in listeDonnees:
            date = UTILS_Dates.DateEngEnDateDD(date)
            date_saisie = UTILS_Dates.DateEngEnDateDD(date_saisie)
            dictTemp = {
                "IDconso": IDconso,
                "IDindividu": IDindividu,
                "IDinscription": IDinscription,
                "IDactivite": IDactivite,
                "date": date,
                "IDunite": IDunite,
                "IDgroupe": IDgroupe,
                "heure_debut": heure_debut,
                "heure_fin": heure_fin,
                "quantite": quantite,
                "etat": etat,
                "verrouillage": verrouillage,
                "date_saisie": date_saisie,
                "IDutilisateur": IDutilisateur,
                "IDcategorie_tarif": IDcategorie_tarif,
                "IDcompte_payeur": IDcompte_payeur,
                "IDprestation": IDprestation,
            }
            if dictConso.has_key(IDprestation) == False:
                dictConso[IDprestation] = []
            if mode_copie == True:
                dictTemp["IDconso"] = None
                dictTemp["etat"] = "reservation"
            dictConso[IDprestation].append(dictTemp)

        # Importation des périodes de contrat
        req = """SELECT prestations.IDprestation, forfait_date_debut, forfait_date_fin, label, montant, prestations.date,
        prestations.IDfacture, factures.IDprefixe, factures_prefixe.prefixe, factures.numero,
        COUNT(consommations.IDconso)
        FROM prestations 
        LEFT JOIN consommations ON consommations.IDprestation = prestations.IDprestation
        LEFT JOIN factures ON factures.IDfacture = prestations.IDfacture
        LEFT JOIN factures_prefixes ON factures_prefixes.IDprefixe = factures.IDprefixe
        WHERE IDcontrat=%d
        GROUP BY prestations.IDprestation
        ORDER BY forfait_date_debut;""" % IDcontrat
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        listePeriodes = []
        for IDprestation, date_debut, date_fin, label, montant, date_prestation, IDfacture, IDprefixe, prefixe, numFacture, nbreConso in listeDonnees:
            date_debut = UTILS_Dates.DateEngEnDateDD(date_debut)
            date_fin = UTILS_Dates.DateEngEnDateDD(date_fin)
            date_prestation = UTILS_Dates.DateEngEnDateDD(date_prestation)

            if IDprefixe != None:
                numFacture = u"%s-%06d" % (prefixe, numFacture)
            else:
                numFacture = u"%06d" % numFacture

            if dictConso.has_key(IDprestation) and copie_conso == True:
                listeConso = dictConso[IDprestation]
            else:
                listeConso = []
            dictTemp = {
                "IDprestation": IDprestation,
                "date_debut": date_debut,
                "date_fin": date_fin,
                "listeConso": listeConso,
                "label_prestation": label,
                "montant_prestation": montant,
                "date_prestation": date_prestation,
                "IDfacture": IDfacture,
                "numFacture": numFacture,
            }
            if mode_copie == True:
                dictTemp["IDprestation"] = None
                dictTemp["IDfacture"] = None
            listePeriodes.append(dictTemp)
        self.listePeriodesInitiale = copy.deepcopy(listePeriodes)
        self.ctrl_periodes.SetDonnees(listePeriodes)

        DB.Close()
Ejemplo n.º 4
0
 def FormateDateCourt(dateDD):
     if dateDD == None :
         return ""
     else:
         return UTILS_Dates.DateEngFr(str(dateDD))
 def HeureEnPos(self, heure, rect):
     tempsAffichable = UTILS_Dates.SoustractionHeures(
         self.heure_max, self.heure_min)
     return 1.0 * UTILS_Dates.SoustractionHeures(
         heure, self.heure_min
     ).seconds / tempsAffichable.seconds * self.GetLargeurMax(rect)
    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        # Préparation du buffer Image
        dcGrid = dc
        bmp = wx.EmptyBitmap(rect.GetWidth(), rect.GetHeight())
        image = wx.MemoryDC()
        image.SelectObject(bmp)
        gc = wx.GraphicsContext.Create(image)
        gc.PushState()

        rectCase = wx.Rect(0, 0, rect.GetWidth(), rect.GetHeight())
        x, y, largeur, hauteur = rectCase.x, rectCase.y, rectCase.width, rectCase.height

        # Dessin du fond
        if self.case.ouvert == True:
            self.couleurFond = wx.Colour(255, 255, 255)
        else:
            self.couleurFond = CTRL_Grille.COULEUR_FERME
        gc.SetBrush(wx.Brush(self.couleurFond, wx.SOLID))
        gc.SetPen(wx.TRANSPARENT_PEN)
        gc.DrawRectangle(x, y, largeur, hauteur)

        if self.case.ouvert == True:
            # Dessin de la bordure 3D pour faire effet Case grid
            self.DrawBorder(grid, gc, rectCase)

            # Dessin du remplissage
            dictInfosPlaces = self.case.GetInfosPlaces()
            if dictInfosPlaces != None:
                for IDunite_remplissage, valeurs in dictInfosPlaces.iteritems(
                ):

                    heure_min = UTILS_Dates.HeureStrEnTime(
                        grid.dictRemplissage[IDunite_remplissage]["heure_min"])
                    if heure_min < self.case.heure_min:
                        heure_min = self.case.heure_min
                    heure_max = UTILS_Dates.HeureStrEnTime(
                        grid.dictRemplissage[IDunite_remplissage]["heure_max"])
                    if heure_max > self.case.heure_max:
                        heure_max = self.case.heure_max

                    nbrePlacesRestantes = valeurs["nbrePlacesRestantes"]
                    nbrePlacesInitial = valeurs["nbrePlacesInitial"]
                    nbrePlacesPrises = valeurs["nbrePlacesPrises"]
                    seuil_alerte = valeurs["seuil_alerte"]
                    nbreAttente = valeurs["nbreAttente"]

                    couleur = None
                    if nbrePlacesRestantes > seuil_alerte:
                        couleur = CTRL_Grille.COULEUR_DISPONIBLE
                    if nbrePlacesRestantes > 0 and nbrePlacesRestantes <= seuil_alerte:
                        couleur = CTRL_Grille.COULEUR_ALERTE
                    if nbrePlacesRestantes <= 0:
                        couleur = CTRL_Grille.COULEUR_COMPLET

                    if nbrePlacesInitial > 0 and couleur != None:
                        gc.SetBrush(wx.Brush(couleur, wx.SOLID))
                        gc.SetPen(wx.TRANSPARENT_PEN)
                        posG = self.case.HeureEnPos(heure_min)
                        posD = self.case.HeureEnPos(heure_max) - posG
                        gc.DrawRectangle(
                            posG + PADDING_MULTIHORAIRES["horizontal"], 1,
                            posD, rectCase.height - 2)

            # Dessin des graduations
            gc.SetPen(wx.Pen((230, 230, 230), 1, wx.SOLID))
            # graduationStep = 25
            # listeGraduations = range(UTILS_Dates.HeuresEnDecimal(self.case.heure_min), UTILS_Dates.HeuresEnDecimal(self.case.heure_max)+graduationStep, graduationStep)
            # nbreGraduations = len(listeGraduations)
            # if nbreGraduations <= 1 :
            #     nbreGraduations = 2
            # step = 1.0 * (rect.width - PADDING_MULTIHORAIRES["horizontal"] * 2) / (nbreGraduations - 1)
            # if step > 3.0 :
            #     x = PADDING_MULTIHORAIRES["horizontal"]
            #     for temp in listeGraduations :
            #         gc.StrokeLine(x, 1, x, rect.height-2)
            #         x += step

            h = datetime.timedelta(minutes=0)
            for x in range(0, 96):
                htime = UTILS_Dates.DeltaEnTime(h)
                if htime >= self.case.heure_min and htime <= self.case.heure_max:
                    x = self.case.HeureEnPos(
                        h) + PADDING_MULTIHORAIRES["horizontal"]
                    gc.StrokeLine(x, 1, x, rect.height - 2)
                h += datetime.timedelta(minutes=15)

        # Dessin des barres
        for barre in self.case.listeBarres:
            conso = barre.conso

            # Calcul des coordonnées de la barre
            barre.UpdateRect()
            rectBarre = barre.GetRect("case")

            # get Couleur barre
            couleurBarre = self.GetCouleurBarre(conso)

            # Dessin du cadre
            gc.SetFont(attr.GetFont())
            gc.SetBrush(
                wx.Brush((couleurBarre.Red(), couleurBarre.Green(),
                          couleurBarre.Blue(), 180),
                         wx.SOLID))  # 128 = demi-transparence

            couleurTexte = UTILS_Couleurs.ModifierLuminosite(couleurBarre, -50)
            couleur = (couleurTexte[0], couleurTexte[1], couleurTexte[2], 255)
            if barre.readOnly == True:
                gc.SetPen(wx.TRANSPARENT_PEN)
            else:
                gc.SetPen(wx.Pen(couleur, 1,
                                 wx.SOLID))  # 128 = demi-transparence
            gc.DrawRoundedRectangle(rectBarre.x, rectBarre.y, rectBarre.width,
                                    rectBarre.height, 5)

            # Dessin des horaires
            heure_debut_x, heure_debut_y, heure_debut_largeur, heure_debut_hauteur = self.DrawTexte(
                gc,
                rectBarre,
                barre.heure_debut.strftime("%Hh%M"),
                couleur=couleurTexte,
                position="gauche")
            heure_fin_x, heure_fin_y, heure_fin_largeur, heure_fin_hauteur = self.DrawTexte(
                gc,
                rectBarre,
                barre.heure_fin.strftime("%Hh%M"),
                couleur=couleurTexte,
                position="droite")

            # Dessin du cadenas VERROUILLAGE
            if conso.verrouillage == 1:
                imageTemp = wx.Bitmap(
                    Chemins.GetStaticPath("Images/Special/Cadenas_ferme.png"),
                    wx.BITMAP_TYPE_ANY)
                largeurBmp, hauteurBmp = imageTemp.GetSize()
                gc.DrawBitmap(imageTemp, 2, rect.height - 10, largeurBmp,
                              hauteurBmp)

            # Dessin de l'image FORFAIT CREDIT
            if conso.etat in (
                    "reservation", "present", "absenti", "absentj"
            ) and conso.IDprestation in grid.dictForfaits.keys():
                couleurForfait = grid.dictForfaits[
                    conso.IDprestation]["couleur"]
                gc.SetBrush(wx.Brush(couleurForfait, wx.SOLID))
                gc.SetPen(wx.TRANSPARENT_PEN)
                path = gc.CreatePath()
                path.AddLineToPoint(8, 0)
                path.AddLineToPoint(1, 8)
                path.AddLineToPoint(1, 0)
                gc.DrawPath(path)

            # Dessin des images
            listeImages = []

            # Dessin de l'image PRESENT (Coche verte)
            if conso.etat == "present":
                listeImages.append(
                    wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Ok5.png"),
                              wx.BITMAP_TYPE_ANY))

            # Dessin de l'image ABSENT JUSTIFIEE (Croix rouge)
            if conso.etat == "absentj":
                listeImages.append(
                    wx.Bitmap(
                        Chemins.GetStaticPath("Images/16x16/absentj.png"),
                        wx.BITMAP_TYPE_ANY))

            # Dessin de l'image ABSENT INJUSTIFIEE (Croix rouge)
            if conso.etat == "absenti":
                listeImages.append(
                    wx.Bitmap(
                        Chemins.GetStaticPath("Images/16x16/absenti.png"),
                        wx.BITMAP_TYPE_ANY))

            # Dessin de l'image SANS PRESTATION (Alerte)
            if conso.etat in (
                    "reservation", "present", "absenti", "absentj"
            ) and conso.IDprestation == None and grid.afficheSansPrestation == True:
                listeImages.append(
                    wx.Bitmap(
                        Chemins.GetStaticPath("Images/16x16/Gratuit.png"),
                        wx.BITMAP_TYPE_ANY))

            paddingImage = 3
            if heure_fin_x == 0:
                heure_fin_x = rectBarre.x + rectBarre.width
            xImage = heure_fin_x - paddingImage  # heure_debut_x + heure_debut_largeur + paddingImage
            if rectBarre.width > len(listeImages) * 19:
                for imageTemp in listeImages:
                    largeurBmp, hauteurBmp = imageTemp.GetSize()
                    gc.DrawBitmap(imageTemp, xImage - largeurBmp,
                                  rectBarre.y + 1, largeurBmp, hauteurBmp)
                    xImage -= largeurBmp + paddingImage

            # Ecrit le nom du groupe
            if CTRL_Grille.AFFICHE_NOM_GROUPE == True and rectBarre.height > 22:
                if conso.IDgroupe != None and conso.IDgroupe != 0 and conso.etat in (
                        "reservation", "present", "absenti", "absentj",
                        "attente", "refus"):
                    couleurTexteGroupe = UTILS_Couleurs.ModifierLuminosite(
                        couleurBarre, -30)
                    gc.SetFont(
                        wx.Font(6, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                                wx.FONTWEIGHT_NORMAL, False, 'Arial'),
                        couleurTexteGroupe)
                    nomGroupe = grid.dictGroupes[conso.IDgroupe]["nom"]
                    largeurNomGroupe, hauteurNomGroupe = gc.GetTextExtent(
                        nomGroupe)
                    nbreGroupesActivite = grid.dictGroupes[
                        conso.IDgroupe]["nbreGroupesActivite"]
                    if rectBarre.width > largeurNomGroupe and nbreGroupesActivite > 1:
                        gc.DrawText(nomGroupe, rectBarre.x + 4,
                                    rectBarre.y + rectBarre.height - 10)

            # Ecrit les étiquettes
            nbreEtiquettes = len(conso.etiquettes)
            if conso.etat != None and nbreEtiquettes > 0:
                index = 0
                for IDetiquette in conso.etiquettes:
                    if grid.dictEtiquettes.has_key(IDetiquette):
                        dictEtiquette = grid.dictEtiquettes[IDetiquette]
                        # Dessine l'étiquette
                        gc.SetBrush(
                            wx.Brush(dictEtiquette["couleur"], wx.SOLID))
                        gc.SetPen(wx.TRANSPARENT_PEN)
                        gc.DrawEllipse(rectBarre.x + rectBarre.width - 7 -
                                       (5 * index),
                                       rectBarre.y + rectBarre.height - 7, 4,
                                       4)  # En haut à droite
                        index += 1

        gc.PopState()

        # Envoi du buffer au DC
        dcGrid.Blit(rect.x, rect.y, bmp.GetWidth(), bmp.GetHeight(), image, 0,
                    0)