Commit 1881b3ab8fde04e7401bd733c19a2ec1ba6de559

Authored by Jailson Dias
2 parents 1c94435d c08c4014

Merge branch 'refactoring' of https://github.com/amadeusproject/amadeuslms into refactoring

reports/migrations/0003_auto_20170323_1517.py 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-23 18:17
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('reports', '0002_reportxls'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='reportxls',
  17 + name='xls_data',
  18 + field=models.TextField(null=True),
  19 + ),
  20 + ]
reports/migrations/0004_auto_20170323_1520.py 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-23 18:20
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('reports', '0003_auto_20170323_1517'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='reportxls',
  17 + name='xls_data',
  18 + field=models.TextField(),
  19 + ),
  20 + ]
reports/migrations/0005_auto_20170323_1603.py 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-23 19:03
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('reports', '0004_auto_20170323_1520'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='reportxls',
  17 + name='xls_data',
  18 + field=models.FileField(upload_to='excel/'),
  19 + ),
  20 + ]
reports/migrations/0006_auto_20170323_1629.py 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-23 19:29
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.db import migrations, models
  6 +
  7 +
  8 +class Migration(migrations.Migration):
  9 +
  10 + dependencies = [
  11 + ('reports', '0005_auto_20170323_1603'),
  12 + ]
  13 +
  14 + operations = [
  15 + migrations.AlterField(
  16 + model_name='reportxls',
  17 + name='xls_data',
  18 + field=models.FileField(upload_to='files/'),
  19 + ),
  20 + ]
reports/models.py
@@ -17,7 +17,7 @@ class ReportCSV(models.Model): @@ -17,7 +17,7 @@ class ReportCSV(models.Model):
17 class ReportXLS(models.Model): 17 class ReportXLS(models.Model):
18 18
19 user = models.ForeignKey(User) 19 user = models.ForeignKey(User)
20 - xls_data = models.TextField() 20 + xls_data = models.FileField(upload_to = 'files/')
21 21
22 class Meta: 22 class Meta:
23 verbose_name = "ReportCSV" 23 verbose_name = "ReportCSV"
reports/templates/reports/view.html
@@ -65,10 +65,11 @@ @@ -65,10 +65,11 @@
65 <ul id="report-info"> 65 <ul id="report-info">
66 <li> {{data.values|length}} {% trans "register(s)" %} </li> 66 <li> {{data.values|length}} {% trans "register(s)" %} </li>
67 <li> 67 <li>
68 - <a href="{% url 'subjects:reports:download_report_csv' %}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}</a> 68 + <a href="{% url 'subjects:reports:download_report_csv' %}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data (.csv)" %}</a>
69 69
70 70
71 </li> 71 </li>
  72 + <li><a href="{% url 'subjects:reports:download_report_xls' %}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data (.xls)" %}</a></li>
72 </ul> 73 </ul>
73 74
74 75
reports/urls.py
@@ -8,4 +8,5 @@ urlpatterns = [ @@ -8,4 +8,5 @@ urlpatterns = [
8 url(r'^get/resources/$', views.get_resources, name='get_resource_and_tags'), 8 url(r'^get/resources/$', views.get_resources, name='get_resource_and_tags'),
9 url(r'^get/tags/$', views.get_tags, name='get_tags'), 9 url(r'^get/tags/$', views.get_tags, name='get_tags'),
10 url(r'^post/download_report/$', views.download_report_csv, name="download_report_csv"), 10 url(r'^post/download_report/$', views.download_report_csv, name="download_report_csv"),
  11 + url(r'^post/download_report/excel$', views.download_report_xls, name="download_report_xls"),
11 ] 12 ]
12 \ No newline at end of file 13 \ No newline at end of file
reports/views.py
@@ -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