def __init__(self, donnees, codesColonnes, nomsColonnes, setterValues):
     self.donnees = donnees
     if not (len(donnees) == len(codesColonnes) == len(nomsColonnes) ==
             len(setterValues)):
         wx.MessageBox(
             "Problème de nombre d'occurences!\n%d donnees, %d codes, %d colonnes et %d valeurs défaut"
             % (len(donnees), len(codesColonnes), len(nomsColonnes),
                len(setterValues)))
     for ix in range(len(donnees)):
         donnee = donnees[ix]
         if setterValues[ix]:
             # prise de la valeur par défaut si pas de donnée
             if (donnee is None):
                 donnee = setterValues[ix]
             # le type de la donnée n'est pas celui attendu
             else:
                 if not isinstance(donnee, type(setterValues[ix])):
                     try:
                         if type(setterValues[ix]) in (int, float):
                             donnee = float(donnee)
                         elif type(setterValues[ix]) == str:
                             donnee = str(donnee)
                         elif isinstance(
                                 setterValues[ix],
                             (wx.DateTime, datetime.date, datetime.datetime,
                              datetime.time)):
                             donnee = xformat.DateSqlToDatetime(donnee)
                     except:
                         pass
         self.__setattr__(codesColonnes[ix], donnee)
Esempio n. 2
0
    def GetDonnees(self,dParams=None):
        if not dParams:
            dParams = self.pnlParams.GetValues(fmtDD=False)
        idem = True
        if self.oldParams == None :
            idem = False
        else:
            for key in ('origine','date','analytique','fournisseur'):
                if not key in self.oldParams.keys(): idem = False
                elif not key in dParams.keys(): idem = False
                elif self.oldParams[key] != dParams[key]: idem = False
        if idem : return

        # appel des données de l'Olv principal à éditer
        lstDonnees = nust.SqlInventaire(self)
        self.mouvementsPost = nust.MouvementsPosterieurs(self)
        if self.mouvementsPost:
            self.pnlPied.SetItemsInfos("Présence de mouvements postérieurs\nLe stock dans l'article n'est pas mis à jour",
                                       wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_OTHER, (16, 16)))


        # l'appel des données peut avoir retourné d'autres paramètres, il faut mettre à jour l'écran
        if len(lstDonnees) > 0:
            # set date du lot importé
            self.pnlParams.SetOneValue('date',xformat.DateSqlToDatetime(dParams['date']),'param1')
            self.date = dParams['date']

        # alimente la grille, puis création de modelObejects pr init
        self.ctrlOlv.lstDonnees = lstDonnees
        self.ctrlOlv.MAJ()
        # les écritures reprises sont censées être valides
        for track in self.ctrlOlv.modelObjects[:-1]:
            track.IDmouvement = None
        self.oldParams = None
 def __init__(self, donnees,codesColonnes, setterValues,codesSup=list):
     # il peut y avoir plus de données que le nombre de colonnes, elles sont non gérées par le tableau
     if not (len(donnees)-len(codesSup) == len(codesColonnes) == len(setterValues) ):
         lst = [str(codesColonnes),str(setterValues),str(donnees)]
         mess = "Problème de nombre d'occurences!\n\n"
         mess += "(%d - %d) donnees, %d codes, %d colonnes"%(len(donnees),len(codesSup),
                                                     len(codesColonnes), len(setterValues))
         mess += '\n\n'+'\n\n'.join(lst)
         wx.MessageBox(mess,caption="xGestion_TableauRecherche.TrackGeneral")
         raise("echec Track général")
     self.donnees = donnees
     for ix in range(len(codesColonnes + codesSup)):
         donnee = donnees[ix]
         if ix < len(codesColonnes):
             if setterValues[ix]:
                 # prise de la valeur par défaut si pas de donnée
                 if (donnee is None):
                     donnee = setterValues[ix]
                 # le type de la donnée n'est pas celui attendu
                 else:
                     if not isinstance(donnee,type(setterValues[ix])):
                         try:
                             if type(setterValues[ix]) in (int,float):
                                 donnee = float(donnee)
                             elif type(setterValues[ix]) == str:
                                 donnee = str(donnee)
                             elif isinstance(setterValues[ix],(wx.DateTime,datetime.date,datetime.datetime,datetime.time)):
                                 donnee = xformat.DateSqlToDatetime(donnee)
                         except : pass
         self.__setattr__((codesColonnes + codesSup)[ix], donnee)
