| @@ -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 |