|
| @@ -4,9 +4,9 @@ from django.utils.translation import ugettext_lazy as _ |
| @@ -4,9 +4,9 @@ from django.utils.translation import ugettext_lazy as _ |
|
4
| |
4
| |
|
5
| from django import forms |
5
| from django import forms |
|
6
| from django.core.urlresolvers import reverse_lazy |
6
| from django.core.urlresolvers import reverse_lazy |
|
7
| - |
7
| +from amadeus import settings |
|
8
| from django.contrib import messages |
8
| from django.contrib import messages |
|
9
| - |
9
| +from os.path import join |
|
10
| import django.views.generic as generic |
10
| import django.views.generic as generic |
|
11
| from mural.models import SubjectPost, Comment, MuralVisualizations |
11
| from mural.models import SubjectPost, Comment, MuralVisualizations |
|
12
| from django.db.models import Q |
12
| from django.db.models import Q |
|
| @@ -20,6 +20,7 @@ from collections import OrderedDict |
| @@ -20,6 +20,7 @@ from collections import OrderedDict |
|
20
| from django.forms import formset_factory |
20
| from django.forms import formset_factory |
|
21
| from .models import ReportCSV, ReportXLS |
21
| from .models import ReportCSV, ReportXLS |
|
22
| import pandas as pd |
22
| import pandas as pd |
|
| |
23
| +from io import BytesIO |
|
23
| |
24
| |
|
24
| class ReportView(LoginRequiredMixin, generic.FormView): |
25
| class ReportView(LoginRequiredMixin, generic.FormView): |
|
25
| template_name = "reports/create.html" |
26
| template_name = "reports/create.html" |
|
| @@ -133,11 +134,13 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -133,11 +134,13 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
133
| context['end_date'] = params_data['end_date'] |
134
| context['end_date'] = params_data['end_date'] |
|
134
| context['subject'] = subject |
135
| context['subject'] = subject |
|
135
| |
136
| |
|
| |
137
| + #I used getlist method so it can get more than one tag and one resource class_name |
|
136
| resources = params_data.getlist('resource') |
138
| resources = params_data.getlist('resource') |
|
137
| tags = params_data.getlist('tag') |
139
| tags = params_data.getlist('tag') |
|
| |
140
| + |
|
138
| self.from_mural = params_data['from_mural'] |
141
| self.from_mural = params_data['from_mural'] |
|
139
| - #I used getlist method so it can get more than one tag and one resource class_name |
| |
|
140
| - context['data'], context['header'] = self.get_mural_data(subject, params_data['init_date'], params_data['end_date'], |
142
| + |
|
| |
143
| + context['data'], context['header'] = self.get_mural_data(subject, context['topic_name'], params_data['init_date'], params_data['end_date'], |
|
141
| resources, tags ) |
144
| resources, tags ) |
|
142
| |
145
| |
|
143
| |
146
| |
|
| @@ -154,19 +157,32 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -154,19 +157,32 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
154
| report.save() |
157
| report.save() |
|
155
| |
158
| |
|
156
| #for excel files |
159
| #for excel files |
|
157
| - """ if ReportXLS.objects.filter(user= self.request.user).count() > 0: |
160
| + if ReportXLS.objects.filter(user= self.request.user).count() > 0: |
|
158
| report = ReportXLS.objects.get(user=self.request.user) |
161
| report = ReportXLS.objects.get(user=self.request.user) |
|
159
| report.delete() |
162
| report.delete() |
|
160
| |
163
| |
|
161
| - df.drop(df.columns[[0]], axis=1, inplace=True) |
| |
|
162
| - writer = pd.ExcelWriter('pandas_simple.xlsx') |
| |
|
163
| - report = ReportXLS(user= self.request.user, xls_data = df.to_excel(writer)) |
| |
|
164
| - report.save()""" |
| |
|
165
| - |
164
| + path = join(settings.MEDIA_ROOT, 'files' , 'report'+str(self.request.user.id)+'.xls') |
|
| |
165
| + writer = pd.ExcelWriter(path) |
|
| |
166
| + df.to_excel(writer, sheet_name='first_sheet') |
|
| |
167
| + writer.save() |
|
| |
168
| + report = ReportXLS(user= self.request.user ) |
|
| |
169
| + report.xls_data.name = path |
|
| |
170
| + report.save() |
|
166
| |
171
| |
|
167
| return context |
172
| return context |
|
168
| |
173
| |
|
169
| - def get_mural_data(self, subject, init_date, end_date, resources_id, tags_id): |
174
| + |
|
| |
175
| + def get_mural_data(self, subject, topics_query, init_date, end_date, resources_type_names, tags_id): |
|
| |
176
| + """ |
|
| |
177
| + |
|
| |
178
| + Process all the data to be brough by the report |
|
| |
179
| + Subject: subject where the report is being created |
|
| |
180
| + topics_query: it's either one of the topics or all of them |
|
| |
181
| + init_date: When the reports filter of dates stars |
|
| |
182
| + end_date: When the reports filter of dates end |
|
| |
183
| + resources_type_names: resources subclasses name that were selected |
|
| |
184
| + tags_id = ID of tag objects that were selected |
|
| |
185
| + """ |
|
170
| data = {} |
186
| data = {} |
|
171
| students = subject.students.all() |
187
| students = subject.students.all() |
|
172
| formats = ["%d/%m/%Y", "%m/%d/%Y", "%Y-%m-%d"] #so it accepts english and portuguese date formats |
188
| formats = ["%d/%m/%Y", "%m/%d/%Y", "%Y-%m-%d"] #so it accepts english and portuguese date formats |
|
| @@ -177,7 +193,10 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -177,7 +193,10 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
177
| |
193
| |
|
178
| except ValueError: |
194
| except ValueError: |
|
179
| pass |
195
| pass |
|
180
| - |
196
| + if topics_query == _("All"): |
|
| |
197
| + topics = subject.topic_subject.all() |
|
| |
198
| + else: |
|
| |
199
| + topics = Topic.objects.get(id=topics_query) |
|
181
| header = ['User'] |
200
| header = ['User'] |
|
182
| |
201
| |
|
183
| #I use this so the system can gather data up to end_date 11h59 p.m. |
202
| #I use this so the system can gather data up to end_date 11h59 p.m. |
|
| @@ -186,9 +205,9 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -186,9 +205,9 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
186
| |
205
| |
|
187
| #For each student in the subject |
206
| #For each student in the subject |
|
188
| for student in students: |
207
| for student in students: |
|
189
| - data[student] = [] |
208
| + data[student.id] = [] |
|
190
| |
209
| |
|
191
| - data[student].append(student.social_name) |
210
| + data[student.id].append(student.social_name) |
|
192
| |
211
| |
|
193
| interactions = OrderedDict() |
212
| interactions = OrderedDict() |
|
194
| |
213
| |
|
| @@ -240,26 +259,26 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -240,26 +259,26 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
240
| |
259
| |
|
241
| |
260
| |
|
242
| #VAR08 through VAR_019 of documenttation: |
261
| #VAR08 through VAR_019 of documenttation: |
|
243
| - if len(resources_id) > 0: |
| |
|
244
| - resources_data = self.get_resources_and_tags_data(resources_id, tags_id, student, subject, init_date, end_date) |
262
| + if len(resources_type_names) > 0: |
|
| |
263
| + resources_data = self.get_resources_and_tags_data(resources_type_names, tags_id, student, subject, topics, init_date, end_date) |
|
245
| for key, value in resources_data.items(): |
264
| for key, value in resources_data.items(): |
|
246
| interactions[key] = value |
265
| interactions[key] = value |
|
247
| |
266
| |
|
248
| |
267
| |
|
249
| #VAR20 - number of access to mural between 6 a.m to 12a.m. |
268
| #VAR20 - number of access to mural between 6 a.m to 12a.m. |
|
250
| interactions[_('Number of access to mural between 6 a.m to 12a.m. .')] = Log.objects.filter(action="access", resource="subject", |
269
| interactions[_('Number of access to mural between 6 a.m to 12a.m. .')] = Log.objects.filter(action="access", resource="subject", |
|
251
| - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11)).count() |
270
| + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11), datetime__range=(init_date,end_date)).count() |
|
252
| |
271
| |
|
253
| #VAR21 - number of access to mural between 0 p.m to 6p.m. |
272
| #VAR21 - number of access to mural between 0 p.m to 6p.m. |
|
254
| interactions[_('Number of access to mural between 0 p.m to 6p.m. .')] = Log.objects.filter(action="access", resource="subject", |
273
| interactions[_('Number of access to mural between 0 p.m to 6p.m. .')] = Log.objects.filter(action="access", resource="subject", |
|
255
| - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17)).count() |
274
| + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17), datetime__range=(init_date,end_date)).count() |
|
256
| #VAR22 |
275
| #VAR22 |
|
257
| interactions[_('Number of access to mural between 6 p.m to 12p.m. .')] = Log.objects.filter(action="access", resource="subject", |
276
| interactions[_('Number of access to mural between 6 p.m to 12p.m. .')] = Log.objects.filter(action="access", resource="subject", |
|
258
| - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23)).count() |
277
| + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23), datetime__range=(init_date,end_date)).count() |
|
259
| |
278
| |
|
260
| #VAR23 |
279
| #VAR23 |
|
261
| interactions[_('Number of access to mural between 0 a.m to 6a.m. .')] = Log.objects.filter(action="access", resource="subject", |
280
| interactions[_('Number of access to mural between 0 a.m to 6a.m. .')] = Log.objects.filter(action="access", resource="subject", |
|
262
| - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5)).count() |
281
| + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5), datetime__range=(init_date,end_date)).count() |
|
263
| |
282
| |
|
264
| #VAR24 through 30 |
283
| #VAR24 through 30 |
|
265
| day_numbers = [0, 1, 2, 3, 4, 5, 6] |
284
| day_numbers = [0, 1, 2, 3, 4, 5, 6] |
|
| @@ -267,7 +286,7 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -267,7 +286,7 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
267
| distinct_days = 0 |
286
| distinct_days = 0 |
|
268
| for day_num in day_numbers: |
287
| for day_num in day_numbers: |
|
269
| interactions[_('Number of access to the subject on ')+ day_names[day_num]] = Log.objects.filter(action="access", resource="subject", |
288
| interactions[_('Number of access to the subject on ')+ day_names[day_num]] = Log.objects.filter(action="access", resource="subject", |
|
270
| - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num).count() |
289
| + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num, datetime__range = (init_date, end_date)).count() |
|
271
| #to save the distinct days the user has accessed |
290
| #to save the distinct days the user has accessed |
|
272
| if interactions[_('Number of access to the subject on ')+ day_names[day_num]] > 0: |
291
| if interactions[_('Number of access to the subject on ')+ day_names[day_num]] > 0: |
|
273
| distinct_days += 1 |
292
| distinct_days += 1 |
|
| @@ -276,25 +295,39 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
| @@ -276,25 +295,39 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView): |
|
276
| interactions[_("Class")] = "" |
295
| interactions[_("Class")] = "" |
|
277
| interactions[_("Performance")] = "" |
296
| interactions[_("Performance")] = "" |
|
278
| for value in interactions.values(): |
297
| for value in interactions.values(): |
|
279
| - data[student].append(value) |
298
| + data[student.id].append(value) |
|
280
| |
299
| |
|
281
| |
300
| |
|
282
| for key in interactions.keys(): |
301
| for key in interactions.keys(): |
|
283
| header.append(key) |
302
| header.append(key) |
|
284
| return data, header |
303
| return data, header |
|
285
| |
304
| |
|
286
| - def get_resources_and_tags_data(self, resources_types, tags, student, subject, init_date, end_date): |
305
| + def get_resources_and_tags_data(self, resources_types, tags, student, subject, topics, init_date, end_date): |
|
287
| data = OrderedDict() |
306
| data = OrderedDict() |
|
288
| - |
307
| + |
|
289
| for i in range(len(resources_types)): |
308
| for i in range(len(resources_types)): |
|
290
| |
309
| |
|
291
| - resources = Resource.objects.select_related(resources_types[i].lower()).filter(tags__in = tags, topic__in=subject.topic_subject.all()) |
310
| + if isinstance(topics,Topic): |
|
| |
311
| + resources = Resource.objects.select_related(resources_types[i].lower()).filter(tags__in = tags, topic=topics) |
|
| |
312
| + else: |
|
| |
313
| + resources = Resource.objects.select_related(resources_types[i].lower()).filter(tags__in = tags, topic__in=topics) |
|
292
| distinct_resources = 0 |
314
| distinct_resources = 0 |
|
293
| total_count = 0 |
315
| total_count = 0 |
|
| |
316
| + |
|
294
| for resource in resources: |
317
| for resource in resources: |
|
295
| - count = Log.objects.filter(action="view", resource=resources_types[i].lower(), |
| |
|
296
| - user_id = student.id, context__contains = {'subject_id': subject.id, |
| |
|
297
| - resources_types[i].lower()+'_id': resource.id}, datetime__range=(init_date, end_date)).count() |
318
| + if isinstance(topics,Topic): |
|
| |
319
| + #or it selected only one topic to work with |
|
| |
320
| + count = Log.objects.filter(action="view", resource=resources_types[i].lower(), |
|
| |
321
| + user_id = student.id, context__contains = {'subject_id': subject.id, |
|
| |
322
| + resources_types[i].lower()+'_id': resource.id, 'topic_id': topics.id}, datetime__range=(init_date, end_date)).count() |
|
| |
323
| + |
|
| |
324
| + else: |
|
| |
325
| + #or the user selected all |
|
| |
326
| + |
|
| |
327
| + count = Log.objects.filter(action="view", resource=resources_types[i].lower(), |
|
| |
328
| + user_id = student.id, context__contains = {'subject_id': subject.id, |
|
| |
329
| + resources_types[i].lower()+'_id': resource.id}, datetime__range=(init_date, end_date)).count() |
|
| |
330
| + |
|
298
| if count > 0: |
331
| if count > 0: |
|
299
| distinct_resources += 1 |
332
| distinct_resources += 1 |
|
300
| total_count += count |
333
| total_count += count |
|
| @@ -366,7 +399,7 @@ def get_tags(request): |
| @@ -366,7 +399,7 @@ def get_tags(request): |
|
366
| |
399
| |
|
367
| #adding empty tag for the purpose of giving the user this option for adicional behavior |
400
| #adding empty tag for the purpose of giving the user this option for adicional behavior |
|
368
| tags = list(tags) |
401
| tags = list(tags) |
|
369
| - tags.append(Tag(name="")) |
402
| + tags.append(Tag(name=" ")) |
|
370
| data['tags'] = [ {'id':tag.id, 'name':tag.name} for tag in tags] |
403
| data['tags'] = [ {'id':tag.id, 'name':tag.name} for tag in tags] |
|
371
| return JsonResponse(data) |
404
| return JsonResponse(data) |
|
372
| |
405
| |
|
| @@ -377,4 +410,12 @@ def download_report_csv(request): |
| @@ -377,4 +410,12 @@ def download_report_csv(request): |
|
377
| response = HttpResponse(report.csv_data,content_type='text/csv') |
410
| response = HttpResponse(report.csv_data,content_type='text/csv') |
|
378
| response['Content-Disposition'] = 'attachment; filename="report.csv"' |
411
| response['Content-Disposition'] = 'attachment; filename="report.csv"' |
|
379
| |
412
| |
|
| |
413
| + return response |
|
| |
414
| + |
|
| |
415
| +def download_report_xls(request): |
|
| |
416
| + report = ReportXLS.objects.get(user= request.user) |
|
| |
417
| + |
|
| |
418
| + response = HttpResponse(report.xls_data,content_type='application/ms-excel') |
|
| |
419
| + response['Content-Disposition'] = 'attachment; filename="report.xls"' |
|
| |
420
| + |
|
380
| return response |
421
| return response |
|
381
| \ No newline at end of file |
422
| \ No newline at end of file |