Esempio n. 4
0
def TransposeDonnees(dlg, recordset, lstCodesChamps, lstCodesDonnees):
    # ajustement des choix possibles selon le contenu du règlement et de la prestation associée
    ixnat = lstCodesDonnees.index('nature')
    ixdat = lstCodesDonnees.index('date')
    ixmode = lstCodesDonnees.index('mode')
    ixcreer = lstCodesDonnees.index('creer')
    ixcompte = lstCodesDonnees.index('compte')

    # les derniers champs ne sont pas dans la grille à afficher, mais tous dans les données
    lstDonnees = []
    # chaque ligne du recordset crée une ligne de données
    for record in recordset:
        donnees = [
            None,
        ] * len(lstCodesDonnees)

        # alimente tous les champs de données présents dans le recordset en l'état
        for ixdon in range(len(lstCodesDonnees)):
            if lstCodesDonnees[ixdon] in lstCodesChamps:
                ixch = lstCodesChamps.index(lstCodesDonnees[ixdon])
                donnees[ixdon] = record[ixch]

        # recherche du mode de règlement
        IDmode = record[lstCodesChamps.index('IDmode')]

        if 'choice' in dlg.ddModesRegl[IDmode].keys():
            donnees[ixmode] = dlg.ddModesRegl[IDmode]['choice']
        else:
            donnees[ixmode] = dlg.ddModesRegl[IDmode]['label']

        # détermination de la nature 'Règlement','Acompte','Don','Debour','Libre'
        compte = record[lstCodesChamps.index('prestcompte')]
        nature = record[lstCodesChamps.index('prestcateg')]
        nbVentil = record[lstCodesChamps.index('nbventil')]
        if nature and nature.lower() == 'don':
            donnees[ixnat] = 'Don'
            donnees[ixcompte] = compte
            creer = 'O'
        elif nature and nature.lower() == 'donsscerfa':
            donnees[ixnat] = 'DonSsCerfa'
            donnees[ixcompte] = compte
            creer = 'O'
        elif nature and nature.lower() == 'debour':
            donnees[ixnat] = 'Debour'
            donnees[ixcompte] = compte
            creer = 'O'
        elif nbVentil and nbVentil > 0:
            donnees[ixnat] = 'Règlement'
            creer = 'N'
        else:
            donnees[ixnat] = 'Acompte'
            creer = 'N'
        donnees[ixcreer] = creer

        # date remise en format français
        donnees[ixdat] = xformat.DateSqlToDatetime(donnees[ixdat])
        lstDonnees.append(donnees)
    return lstDonnees
Esempio n. 5
0
    def GetExercices(self, where='WHERE  actif = 1',tip='date'):
        if self.ltExercices: return self.ltExercices
        self.ltExercices = []
        lstChamps = ['date_debut', 'date_fin']
        req = """   SELECT %s
                    FROM cptaExercices
                    %s                   
                    """ % (",".join(lstChamps), where)
        retour = self.db.ExecuterReq(req, mess='UTILS_Noegest.GetExercices')
        if retour == "ok":
            recordset = self.db.ResultatReq()
            if len(recordset) == 0:
                wx.MessageBox("Aucun exercice n'est paramétré")
            for debut, fin in recordset:
                if tip.lower() in ('date', 'datetime'): debut, fin = xformat.DateSqlToDatetime(debut), \
                                                                     xformat.DateSqlToDatetime(fin)
                elif tip.lower() in ('str','iso','ansi'): debut,fin = xformat.DateSqlToIso(debut),\
                                                                xformat.DateSqlToIso(fin)
                elif tip.lower() == 'fr': debut,fin = xformat.DateSqlToFr(debut),\
                                                      xformat.DateSqlToFr(fin)
                self.ltExercices.append((debut, fin))

        return self.ltExercices
