Skip to content

Commit a51de7c

Browse files
committed
Add tabs and extra buttons to audit dashboard for managing recall requests
1 parent 0f81a9b commit a51de7c

File tree

2 files changed

+164
-72
lines changed

2 files changed

+164
-72
lines changed

tally_ho/apps/tally/templates/audit/dashboard.html

Lines changed: 132 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,147 @@
44

55
{% block content %}
66

7-
<h1>{% trans 'Audit List' %}</h1>
7+
<h1>{% trans 'Audit Dashboard' %}</h1>
88

9-
<form method="get" action="{% url 'audit-csv' tally_id 'csv' %}">
10-
<button type="submit" class="btn btn-primary btn-small pull-right">
11-
{% trans 'Download' %}
12-
</button>
13-
</form>
9+
{% if messages %}
10+
<div class="messages">
11+
{% for message in messages %}
12+
<div class="alert alert-{{ message.tags }}">{{ message }}</div>
13+
{% endfor %}
14+
</div>
15+
{% endif %}
1416

15-
<br/>
17+
{# Tabs #}
18+
<ul class="nav nav-tabs">
19+
<li class="{% if active_tab == 'audit' %}active{% endif %}">
20+
<a href="{% url 'audit_dashboard' tally_id %}?tab=audit">{% trans 'Forms Awaiting Audit' %}</a>
21+
</li>
22+
<li class="{% if active_tab == 'recalls' %}active{% endif %}">
23+
<a href="{% url 'audit_dashboard' tally_id %}?tab=recalls">{% trans 'Archive Recall Requests' %}</a>
24+
</li>
25+
</ul>
1626

17-
<form method="get" action="{% url 'audit-new' tally_id %}">
18-
<button type="submit" class="btn btn-primary btn-small pull-right">
19-
{% trans 'New Form Record' %}
20-
</button>
21-
</form>
27+
<div class="tab-content">
28+
{# Forms Awaiting Audit Tab #}
29+
<div class="tab-pane {% if active_tab == 'audit' %}active{% endif %}" id="audit-forms">
30+
<br>
31+
<div class="pull-right">
32+
<a href="{% url 'initiate_recall_request' tally_id %}" class="btn btn-info btn-small">{% trans 'Initiate Archive Recall' %}</a>
33+
&nbsp;
34+
<form method="get" action="{% url 'audit_dashboard_csv' tally_id 'csv' %}?tab=audit" style="display: inline;">
35+
<button type="submit" class="btn btn-primary btn-small">{% trans 'Download Audit List' %}</button>
36+
</form>
37+
&nbsp;
38+
<form method="get" action="{% url 'audit_create' tally_id %}" style="display: inline;">
39+
<button type="submit" class="btn btn-primary btn-small">{% trans 'New Form Record' %}</button>
40+
</form>
41+
</div>
2242

23-
<br/>
24-
<br/>
43+
<h2>{% trans 'Forms Awaiting Audit' %}</h2>
2544

26-
<table class="table table-bordered table-striped">
27-
<tr>
28-
<th>{% trans 'Barcode' %}</th>
29-
<th>{% trans 'Center Name' %}</th>
30-
<th>{% trans 'Center ID' %}</th>
31-
<th>{% trans 'Station' %}</th>
32-
<th>{% trans 'Reviewed?' %}</th>
33-
<th>{% trans 'Supervisor Reviewed?' %}</th>
34-
<th>{% trans 'Modified Date' %}</th>
35-
<th>{% trans 'Quaritine Check' %}</th>
36-
<th>{% trans 'Review' %}</th>
37-
</tr>
38-
{% for form in forms %}
39-
<tr>
40-
<td>{{ form.barcode }}</td>
41-
<td>{{ form.center.name }}</td>
42-
<td>{{ form.center.code }}</td>
43-
<td>{{ form.station_number }}</td>
44-
<td>{{ form.audit_team_reviewed }}</td>
45-
<td>{{ form.audit_supervisor_reviewed }}</td>
46-
<td>{{ form.modified_date }}</td>
47-
<td>
48-
{% for audit_quaritine_check_name in form.audit_quaritine_checks %}
49-
{% trans audit_quaritine_check_name.name %}
45+
<table class="table table-bordered table-striped">
46+
<tr>
47+
<th>{% trans 'Barcode' %}</th>
48+
<th>{% trans 'Center Name' %}</th>
49+
<th>{% trans 'Center ID' %}</th>
50+
<th>{% trans 'Station' %}</th>
51+
<th>{% trans 'Audit Team Reviewed By' %}</th>
52+
<th>{% trans 'Audit Supervisor Reviewed By' %}</th>
53+
<th>{% trans 'Modified Date' %}</th>
54+
<th>{% trans 'Quarantine Checks' %}</th>
55+
<th>{% trans 'Review' %}</th>
56+
</tr>
57+
{% for form in forms %}
58+
<tr>
59+
<td>{{ form.barcode }}</td>
60+
<td>{{ form.center.name }}</td>
61+
<td>{{ form.center.code }}</td>
62+
<td>{{ form.station_number }}</td>
63+
<td>{{ form.audit_team_reviewed }}</td>
64+
<td>{{ form.audit_supervisor_reviewed }}</td>
65+
<td>{{ form.modified_date }}</td>
66+
<td>
67+
{% for check in form.audit_quaritine_checks %}
68+
{{ check.name }}{% if not forloop.last %}, {% endif %}
69+
{% empty %}
70+
N/A
71+
{% endfor %}
72+
</td>
73+
<td>
74+
<form name="form_{{ forloop.counter }}" method="post" action="">
75+
<input type="hidden" name="result_form" value="{{ form.pk }}">
76+
<button class="btn btn-default btn-small" type="submit" name="submit">{% trans "Review" %}</button>
77+
{% csrf_token %}
78+
</form>
79+
</td>
80+
</tr>
81+
{% empty %}
82+
<tr><td colspan="9">{% trans "No forms awaiting audit." %}</td></tr>
5083
{% endfor %}
51-
</td>
52-
<td>
53-
<form name="form_{{ forloop.counter }}" method="post" action="">
54-
<input type="hidden" name="result_form" value="{{ form.pk }}">
55-
<button class="btn btn-default btn-small" type="submit" name="submit">{% trans "Review" %}</button>
56-
{% csrf_token %}
84+
</table>
85+
86+
{% include "includes/pagination.html" with objects=forms page_key='page_audit' %}
87+
</div>
88+
89+
{# Archive Recall Requests Tab #}
90+
<div class="tab-pane {% if active_tab == 'recalls' %}active{% endif %}" id="recall-requests">
91+
<br>
92+
<div class="pull-right">
93+
<form method="get" action="{% url 'audit_dashboard_csv' tally_id 'csv' %}?tab=recalls" style="display: inline;">
94+
<button type="submit" class="btn btn-primary btn-small">{% trans 'Download Recall List' %}</button>
5795
</form>
58-
</td>
59-
</tr>
60-
{% endfor %}
61-
</table>
96+
</div>
6297

63-
<div class="pagination">
64-
<span class="step-links">
65-
{% if forms.has_previous %}
66-
<a href="?page={{ forms.previous_page_number }}">{% trans 'previous' %}</a>
67-
{% endif %}
98+
<h2>{% trans 'Archive Recall Requests' %}</h2>
6899

69-
<span class="current">
70-
{% blocktrans with number=forms.number num_pages=forms.paginator.num_pages %}
71-
Page {{ number }} of {{num_pages}}.
72-
{% endblocktrans %}
73-
</span>
100+
<table class="table table-bordered table-striped">
101+
<tr>
102+
<th>{% trans 'Request ID' %}</th>
103+
<th>{% trans 'Barcode' %}</th>
104+
<th>{% trans 'Center' %}</th>
105+
<th>{% trans 'Station' %}</th>
106+
<th>{% trans 'Reason' %}</th>
107+
<th>{% trans 'Requested By' %}</th>
108+
<th>{% trans 'Requested On' %}</th>
109+
<th>{% trans 'Status' %}</th>
110+
<th>{% trans 'Action' %}</th>
111+
</tr>
112+
{% for request in recall_requests %}
113+
<tr>
114+
<td>{{ request.pk }}</td>
115+
<td>{{ request.result_form.barcode }}</td>
116+
<td>{{ request.result_form.center_name }} ({{ request.result_form.center_code }})</td>
117+
<td>{{ request.result_form.station_number }}</td>
118+
<td>{{ request.get_request_reason_display }}</td>
119+
<td>{{ request.requester.username }}</td>
120+
<td>{{ request.created_date|date:"Y-m-d H:i" }}</td>
121+
<td>{{ request.get_status_display }}</td>
122+
<td>
123+
<a href="{% url 'recall_request_detail' tally_id request.pk %}" class="btn btn-default btn-small">{% trans "View Details" %}</a>
124+
</td>
125+
</tr>
126+
{% empty %}
127+
<tr><td colspan="9">{% trans "No archive recall requests found." %}</td></tr>
128+
{% endfor %}
129+
</table>
74130

75-
{% if forms.has_next %}
76-
<a href="?page={{ forms.next_page_number }}">{% trans 'next' %}</a>
77-
{% endif %}
78-
</span>
131+
{% include "includes/pagination.html" with objects=recall_requests page_key='page_recalls' %}
132+
</div>
79133
</div>
134+
135+
{# Ensure pagination links work with tabs #}
136+
<script type="text/javascript">
137+
document.addEventListener('DOMContentLoaded', function() {
138+
var paginationLinks = document.querySelectorAll('.pagination a[href*="page_"]');
139+
paginationLinks.forEach(function(link) {
140+
var url = new URL(link.href);
141+
var currentTab = '{{ active_tab|escapejs }}';
142+
if (currentTab) {
143+
url.searchParams.set('tab', currentTab);
144+
link.href = url.toString();
145+
}
146+
});
147+
});
148+
</script>
149+
80150
{% endblock %}

tally_ho/apps/tally/views/audit.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
from tally_ho.apps.tally.models.audit import Audit
1515
from tally_ho.apps.tally.models.result_form import ResultForm
1616
from tally_ho.apps.tally.models.result_form_stats import ResultFormStats
17+
from tally_ho.apps.tally.models.workflow_request import WorkflowRequest
1718
from tally_ho.apps.tally.views.quality_control import result_form_results
1819
from tally_ho.libs.models.enums.audit_resolution import\
1920
AuditResolution
2021
from tally_ho.libs.models.enums.actions_prior import\
2122
ActionsPrior
2223
from tally_ho.libs.models.enums.form_state import FormState
24+
from tally_ho.libs.models.enums.request_type import RequestType
2325
from tally_ho.libs.permissions import groups
2426
from tally_ho.libs.views import mixins
2527
from tally_ho.libs.views.form_state import form_in_state,\
@@ -172,19 +174,39 @@ class DashboardView(LoginRequiredMixin,
172174
success_url = 'audit-review'
173175

174176
def get(self, *args, **kwargs):
175-
format_ = kwargs.get('format')
176-
tally_id = kwargs.get('tally_id')
177+
format_ = self.kwargs.get('format')
178+
tally_id = self.kwargs.get('tally_id')
177179
user_is_clerk = is_clerk(self.request.user)
180+
active_tab = self.request.GET.get('tab', 'audit')
181+
178182
form_list = forms_for_user(user_is_clerk, tally_id)
179183

180-
if format_ == 'csv':
184+
if format_ == 'csv' and active_tab == 'audit':
181185
return render_to_csv_response(form_list)
182186

183-
forms = paging(form_list, self.request)
187+
forms = paging(form_list, self.request, page_kwarg='page_audit')
184188

185-
return self.render_to_response(self.get_context_data(
186-
forms=forms, is_clerk=user_is_clerk,
187-
tally_id=tally_id))
189+
recall_requests_qs = WorkflowRequest.objects.filter(
190+
result_form__tally__id=tally_id,
191+
request_type=RequestType.RECALL_FROM_ARCHIVE
192+
).select_related(
193+
'result_form', 'requester', 'approver'
194+
).order_by('-created_date')
195+
196+
if format_ == 'csv' and active_tab == 'recalls':
197+
return render_to_csv_response(recall_requests_qs)
198+
199+
recall_requests =\
200+
paging(recall_requests_qs, self.request, page_kwarg='page_recalls')
201+
202+
context = self.get_context_data(
203+
forms=forms,
204+
is_clerk=user_is_clerk,
205+
tally_id=tally_id,
206+
recall_requests=recall_requests,
207+
active_tab=active_tab
208+
)
209+
return self.render_to_response(context)
188210

189211
def post(self, *args, **kwargs):
190212
tally_id = kwargs.get('tally_id')
@@ -207,7 +229,7 @@ class ReviewView(LoginRequiredMixin,
207229
form_class = AuditForm
208230
group_required = [groups.AUDIT_CLERK, groups.AUDIT_SUPERVISOR]
209231
template_name = "audit/review.html"
210-
success_url = 'audit'
232+
success_url = 'audit_dashboard'
211233

212234
def get(self, *args, **kwargs):
213235
tally_id = kwargs.get('tally_id')
@@ -321,7 +343,7 @@ def post(self, *args, **kwargs):
321343

322344
del self.request.session['result_form']
323345

324-
return redirect('audit', tally_id=tally_id)
346+
return redirect('audit_dashboard', tally_id=tally_id)
325347

326348
return self.render_to_response(
327349
self.get_context_data(result_form=result_form,
@@ -336,7 +358,7 @@ class CreateAuditView(LoginRequiredMixin,
336358
form_class = BarcodeForm
337359
group_required = [groups.AUDIT_CLERK, groups.AUDIT_SUPERVISOR]
338360
template_name = "barcode_verify.html"
339-
success_url = 'audit'
361+
success_url = 'audit_dashboard'
340362

341363
def get_context_data(self, **kwargs):
342364
context = super(CreateAuditView, self).get_context_data(**kwargs)

0 commit comments

Comments
 (0)