File: odfviews.py

package info (click to toggle)
slm 2.12-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,520 kB
  • sloc: python: 15,419; javascript: 5,061; makefile: 184; sh: 182; xml: 57
file content (382 lines) | stat: -rw-r--r-- 13,564 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
"""
    gestion.odfviews, un module pour SLM
    - rendu d'information sous forme de document pour LibreOffice

    Copyright (C) 2023 Georges Khaznadar <georgesk@debian.org>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

from odf.opendocument import OpenDocumentSpreadsheet, OpenDocumentText
from odf.style import Style, ParagraphProperties, TableColumnProperties
from odf import style
from odf.text import H, P
from odf.table import Table, TableColumn, TableRow, TableCell

from io import BytesIO
from datetime import datetime

from django.http import FileResponse
from django.db.models import Count, Q
from django.views.decorators.csrf import ensure_csrf_cookie

from .models import Prets, Eleves, Classes, DATE111, Eleves_de_siecle, Caution
from .version import this_version

@ensure_csrf_cookie
def tableauSortantsPasAjour(request):
    """
    produit un fichier ODS avec des informations sur les élèves sortants,
    qui ne sont pas à jour pour rendre leurs livres prêtés.
    le POST contient un paramètre ids avec une liste d'identifiants d'élèves
    séparés par des virgules
    """
    ids = request.POST.get("ids").split(",")
    liste_eleves = Eleves.objects.filter(id__in = ids)
    fields_eleve = {
        "Nom_de_famille": "Nom de famille",
        "Prenom" : "Prénom",
        "Lib_Structure" : "Classe",
        "Tel_Portable" : "Téléphone portable",
        "Adresse" : "Adresse",
        "Nom_de_famille_Repr_Leg" : "Nom du représentant légal",
        "Prenom_Repr_Leg" : "Prénom du représentant légal",
        "Tel_Portable_Repr_Leg" : "Téléphone portable du représentant légal",
    }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=2+len(fields_eleve),stylename=widthshort))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)
        
    tc = TableCell() # nmuéro de caution
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Numéro de caution")
    tc.addElement(p)
    
    tc = TableCell() # caution non remboursée
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Caution non rendue")
    tc.addElement(p)
    
    tc = TableCell() # nombre de livres dus
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Nombre de livres non rendus")
    tc.addElement(p)

    tc = TableCell() # livres dus
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Livres non rendus")
    tc.addElement(p)

    for e in liste_eleves:
        # considérons tous les prêts à l'élève
        livres_non_rendus = Prets.objects.filter(eleve=e)
        try:
            caution_en_cours = Caution.objects.get(
                numero = e.no_caution).somme_payee
        except Exception as err:
            caution_en_cours = -1 # signe qu'il y a un bug !
        # retenons ceux qui ne sont pas encore rendus ni déclarés persus
        livres_non_rendus = livres_non_rendus.filter(
            ~Q(date_retour__gt = DATE111) &
            ~Q(Date_Declaration_Perte__gt = DATE111)
        )
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)

        # numéro de caution
        tc = TableCell(valuetype="float", value = e.no_caution)
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(e.no_caution))
        tc.addElement(p)
        
        # caution non rendue
        tc = TableCell(valuetype="float", value = caution_en_cours)
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(caution_en_cours))
        tc.addElement(p)
        
        # nombre de livres non rendus
        tc = TableCell(valuetype="float", value = len(livres_non_rendus))
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=str(len(livres_non_rendus)))
        tc.addElement(p)

        # titres des livres non rendus
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,
              text=", ". \
              join([liv.inventaire.materiel.titre for liv in livres_non_rendus]))
        tc.addElement(p)
        

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    return FileResponse(
        buffer,
        as_attachment=True,
        filename="Eleves_pas_a_jour.ods")

    

def listes_eleves_ODT(request):
    """
    Crée une liste des élèves éditable (format ODT) et imprimable.
    une page par classe (triées 2nde > 1ere > Term) avec le nom de la classe,
    la date d'impression, le nom du PP, le nom du CPE, et dans chaque page un
    tableau avec des lignes d'élèves (ordonnés alphabétiquement ; chaque ligne
    comprend un N° de coop, une case à cocher (pris des livres : oui/non),
    nom et prénom, liste succinte des options/spécialités
    """
    doc = OpenDocumentText()
    # Create a style for the paragraph with page-break
    withbreak = Style(
        name="WithBreak", parentstylename="Standard", family="paragraph")
    withbreak.addElement(ParagraphProperties(breakbefore="page"))
    doc.automaticstyles.addElement(withbreak)

    # styles de largeur pour tableau
    w1 = Style(name="W1", family="table-column")
    w1.addElement(TableColumnProperties(columnwidth="1cm"))
    doc.automaticstyles.addElement(w1)
    w2 = Style(name="W2", family="table-column")
    w2.addElement(TableColumnProperties(columnwidth="0.5cm"))
    doc.automaticstyles.addElement(w2)
    w3 = Style(name="W3", family="table-column")
    w3.addElement(TableColumnProperties(columnwidth="10cm"))
    doc.automaticstyles.addElement(w3)
    
    h1style = style.Style(name="Heading 1", family="paragraph")
    h1style.addElement(
        style.TextProperties(attributes={
            'fontsize': "24pt",
            'fontweight': "bold"
        }))
    doc.styles.addElement(h1style)

    boldstyle = style.Style(name="Bold", family="text")
    boldstyle.addElement(
        style.TextProperties(attributes={'fontweight': "bold"}))
    doc.automaticstyles.addElement(boldstyle)


    firstpage = True
    for classe in Classes.classes_importantes():
        timbre_date = f"Date : {datetime.now().strftime('%d/%m/%Y')} ; " + \
            f"imprimé par SLM, version {this_version}"
        if firstpage:
            p = P(text=timbre_date)
        else:
            p = P(stylename=withbreak, text=timbre_date)
        doc.text.addElement(p)
        doc.text.addElement(P(text = "PP :"))
        doc.text.addElement(P(text = "CPE :"))
        firstpage = False
        h = H(outlinelevel=1, stylename=h1style,
              text=f"Élèves de la {classe.libelle}")
        doc.text.addElement(h)
        table = Table()
        table.addElement(TableColumn(stylename=w1))
        table.addElement(TableColumn(stylename=w2))
        table.addElement(TableColumn(stylename=w3))
        doc.text.addElement(table)
        for eleve in Eleves.objects.annotate(
                num_prets=Count("prets")).filter(
                Lib_Structure = classe.libelle).order_by('NomPrenomEleve'):
            tr = TableRow()
            table.addElement(tr)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text=str(eleve.no_caution if eleve.no_caution else '...'))
            tc.addElement(p)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text="☐")
            tc.addElement(p)
            
            tc = TableCell()
            tr.addElement(tc)
            p = P(text=eleve.NomPrenomEleve)
            tc.addElement(p)

    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    return FileResponse(
        buffer,
        as_attachment=True,
        filename="Listes_eleves.odt")
    
@ensure_csrf_cookie
def print_eleves_sans_livres(request):
    """
    produit un fichier ODS avec des informations sur les élèves
    sans livres prêtés. Le POST peut apporter un paramètre "classe"
    """
    classe = request.POST.get("classe","")
    liste_sans_prets = Eleves.sans_prets_en_cours(classe)
    fields_eleve = {
        "Lib_Structure" : "Classe",
        "NomPrenomEleve": "Nom et prénom",
        "classes_passees": "Classes passées",
     }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=len(fields_eleve),stylename=widthwide))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)
        
    for e in liste_sans_prets:
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)
        

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    filename = "Eleves_sans_livres"
    if classe:
        filename += "_" + classe
    filename += ".ods"
    return FileResponse(buffer, as_attachment=True, filename=filename)

@ensure_csrf_cookie
def print_eleves_avec_livres(request):
    """
    produit un fichier ODS avec des informations sur les élèves
    avec des livres prêtés. Le POST peut apporter un paramètre "classe"
    """
    classe = request.POST.get("classe","")
    liste_sans_prets = Eleves.avec_prets_en_cours(classe)
    fields_eleve = {
        "Lib_Structure" : "Classe",
        "NomPrenomEleve": "Nom et prénom",
        "classes_passees": "Classes passées",
     }
    doc = OpenDocumentSpreadsheet()

    tablecontents = Style(name="Table Contents", family="paragraph")
    tablecontents.addElement(ParagraphProperties(
        numberlines="false", linenumber="0"))
    doc.styles.addElement(tablecontents)

    widthshort = Style(name="Wshort", family="table-column")
    widthshort.addElement(TableColumnProperties(columnwidth="1.7cm"))
    doc.automaticstyles.addElement(widthshort)

    widthwide = Style(name="Wwide", family="table-column")
    widthwide.addElement(TableColumnProperties(columnwidth="3.8cm"))
    doc.automaticstyles.addElement(widthwide)

    table = Table(name="Eleves")
    table.addElement(TableColumn(
        numbercolumnsrepeated=1+len(fields_eleve),stylename=widthwide))

    tr = TableRow()
    table.addElement(tr)
    for f in fields_eleve: # champs relatifs à l'élève
        tc = TableCell()
        tr.addElement(tc)
        p = P(stylename=tablecontents,text=fields_eleve[f])
        tc.addElement(p)

    # nombre de livres prêtés
    tc = TableCell()
    tr.addElement(tc)
    p = P(stylename=tablecontents,text="Livres prêtés")
    tc.addElement(p)
    
        
    for e in liste_sans_prets:
        tr = TableRow()
        table.addElement(tr)
        for f in fields_eleve:
            tc = TableCell()
            tr.addElement(tc)
            p = P(stylename=tablecontents,text=str(getattr(e, f)))
            tc.addElement(p)
        # nombre de livres prêtés
        tc = TableCell(valuetype="float", value=len(Prets.faits_a(e)))
        tr.addElement(tc)

    doc.spreadsheet.addElement(table)
    buffer = BytesIO()
    doc.write(buffer)
    buffer.seek(0)
    filename = "Eleves_avec_livres"
    if classe:
        filename += "_" + classe
    filename += ".ods"
    return FileResponse(buffer, as_attachment=True, filename=filename)