def ComposeLstDonnees(record, lstChamps, lstColonnes):
    # retourne les données pour colonnes, les champs doivent correspondre aux premières colonnes
    lstdonnees = []
    nbcol = min(len(lstChamps), len(lstColonnes))
    for ix in range(nbcol):
        if type(lstColonnes[ix].valueSetter) in (wx.DateTime, datetime.date,
                                                 datetime.datetime):
            if type(lstColonnes[ix].valueSetter) == wx.DateTime:
                lstdonnees.append(xformat.DateSqlToWxdate(record[ix]))
            else:
                lstdonnees.append(xformat.DateSqlToDatetime(record[ix]))
        else:
            lstdonnees.append(record[ix])
    return lstdonnees
Esempio n. 7
0
    def RecalculPrixSorties(self, fin=None):
        ok = False
        if fin == None: fin = self.cloture
        debut = None
        if self.lastInventaire:
            # présence d'un inventaire antérieur
            debut = xformat.DateSqlToDatetime(self.lastInventaire[0][0])

        #['jour', 'origine', 'nomArticle', 'qteMouvement','prixUnit']
        self.mvtsCorriges = GetMouvements(debut=debut, fin=fin)
        self._xAjoutInventaire(self.mvtsCorriges)
        self.mvtsCorriges.sort()

        lstArticles = []
        # listes préalable, chaque article est traité à part
        for jour, origine, article, qte, pu, id in self.mvtsCorriges:
            if not article in lstArticles:
                lstArticles.append(article)
        lstArticles.sort()
        if lstArticles == None:
            raise Exception("Aucun mouvement dans la période du %s au %s"\
                  %(debut,fin))

        nbrUpdates = 0
        self.llModifsMouvements = []
        for artArt in lstArticles:
            mvtsArticle = []
            self.dicPrixMvtOld = {}
            self.dicPrixMvtNew = {}
            # isole les mouvements de l'article
            for jour, origine, artMvt, qte, pu, id in self.mvtsCorriges:
                if artMvt != artArt:
                    continue
                self.dicPrixMvtOld[id] = pu
                mvtsArticle.append([jour, origine, artMvt, qte, pu, id])

            #if artArt == "ABRICOTS FRAIS KG": print()# debug arrêt sur article
            self._xRecalculPrixSortiesUnArticle(mvtsArticle)
            for id, prix in self.dicPrixMvtNew.items():
                # les calculs intermédiaires font varier temporairement prix
                if abs(prix - self.dicPrixMvtOld[id]) > 0.0001:
                    self.llModifsMouvements.append([prix, id])
                    nbrUpdates += 1
            ok = True

        PostMouvements(champs=['prixUnit', 'idMouvement'],
                       mouvements=self.llModifsMouvements)

        print(nbrUpdates)
        return ok
Esempio n. 8
0
 def __init__(self,
              donnees,
              codesColonnes,
              nomsColonnes,
              setterValues,
              codesSup=[]):
     # les données suplémentaires au nbre de colonnes, sont présentes dans les tracks et définies par codesSup
     if not (len(donnees) - len(codesSup) == len(codesColonnes) ==
             len(nomsColonnes) == len(setterValues)):
         lst = [
             str(codesColonnes),
             str(nomsColonnes),
             str(setterValues),
             str(donnees)
         ]
         mess = "Problème de nombre d'occurences!\n\n"
         mess += "%d codesCol, %d nomsCol, %d valDéfaut, (%d donnees - %d codes_sup) = %d" % (
             len(codesColonnes), len(nomsColonnes), len(setterValues),
             len(donnees), len(codesSup), (len(donnees) - len(codesSup)))
         mess += '\n\n' + '\n\n'.join(lst)
         wx.MessageBox(mess, caption="xGestion_TableauEditor.TrackGeneral")
         raise (mess)
     # pour chaque donnée affichée, attribut et ctrl setter value
     for ix in range(len(codesColonnes)):
         donnee = donnees[ix]
         if setterValues[ix]:
             # prise de la valeur par défaut si pas de donnée
             if (donnee is None):
                 donnee = setterValues[ix]
             # le type de la donnée n'est pas celui attendu
             else:
                 if not isinstance(donnee, type(setterValues[ix])):
                     try:
                         if type(setterValues[ix]) in (int, float):
                             donnee = float(donnee)
                         elif type(setterValues[ix]) == str:
                             donnee = str(donnee)
                         elif isinstance(
                                 setterValues[ix],
                             (wx.DateTime, datetime.date, datetime.datetime,
                              datetime.time)):
                             donnee = xformat.DateSqlToDatetime(donnee)
                     except:
                         pass
         self.__setattr__((codesColonnes + codesSup)[ix], donnee)
     # complément des autres données
     for ixrel in range(len(codesSup)):
         ixabs = len(codesColonnes) + ixrel
         self.__setattr__((codesSup)[ixrel], donnees[ixabs])
     self.donnees = donnees
