Commit b6711131 authored by msrr18's avatar msrr18 😑
Browse files

Merge branch '209-identificar-barrados' into 'development'

Resolve "Identificar barrados"

Closes #209

See merge request !104
parents 247798c9 5699d3f6
Pipeline #21161 passed with stage
in 2 minutes and 32 seconds
...@@ -159,6 +159,7 @@ class DegreeGridDescription: ...@@ -159,6 +159,7 @@ class DegreeGridDescription:
self.equiv_codes = obj["equiv_codes"] self.equiv_codes = obj["equiv_codes"]
self.fake_codes = obj["fake_codes"] self.fake_codes = obj["fake_codes"]
self.prerequisites = obj["prerequisites"] self.prerequisites = obj["prerequisites"]
self.phases = obj["phases"]
# Codes that show more then one time on grid, like OPT # Codes that show more then one time on grid, like OPT
self.repeated_codes = obj["repeated_codes"] self.repeated_codes = obj["repeated_codes"]
...@@ -582,9 +583,12 @@ class DegreeGrid: ...@@ -582,9 +583,12 @@ class DegreeGrid:
"CI064", "CM045", "CM005", "CI237", "CM201", "CM202", "CI166"], "CI064", "CM045", "CM005", "CI237", "CM201", "CM202", "CI166"],
"TG II": ["CI068", "CI210", "CI212", "CI055", "CI056", "CI057", "CM046", "CI067", "TG II": ["CI068", "CI210", "CI212", "CI055", "CI056", "CI057", "CM046", "CI067",
"CI064", "CM045", "CM005", "CI237", "CM201", "CM202", "CI166"], "CI064", "CM045", "CM005", "CI237", "CM201", "CM202", "CI166"],
},
}
"phases":{
"Barreira": ["CI068", "CI055", "CM046", "CM045", "CM201",
"CI210", "CI056", "CI067", "CM005", "CM202",
"CI212", "CI057", "CI064", "CI237", "CI166",]
},
}) })
...@@ -144,12 +144,21 @@ ...@@ -144,12 +144,21 @@
<td>Período pretendido</td> <td>Período pretendido</td>
<td> <td>
{% if analysis_result.periodo_pretendido %} {% if analysis_result.periodo_pretendido %}
<span class="data">{{ analysis_result.periodo_pretendido }}</span> <span class="data">
{{ analysis_result.periodo_pretendido }}
</span>
{% else %} {% else %}
<span class="data">Formado</span> <span class="data">Formado</span>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% for phase_name, phase_value in grid_phases %}
<tr>
<td>{{phase_value.description_name}} ({{phase_name}})</td>
<td><span class="data">{{phase_value.description_value}}</span></td>
</tr>
{% endfor %}
</table> </table>
</div> </div>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% load static %} {% load static %}
{% load adega_templatetag %}
{% block content %} {% block content %}
...@@ -31,120 +31,149 @@ ...@@ -31,120 +31,149 @@
<a class="nav-item nav-link" href="#abandono" aria-controls="abandono" data-toggle="tab">Abandono</a> <a class="nav-item nav-link" href="#abandono" aria-controls="abandono" data-toggle="tab">Abandono</a>
<a class="nav-item nav-link" href="#desistencia" aria-controls="desistencia" data-toggle="tab">Desistência</a> <a class="nav-item nav-link" href="#desistencia" aria-controls="desistencia" data-toggle="tab">Desistência</a>
<a class="nav-item nav-link" href="#outras" aria-controls="outras" data-toggle="tab">Outras Formas de Evasão</a> <a class="nav-item nav-link" href="#outras" aria-controls="outras" data-toggle="tab">Outras Formas de Evasão</a>
{% for phase_name, phase_value in grid_phases %}
<a class="nav-item nav-link" href="#phase_{{phase_name|remove_spaces}}" aria-controls="{{phase_name}}" data-toggle="tab">{{phase_name}}</a>
{% endfor %}
</div> </div>
<br> <br>
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="sem_evasao"> <div role="tabpanel" class="tab-pane active" id="sem_evasao">
<table class="table table-striped table-bordered" id="sem_evasao_table"> <table class="table table-striped table-bordered" id="sem_evasao_table">
<thead> <thead>
<tr> <tr>
<th class="col-md-2">GRR</th> <th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th> <th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th> <th class="col-md-2">IRA</th>
<th class="col-md-2">Forma evasão</th> <th class="col-md-2">{{sem_evasao.description_name}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for l in sem_evasao %} {% for l in sem_evasao.student_list %}
<tr> <tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.description_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div role="tabpanel" class="tab-pane" id="formados">
<table class="table table-striped table-bordered" id="formados_table">
<thead>
<tr>
<th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th>
<th class="col-md-2">{{formatura.description_name}}</th>
</tr>
</thead>
<tbody>
{% for l in formatura.student_list %}
<tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.description_value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div role="tabpanel" class="tab-pane" id="abandono">
<table class="table table-striped table-bordered" id="abandono_table">
<thead>
<tr>
<th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th>
<th class="col-md-2">{{abandono.description_name}}</th>
</tr>
</thead>
<tbody>
{% for l in abandono.student_list %}
<tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td> <td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td> <td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td> <td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.forma_evasao }}</td> <td class="col-md-2">{{ l.description_value }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div role="tabpanel" class="tab-pane" id="formados"> <div role="tabpanel" class="tab-pane" id="desistencia">
<table class="table table-striped table-bordered" id="formados_table"> <table class="table table-striped table-bordered" id="desistencia_table">
<thead> <thead>
<tr> <tr>
<th class="col-md-2">GRR</th> <th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th> <th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th> <th class="col-md-2">IRA</th>
<th class="col-md-2">Forma evasão</th> <th class="col-md-2">{{desistencia.description_name}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for l in formatura %} {% for l in desistencia.student_list %}
<tr> <tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td> <td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td> <td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td> <td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.forma_evasao }}</td> <td class="col-md-2">{{ l.description_value }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div role="tabpanel" class="tab-pane" id="abandono"> <div role="tabpanel" class="tab-pane" id="outras">
<table class="table table-striped table-bordered" id="abandono_table"> <table class="table table-striped table-bordered" id="outros_table">
<thead> <thead>
<tr> <tr>
<th class="col-md-2">GRR</th> <th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th> <th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th> <th class="col-md-2">IRA</th>
<th class="col-md-2">Forma evasão</th> <th class="col-md-2">{{outros.description_name}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for l in abandono %} {% for l in outros.student_list %}
<tr> <tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td> <td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td> <td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td> <td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.forma_evasao }}</td> <td class="col-md-2">{{ l.description_value }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div role="tabpanel" class="tab-pane" id="desistencia">
<table class="table table-striped table-bordered" id="desistencia_table">
<thead> {% for phase_name, phase_value in grid_phases %}
<tr> <div role="tabpanel" class="tab-pane" id="phase_{{phase_name|remove_spaces}}">
<th class="col-md-2">GRR</th> <table class="table table-striped table-bordered" id="phase_{{phase_name|remove_spaces}}_table">
<th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th>
<th class="col-md-2">Forma evasão</th>
</tr>
</thead>
<tbody>
{% for l in desistencia %}
<tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.forma_evasao }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div role="tabpanel" class="tab-pane" id="outras">
<table class="table table-striped table-bordered" id="outros_table">
<thead> <thead>
<tr> <tr>
<th class="col-md-2">GRR</th> <th class="col-md-2">GRR</th>
<th class="col-md-4">Nome</th> <th class="col-md-4">Nome</th>
<th class="col-md-2">IRA</th> <th class="col-md-2">IRA</th>
<th class="col-md-2">Forma evasão</th> <th class="col-md-2">{{phase_value.description_name}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for l in outros %} {% for l in phase_value.student_list %}
<tr> <tr>
<td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td> <td class="col-md-2"><a href="{% url 'student:detail' grr=l.grr submission_id=submission.id %}">{{ l.grr }}</a></td>
<td class="col-md-4">{{ l.nome }}</td> <td class="col-md-4">{{ l.nome }}</td>
<td class="col-md-2">{{ l.ira|floatformat:2 }}</td> <td class="col-md-2">{{ l.ira|floatformat:2 }}</td>
<td class="col-md-2">{{ l.forma_evasao }}</td> <td class="col-md-2">{{ l.description_value }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
{% endfor %}
</div> </div>
</div> </div>
</div> </div>
...@@ -158,7 +187,10 @@ ...@@ -158,7 +187,10 @@
$("#formados_table"), $("#formados_table"),
$("#abandono_table"), $("#abandono_table"),
$("#desistencia_table"), $("#desistencia_table"),
$("#outros_table") $("#outros_table"),
{% for phase_name, phase_value in grid_phases %}
$("#phase_{{phase_name|remove_spaces}}_table"),
{% endfor %}
]; ];
$(table_names).each(function(i,x){ $(table_names).each(function(i,x){
var t = x.dataTable({ var t = x.dataTable({
......
...@@ -13,7 +13,7 @@ from guardian.decorators import permission_required_or_403 ...@@ -13,7 +13,7 @@ from guardian.decorators import permission_required_or_403
from student.grid import DegreeGrid from student.grid import DegreeGrid
from submission.analysis.utils.situations import Situation from submission.analysis.utils.situations import Situation, EvasionForm
situations_pass = Situation.SITUATION_PASS situations_pass = Situation.SITUATION_PASS
situations_pass = [Situation.code_to_str(c) for c in situations_pass] situations_pass = [Situation.code_to_str(c) for c in situations_pass]
...@@ -40,6 +40,31 @@ def detail(request, submission_id, grr): ...@@ -40,6 +40,31 @@ def detail(request, submission_id, grr):
grid_info, grid_info_extra = dg.get_situation(hist) grid_info, grid_info_extra = dg.get_situation(hist)
grid_phases = dg.grid_detail.phases # Dictionary
# Parse to list of tuples
grid_phases_values = []
for phase_name in grid_phases:
list_phase_val = get_list_students(
request.session,
degree,
phase_name,
submission_id
)
# list_phase_val
grid_phase_desc_value = None
for student in list_phase_val["student_list"]:
if student["grr"] == grr:
grid_phase_desc_value = student["description_value"]
break
grid_phases_values.append({
"description_value": grid_phase_desc_value,
"description_name": list_phase_val["description_name"],
})
grid_phases = list(zip(grid_phases.keys(), grid_phases_values))
analysis_result = { analysis_result = {
'indice_aprovacao' : cache_j['taxa_aprovacao'], 'indice_aprovacao' : cache_j['taxa_aprovacao'],
'periodo_real': cache_j['periodo_real'], 'periodo_real': cache_j['periodo_real'],
...@@ -51,7 +76,7 @@ def detail(request, submission_id, grr): ...@@ -51,7 +76,7 @@ def detail(request, submission_id, grr):
'student': cache_j['student'], 'student': cache_j['student'],
'aluno_turmas': hist, 'aluno_turmas': hist,
'grid': grid_info, 'grid': grid_info,
'grid_extra': grid_info_extra 'grid_extra': grid_info_extra,
} }
return render(request, 'student/detail.html', { return render(request, 'student/detail.html', {
...@@ -60,6 +85,7 @@ def detail(request, submission_id, grr): ...@@ -60,6 +85,7 @@ def detail(request, submission_id, grr):
"submission": submission, "submission": submission,
"situations_pass": situations_pass, "situations_pass": situations_pass,
"situations_fail": situations_fail, "situations_fail": situations_fail,
'grid_phases': grid_phases
}) })
...@@ -103,6 +129,26 @@ def index(request, submission_id): ...@@ -103,6 +129,26 @@ def index(request, submission_id):
submission_id submission_id
) )
dg = DegreeGrid(DegreeGrid.bcc_grid_2011)
grid_phases = dg.grid_detail.phases # Dictionary
# Parse to list of tuples
grid_phases_names = list(grid_phases.keys())
active_name = EvasionForm.code_to_str(EvasionForm.EF_ATIVO)
# Collect the phases list only for active students (see student analysis)
grid_phases_names+=[p+" - "+active_name for p in grid_phases_names]
grid_phases_values = []
for phase_name in grid_phases_names:
grid_phases_values.append(
get_list_students(
request.session,
degree,
phase_name,
submission_id
)
)
grid_phases = list(zip(grid_phases_names, grid_phases_values))
return render(request, 'student/index.html', { return render(request, 'student/index.html', {
'degree': degree, 'degree': degree,
'formatura': formatura, 'formatura': formatura,
...@@ -113,5 +159,6 @@ def index(request, submission_id): ...@@ -113,5 +159,6 @@ def index(request, submission_id):
"submission": submission, "submission": submission,
"situations_pass": situations_pass, "situations_pass": situations_pass,
"situations_fail": situations_fail, "situations_fail": situations_fail,
"grid_phases": grid_phases,
}) })
...@@ -11,11 +11,13 @@ from collections import defaultdict ...@@ -11,11 +11,13 @@ from collections import defaultdict
class StudentAnalysis: class StudentAnalysis:
data_frame = None data_frame = None
def __init__(self, df, current_year, current_semester): def __init__(self, df, current_year, current_semester, dg):
self.data_frame = df self.data_frame = df
self.current_year = current_year self.current_year = current_year
self.current_semester = current_semester self.current_semester = current_semester
self.dg = dg
self._ira_alunos_last_result = None
def student_info(self, df=None): def student_info(self, df=None):
df = df if df is not None else self.data_frame df = df if df is not None else self.data_frame
...@@ -49,30 +51,73 @@ class StudentAnalysis: ...@@ -49,30 +51,73 @@ class StudentAnalysis:
return info return info
def list_students(self, df=None): def list_students_situation(self, df=None):
df = df if df is not None else self.data_frame df = df if df is not None else self.data_frame
situations = df.groupby(["MATR_ALUNO", "NOME_PESSOA", "FORMA_EVASAO"]) situations = df.groupby(["MATR_ALUNO", "NOME_PESSOA", "FORMA_EVASAO"])
situations = list(pd.DataFrame( situations = list(pd.DataFrame(
{'count': situations.size()}).reset_index().groupby(["FORMA_EVASAO"])) {'count': situations.size()}).reset_index().groupby(["FORMA_EVASAO"]))
iras = self.ira_alunos(df=df) iras = self.ira_alunos()
list_situations = defaultdict(list) list_situations = defaultdict(dict)
for sit in situations: for sit in situations:
grrs = list(sit[1]["MATR_ALUNO"]) grrs = list(sit[1]["MATR_ALUNO"])
people_names = list(sit[1]["NOME_PESSOA"]) people_names = list(sit[1]["NOME_PESSOA"])
evasion_form_name = EvasionForm.code_to_str(sit[0]) evasion_form_name = EvasionForm.code_to_str(sit[0])
student_list = []
for i, student in enumerate(grrs): for i, student in enumerate(grrs):
list_situations[sit[0]].append({ student_list.append({
"forma_evasao": evasion_form_name, "description_value": evasion_form_name,
"grr": grrs[i], "grr": grrs[i],
"ira": iras[grrs[i]], "ira": iras[grrs[i]],
"nome": people_names[i] "nome": people_names[i]
}) })
list_situations[sit[0]]["student_list"] = student_list
list_situations[sit[0]]["description_name"] = "Forma de evasão"
return list_situations return list_situations
def list_students_phases(self, df=None, only_actives=False):
df = df if df is not None else self.data_frame
iras = self.ira_alunos()
if only_actives:
df = df[df["FORMA_EVASAO"] == EvasionForm.EF_ATIVO]
groups = df.groupby("MATR_ALUNO")
# Parse phases lists to sets before start the checkage
phases = self.dg.grid_detail.phases
set_phases = {p:set(phases[p]) for p in phases}
list_phases = defaultdict(dict)
for s in set_phases:
phase_name = s
if only_actives:
phase_name+=" - "+EvasionForm.code_to_str(EvasionForm.EF_ATIVO)
student_list = []
for grr,group in groups:
# Each row of sub dataframe have the same "NOME_PESSOA" value
people_name = group["NOME_PESSOA"][0]
group = group[group['SITUACAO'].isin(Situation.SITUATION_PASS)]
approved_courses = set(group["COD_ATIV_CURRIC"].values)
# Total if courses needed fot a student complete a phase
debpt = len(set_phases[s] - approved_courses)
student_list.append({
"grr":grr,
"nome": people_name,
"ira": iras[grr],
"description_value":debpt,
})
list_phases[phase_name]["student_list"] = student_list
list_phases[phase_name]["description_name"] = "Disciplinas restantes"
return list_phases
def ira_alunos(self, df=None): def ira_alunos(self, df=None):
""" """
...@@ -91,8 +136,14 @@ class StudentAnalysis: ...@@ -91,8 +136,14 @@ class StudentAnalysis:
-------- --------
iras = { GRR: number, ...} iras = { GRR: number, ...}
""" """
df = df if df is not None else self.data_frame df = df if df is not None else self.data_frame
# Verify if exist cache for default dataframe result
if not (self._ira_alunos_last_result is None) and df.equals(self.data_frame):
return self._ira_alunos_last_result
iras = self.ira_por_quantidade_disciplinas(df=df) iras = self.ira_por_quantidade_disciplinas(df=df)