Esempio n. 9
0
    def CalculInventaire(self, fin=None):
        # retourne un inventaire: liste de liste
        if fin == None: fin = self.cloture

        debut = None
        if self.lastInventaire:
            # présence d'un inventaire antérieur
            debut = xformat.DateSqlToDatetime(self.lastInventaire[0][0])

        #['jour', 'origine', 'nomArticle', 'qteMouvement','prixUnit']
        llMouvements = GetMouvements(debut=debut, fin=fin)
        self._xAjoutInventaire(llMouvements)

        # liste préalable pour traitement par article
        lstArticles = []
        for jour, origine, article, qte, pu, id in llMouvements:
            if not article:
                raise Exception("Article disparu! mvt du %s qte= %d" %
                                (jour, qte))
            if not article in lstArticles:
                lstArticles.append(article)
        lstArticles.sort()
        if lstArticles == None:
            raise Exception("Aucun mouvement dans la période du %s au %s"\
                  %(debut,fin))

        # composition de l'inventaire
        llinventaire = []
        for article in lstArticles:
            lstMvts = [x[0:2] + x[3:] for x in llMouvements if x[2] == article]
            qte, mtt, lastPrix = self._CalculInventaireUnArticle(lstMvts)
            if qte == 0:
                pu = 0.0
            else:
                pu = round(mtt / qte, 4)
            if qte != 0 and mtt != 0:
                # compose [dte,article,qte,prixMoyen,montant,lastPrix]
                llinventaire.append([
                    xformat.DatetimeToStr(fin, iso=True),
                    article,
                    round(qte, 4),
                    pu,
                    round(mtt, 4),
                    lastPrix,
                ])
        return llinventaire
Esempio n. 10
0
    def __init__(self,dteJour=None):
        # boutons de bas d'écran - infos: texte ou objet window.  Les infos sont  placées en bas à gauche
        lstInfos = [ wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_OTHER, (16, 16)),]
        lstInfos += INFOS
        dicPied = {'lstBtns': GetBoutons(self), "lstInfos": lstInfos}

        # Propriétés du corps de l'écran
        self.dicOlv = {'lstColonnes': GetOlvColonnes(self)}
        self.dicOlv.update({'lstCodesSup': GetOlvCodesSup()})
        self.dicOlv.update(GetOlvOptions(self))

        # variables gérées par l'écran paramètres
        self.today = datetime.date.today()
        if not dteJour:
            dteJour = self.today
        else: dteJour = xformat.DateSqlToDatetime(dteJour)
        self.periode = (dteJour,dteJour)
        self.cuisine = True
        self.analytique = '00'
        self.midi = True
        self.soir = True
        self.matin = True

        # Propriétés de l'écran global type Dialog
        kwds = GetDlgOptions(self)
        kwds['autoSizer'] = False
        kwds['dicParams'] = GetDicParams()
        #kwds['dicOlv'] = self.dicOlv
        kwds['dicPied'] = dicPied
        kwds['db'] = xdb.DB()

        super().__init__(None, **kwds)
        self.pnlOlv = PNL_corps(self, self.dicOlv,  **kwds )
        self.ctrlOlv = self.pnlOlv.ctrlOlv

        ret = self.Init()
        if ret == wx.ID_ABORT: self.Destroy()
        self.Sizer()
        self.ctrlOlv.MAJ()
        self.ctrlOlv.SetFocus()
Esempio n. 11
0
    def Importation(self):
        if self.IDreglement == None :
            IDreglement = 0
        else:
            IDreglement = self.IDreglement
        
        # Importation des ventilations de ce règlement
        DB = xdb.DB()
        req = """SELECT IDventilation, IDprestation, montant
        FROM ventilation
        WHERE IDreglement=%d
        ;""" % IDreglement
        DB.ExecuterReq(req)
        lstDonnees = DB.ResultatReq()
        self.dictVentilation = {}
        self.dictVentilationInitiale = {}
        for IDventilation, IDprestation, montant in lstDonnees :
            self.dictVentilation[IDprestation] = montant
            self.dictVentilationInitiale[IDprestation] = IDventilation

        # Importation des prestations de la famille et leurs parts réglées
        req = """
        SELECT prestations.IDprestation, prestations.IDcompte_payeur, date, categorie, label, prestations.montant, 
        prestations.IDactivite, activites.nom,
        prestations.IDtarif, noms_tarifs.nom, categories_tarifs.nom, 
        prestations.IDfacture, factures.numero, factures.date_edition,
        IDfamille, prestations.IDindividu, 
        individus.nom, individus.prenom,
        SUM(ventilation.montant) AS montant_ventilation
        FROM prestations
        LEFT JOIN ventilation ON prestations.IDprestation = ventilation.IDprestation
        LEFT JOIN activites ON prestations.IDactivite = activites.IDactivite
        LEFT JOIN individus ON prestations.IDindividu = individus.IDindividu
        LEFT JOIN tarifs ON prestations.IDtarif = tarifs.IDtarif
        LEFT JOIN noms_tarifs ON tarifs.IDnom_tarif = noms_tarifs.IDnom_tarif
        LEFT JOIN categories_tarifs ON tarifs.IDcategorie_tarif = categories_tarifs.IDcategorie_tarif
        LEFT JOIN factures ON prestations.IDfacture = factures.IDfacture
        WHERE prestations.IDcompte_payeur = %d 
        GROUP BY prestations.IDprestation, prestations.IDcompte_payeur, date, categorie, label, prestations.montant, 
                prestations.IDactivite, activites.nom,
                prestations.IDtarif, noms_tarifs.nom, categories_tarifs.nom, 
                prestations.IDfacture, factures.numero, factures.date_edition,
                IDfamille, prestations.IDindividu, 
                individus.nom, individus.prenom
        ORDER BY date
        ;""" % self.IDcompte_payeur
        DB.ExecuterReq(req)
        lstDonnees = DB.ResultatReq()
        DB.Close()
        listeLignesPrestations = []
        for IDprestation, IDcompte_payeur, date, categorie, label, montant, IDactivite, nomActivite, IDtarif, nomTarif, \
            nomCategorieTarif, IDfacture, num_facture, date_facture, IDfamille, IDindividu, nomIndividu, prenomIndividu,\
            montantVentilation in lstDonnees :
            montant = montant
            if montantVentilation == None: montantVentilation = 0.0
            if num_facture == None : num_facture = 0
            # Vérif cohérence
            if (montant >= 0.0 and montantVentilation > montant) \
                    or (montant < 0.0 and montantVentilation < montant)\
                    or ((montant * montantVentilation) < 0.0):
                montant,montantVentilation = self.CorrigeVentilation(IDprestation)

            # Composition des données OLV
            if (montant >= 0.0 and montantVentilation < montant) \
                    or (montant < 0.0 and montantVentilation > montant) \
                    or IDprestation in self.dictVentilation.keys() :
                # On garde cette prestation pour pouvoir affecter le règlement
                date = xformat.DateSqlToDatetime(date)
                if IDprestation in self.dictVentilation.keys() :
                    montantVentilation = montantVentilation - self.dictVentilation[IDprestation] 

                dictTemp = {
                    "IDprestation" : IDprestation, "IDcompte_payeur" : IDcompte_payeur, "date" : date, "categorie" : categorie,
                    "label" : label, "montant" : montant, "IDactivite" : IDactivite, "nomActivite" : nomActivite, "IDtarif" : IDtarif, "nomTarif" : nomTarif, 
                    "nomCategorieTarif" : nomCategorieTarif, "IDfacture" : IDfacture, "num_facture" : num_facture, "date_facture" : date_facture, 
                    "IDfamille" : IDfamille, "IDindividu" : IDindividu, "nomIndividu" : nomIndividu, "prenomIndividu" : prenomIndividu,
                    "ventilationPassee" : montantVentilation,
                    }
                ligne_prestation = Ligne_prestation(grid=self, donnees=dictTemp)
                listeLignesPrestations.append(ligne_prestation)
        return listeLignesPrestations
Esempio n. 12
0
def ComposeFuncExp(dicParams, donnees, champsIn, champsOut):
    """ 'in' est l'OLV enrichi des champs obligatoires, 'out' est le fichier de sortie
        obligatoires dans champsIN : date,compte,piece,libelle,montant,
                        facultatifs: contrepartie (qui aura priorité sur la valeur dans dicParams)
        dans dicParams sont facultatifs: journal, contrepartie, typepiece
    """
    lstOut = []
    #formatOut = dicParams['fichiers']['formatexp']
    typepiece = "B"  # cas par défaut B comme carte Bancaire
    journal = 'OD'
    contrepartie = '58999'
    if 'typepiece' in dicParams['p_export']:
        typepiece = dicParams['p_export']['typepiece']
    if 'journal' in dicParams['p_compta']:
        journal = dicParams['p_compta']['journal']
    if 'contrepartie' in dicParams['p_export']:
        contrepartie = dicParams['p_export']['contrepartie']

    # déroulé des lignes puis des champs out
    for ligne in donnees:
        ligneOut = []
        montant = ligne[champsIn.index('montant')]
        if isinstance(montant, str):
            montant = float(montant.replace(",", "."))
        elif isinstance(montant, (int, float)):
            montant = float(montant)
        else:
            montant = 0.0
        for champ in champsOut:
            if champ in champsIn:
                valeur = ligne[champsIn.index(champ)]
            else:
                valeur = ''
            # composition des champs sortie
            if champ == 'journal': valeur = journal
            elif champ == 'compte':
                if not valeur or valeur == '': valeur = '471'
            elif champ == 'date':
                valeur = xformat.DateSqlToDatetime(valeur)
            elif champ == 'typepiece':
                valeur = typepiece
            elif champ == 'contrepartie':
                if 'contrepartie' in champsIn:
                    valeur = ligne[champsIn.index('contrepartie')]
                else:
                    valeur = contrepartie
            elif champ == 'devise':
                valeur = 'EUR'
            elif champ == 'sens':
                if montant >= 0: valeur = 'C'
                else: valeur = 'D'
            elif champ == 'valeur': valeur = abs(montant)
            elif champ == 'valeur00': valeur = abs(montant * 100)
            elif champ == 'debit':
                if montant < 0.0: valeur = -montant
                else: valeur = 0.0
            elif champ == 'credit':
                if montant >= 0.0: valeur = montant
                else: valeur = 0.0
            ligneOut.append(valeur)
        lstOut.append(ligneOut)
        # ajout de la contrepartie banque
        ligneBanque = [x for x in ligneOut]
        ligneBanque[champsOut.index('contrepartie')] = ligneOut[
            champsOut.index('compte')]
        if 'contrepartie' in champsIn:
            ligneBanque[champsOut.index('compte')] = ligne[champsIn.index(
                'contrepartie')]
        else:
            ligneBanque[champsOut.index(
                'compte')] = dicParams['p_export']['contrepartie']
        if 'debit' in champsOut:
            ligneBanque[champsOut.index('debit')] = ligneOut[champsOut.index(
                'credit')]
            ligneBanque[champsOut.index('credit')] = ligneOut[champsOut.index(
                'debit')]
        elif 'sens' in champsOut:
            ix = champsOut.index('sens')
            if ligneOut[ix] == 'D': ligneBanque[ix] = 'C'
            elif ligneOut[ix] == 'C': ligneBanque[ix] = 'D'
        lstOut.append(ligneBanque)
    return lstOut
Esempio n. 13
0
def GetPrixJourDetail(dlg,grouper='date',**kwd):
    db = kwd.get('db',dlg.db)
    if not grouper in ('date','article','ensemble'):
        raise Exception("GetPrixJour détail grouper not in ('date','IDarticle','ensemble')")
    periode = dlg.periode
    # filtrage sur la date
    dtFin = xformat.DateSqlToDatetime(periode[1])
    dtDeb = xformat.DateSqlToDatetime(periode[0])
    dtFinJ1 = xformat.DecaleDateTime(dtFin,+1) # pour inclure les ptDèj du lendemain

    # filtrage sur les types de repas demandés
    lstRepasRetenus = []
    if dlg.midi:
        lstRepasRetenus.append(2)
    if dlg.soir:
        lstRepasRetenus.append(3)
    if len(lstRepasRetenus) >0:
        lstRepasRetenus += [0,5,]# ajout des indifinis sauf si matins seuls
    if dlg.matin:
        lstRepasRetenus += [1,4]
    if lstRepasRetenus == []: return []

    # compose le where sur date et analytique
    def getWhere(nomDate, deb,fin):
        wh = """
                WHERE (%s >= '%s' AND %s <= '%s')
                    """%(nomDate,deb,nomDate,fin)

        # filtrage sur le code analytique
        if dlg.cuisine: wh += """
                        AND ( IDanalytique = '00' OR IDanalytique IS NULL )"""
        else: wh += """
                        AND ( IDanalytique = '%s')"""%dlg.analytique
        return wh


    # Recherche des effectifs: ['date', 'nbMidiCli', 'nbMidiRep', 'nbSoirCli', 'nbSoirRep']-------------
    where = getWhere('IDdate', dtDeb,dtFin)

    lstChamps = ['IDdate', 'midiRepas', 'soirRepas', 'midiClients', 'soirClients']
    req = """
            SELECT  %s 
            FROM stEffectifs 
            %s
            ORDER BY IDdate DESC
            ; """%(",".join(lstChamps),where)

    retour = db.ExecuterReq(req, mess='GetPrixJours2')
    recordset = ()
    if retour == "ok":
        recordset = db.ResultatReq()

    # composition du dic des effectifs
    dicEffectifs = {}
    for record in recordset:
        dicEff = xformat.ListToDict(lstChamps,record)
        dicEffectifs[dicEff['IDdate']] = dicEff

    # Recherche des mouvements ------------------------------------------------------------------------
    where = getWhere('date', dtDeb, dtFinJ1)
    where += """
                        AND
                        origine in ('repas', 'camp')
                        """

    # ajoute la condition sur les codes repas choisis
    if len(lstRepasRetenus) <5:
        where += """
                        AND (repas in (%s)
                            OR (repas IS NULL))"""%str(lstRepasRetenus)[1:-1]
    lstRepasRetenus.append(None)

    if grouper == 'article':
        lstChamps = ['date', 'repas', 'stMouvements.IDarticle', 'qte', 'prixUnit', 'stArticles.rayon']
        join = "LEFT JOIN stArticles ON stArticles.IDarticle = stMouvements.IDarticle"
    else:
        lstChamps = ['date', 'repas', 'stMouvements.IDarticle', 'qte', 'prixUnit']
        join = ""

    req = """
            SELECT  %s
            FROM stMouvements
            %s
            %s
            ORDER BY stMouvements.Date DESC , stMouvements.repas
            ; """%(", ".join(lstChamps), join, where)

    retour = db.ExecuterReq(req, mess='GetPxJoursDetail')
    lstMouvements = ()
    if retour == "ok": lstMouvements = db.ResultatReq()

    # création de dictionnaires de données à partir du lstMouvements
    dicLignes = {}

    # Premier passage : regroupement sur la clé grouper ----------------------------------------------
    for record in lstMouvements:
        date = record[0]
        codeRepas = record[1]
        # on ne retient que les repas à inclure
        if not codeRepas in lstRepasRetenus: continue
        # seuls les pt dej au delà de date fin sont pris
        date = xformat.DateSqlToDatetime(date)
        if codeRepas == 1:
            # Ptit dèj: reculer d'un jour pour se rattacher au soir
            date = xformat.DecaleDateTime(date,-1)
        if date > dtFin or date < dtDeb : continue
        IDarticle = ""
        date, rayon, keyLigne = None, None, None

        if grouper == 'date':
            date, codeRepas, IDarticle, qteConso, prixUnit = record
            date = record[0]
            IDarticle = ""
            keyLigne = date
        elif grouper == 'article':
            date, codeRepas, IDarticle, qteConso, prixUnit, rayon = record
            keyLigne = IDarticle
            date = None
        elif grouper == 'ensemble':
            date, codeRepas, IDarticle, qteConso, prixUnit = record
            date = None
            IDarticle = ""
            keyLigne = 'ensemble'

        if not keyLigne in dicLignes.keys():
            dicLignes[keyLigne] = {'IDarticle': IDarticle,
                                'date': date,
                                'rayon': rayon,
                                'qteConso': 0.0,
                                'cout': {},
                                }
            # on garde le distingo par repas à cause des valeurs unitaires à calculer en final
            for code in lstRepasRetenus:
                dicLignes[keyLigne]['cout'][code] = 0.0
        dicLignes[keyLigne]['cout'][codeRepas] += round(-qteConso * prixUnit,6)
        dicLignes[keyLigne]['qteConso'] -= qteConso

    # Deuxième passage: Calcul des composants de la ligne regroupée -----------------------------------
    lstDonnees = []
    for keyLigne,dic in dicLignes.items():
        # calcul du coût midi et soir
        cout = 0.0
        lstCodRepas = [] # listes des différents repas servis pour cette clé
        for codeRepas, value in dic['cout'].items():
            cout += value
            if value >0 and not codeRepas in lstCodRepas:
                lstCodRepas.append(codeRepas)
        # test présence des différents repas servis
        effSoir = (1 in lstCodRepas or 3 in lstCodRepas or 4 in lstCodRepas) # présence de repas du soir
        effMidi = (2 in lstCodRepas)
        repasIndef = (5 in lstCodRepas or 0 in lstCodRepas or None in lstCodRepas) # présence de repas indéterminés

        # finalisation selon les cases cochées lors de la demande
        if dlg.matin and not (dlg.midi or dlg.soir):
            effSoir = True # le cout matin seul sera divisé par l'effectif du soir seul
            effMidi = False
        if repasIndef:
            # il y a des repas indéfinis, on ne s'occupe que des cases cochées
            effMidi, effSoir = False, False
            if dlg.midi: effMidi = True
            if dlg.soir or dlg.matin: effSoir = True

        nbClientsLigne = 0
        diviseurCli = 0
        nbRepasLigne = 0
        for key, dicEff in dicEffectifs.items():
            # calcul du nombre de client à retenir pour la journée
            if grouper == 'date':
                if key != keyLigne:
                    continue
            nbRepasLigne = xformat.Nz(dicEff['midiRepas']) + xformat.Nz(dicEff['soirRepas'])
            # force le service de repas clients si saisie d'effectifs
            if effMidi or xformat.Nz(dicEff['midiClients']) > 0:
                # service du midi
                nbClientsLigne += xformat.Nz(dicEff['midiClients'])
                if nbClientsLigne > 0: diviseurCli +=1
            if effSoir or xformat.Nz(dicEff['soirClients']) >0:
                #  ajout du service du soir + 5ème et ptdèjJ1
                nbClientsLigne += xformat.Nz(dicEff['soirClients'])
                if nbClientsLigne > 0: diviseurCli +=1

        # le client compte toujours un si présent seulement le midi ou le soir ou toute la journée
        if diviseurCli == 0: diviseurCli = 1
        nbClientsLigne = nbClientsLigne / diviseurCli
        
        prixRepas = cout
        prixClient = cout
        if nbRepasLigne > 0:
            prixRepas = cout / nbRepasLigne
        if nbClientsLigne > 0:
            prixClient = cout / nbClientsLigne
        if abs(dic['qteConso']) > 0:
            prixUn = cout / dic['qteConso']
        else:
            prixUn = cout

        if grouper == 'article':
            ligne = [   None,
                    dic['IDarticle'],
                    dic['rayon'],
                    dic['qteConso'],
                    prixUn,
                    cout,
                    nbRepasLigne,
                    prixRepas,
                    nbClientsLigne,
                    prixClient,]

        elif grouper == 'date':
            ligne = [  None,
                    dic['date'],
                    nbRepasLigne,
                    nbClientsLigne,
                    prixRepas,
                    prixClient,
                    cout]
        elif grouper == 'ensemble':
            ligne = [cout,nbRepasLigne,nbClientsLigne] # nombres à regrouper
        lstDonnees.append(ligne)
    return lstDonnees