Skip to content

Commit

Permalink
Fault report on behalf of (#112)
Browse files Browse the repository at this point in the history
* Fault report on behalf of

* Translations

* Tests
  • Loading branch information
berk76 authored Nov 13, 2024
1 parent 9c3e79e commit c133ba5
Show file tree
Hide file tree
Showing 18 changed files with 493 additions and 349 deletions.
16 changes: 11 additions & 5 deletions svjis/articles/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def label_from_instance(self, obj):


class BoardForm(forms.ModelForm):
member = MemberModelChoiceField(queryset=User.objects.filter(is_active=True).order_by('last_name'))
member = MemberModelChoiceField(queryset=User.objects.filter(is_active=True).order_by('last_name', 'first_name'))

class Meta:
model = models.Board
Expand Down Expand Up @@ -311,7 +311,7 @@ class Meta:
}


class AssignedUserChoiceField(forms.ModelChoiceField):
class UserChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return f"{obj.last_name} {obj.first_name}"

Expand All @@ -323,24 +323,30 @@ class FaultReportForm(forms.ModelForm):
help_text=_(SELECT_ENTRANCE_TEXT),
label=_("Entrance"),
)
assigned_to_user = AssignedUserChoiceField(
assigned_to_user = UserChoiceField(
queryset=User.objects.filter(groups__permissions__codename='svjis_fault_resolver')
.exclude(is_active=False)
.distinct()
.order_by('last_name'),
.order_by('last_name', 'first_name'),
required=False,
label=_("Resolver"),
)
created_by_user = UserChoiceField(
queryset=User.objects.exclude(is_active=False).distinct().order_by('last_name', 'first_name'),
required=False,
label=_("On Behalf Of"),
)

class Meta:
model = models.FaultReport
fields = ("subject", "entrance", "description", "assigned_to_user", "closed")
fields = ("subject", "entrance", "description", "created_by_user", "assigned_to_user", "closed")
widgets = {
'subject': forms.widgets.TextInput(attrs={'class': 'common-input', 'size': '80'}),
'entrance': forms.widgets.Select(attrs={'class': 'common-input'}),
'description': forms.widgets.Textarea(
attrs={'class': 'common-textarea', 'rows': '5', 'cols': '80', 'wrap': True}
),
'created_by_user': forms.widgets.Select(attrs={'class': 'common-input'}),
'assigned_to_user': forms.widgets.Select(attrs={'class': 'common-input'}),
'closed': forms.widgets.CheckboxInput(attrs={'class': 'common-input', 'size': '50'}),
}
Expand Down
8 changes: 6 additions & 2 deletions svjis/articles/locale/cs/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-10 10:18+0200\n"
"POT-Creation-Date: 2024-11-11 19:21+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand All @@ -32,6 +32,10 @@ msgstr "Vchod"
msgid "Resolver"
msgstr "Řešitel"

#: articles/forms.py:337
msgid "On Behalf Of"
msgstr "Za uživatele"

#: articles/models.py:14 articles/models.py:130 articles/models.py:440
#: articles/templates/redaction_useful_link.html:13
msgid "Header"
Expand Down Expand Up @@ -318,7 +322,7 @@ msgstr "Smazat"
#: articles/templates/admin_preferences_edit.html:27
#: articles/templates/admin_user_edit.html:94
#: articles/templates/advert_edit.html:41
#: articles/templates/faults_create.html:31
#: articles/templates/faults_create.html:37
#: articles/templates/faults_edit.html:34
#: articles/templates/personal_settings_edit.html:58
#: articles/templates/personal_settings_password.html:26
Expand Down
8 changes: 6 additions & 2 deletions svjis/articles/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-10 10:18+0200\n"
"POT-Creation-Date: 2024-11-11 19:20+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand All @@ -31,6 +31,10 @@ msgstr "Entrance"
msgid "Resolver"
msgstr "Resolver"

#: articles/forms.py:337
msgid "On Behalf Of"
msgstr "On Behalf Of"

#: articles/models.py:14 articles/models.py:130 articles/models.py:440
#: articles/templates/redaction_useful_link.html:13
msgid "Header"
Expand Down Expand Up @@ -317,7 +321,7 @@ msgstr "Delete"
#: articles/templates/admin_preferences_edit.html:27
#: articles/templates/admin_user_edit.html:94
#: articles/templates/advert_edit.html:41
#: articles/templates/faults_create.html:31
#: articles/templates/faults_create.html:37
#: articles/templates/faults_edit.html:34
#: articles/templates/personal_settings_edit.html:58
#: articles/templates/personal_settings_password.html:26
Expand Down
6 changes: 6 additions & 0 deletions svjis/articles/templates/faults_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ <h1 class="page-title" id="tbl-desc">{% trans 'Fault report' %}</h1>
{{ form.description }}
</p>
{% if perms.articles.svjis_fault_resolver %}
<p>
{{ form.created_by_user.label }}<br>
{{ form.created_by_user }}
</p>
{% endif %}
{% if perms.articles.svjis_fault_resolver %}
<p>
{{ form.assigned_to_user.label }}<br>
{{ form.assigned_to_user }}
Expand Down
1 change: 1 addition & 0 deletions svjis/articles/templates/faults_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ <h1 class="page-title" id="tbl-desc">#{{ form.instance.pk }} - {{ form.instance.
<form action="{% url 'faults_fault_update' %}" method="post">
{% csrf_token %}
<input type="hidden" name="pk" value="{{ pk }}" />
<input type="hidden" name="created_by_user" value="{{ form.instance.created_by_user.pk }}" />
<p>
{{ form.subject.label }}<br>
{{ form.subject }}
Expand Down
4 changes: 4 additions & 0 deletions svjis/articles/tests/factories/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from .user import UserFactory
from .article_menu import ArticleMenuFactory
from .article import ArticleFactory
from .preferences import PreferencesFactory
from .company import CompanyFactory

__all__ = [
"ContentTypeFactory",
Expand All @@ -12,4 +14,6 @@
"UserFactory",
"ArticleMenuFactory",
"ArticleFactory",
"PreferencesFactory",
"CompanyFactory",
]
18 changes: 18 additions & 0 deletions svjis/articles/tests/factories/company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import factory

from ...models import Company


class CompanyFactory(factory.django.DjangoModelFactory):
name = factory.Faker("word")
address = factory.Faker("word")
city = factory.Faker("word")
post_code = factory.Faker("word")
phone = factory.Faker("word")
email = factory.Faker("word")
registration_no = factory.Faker("word")
vat_registration_no = factory.Faker("word")
internet_domain = factory.Faker("word")

class Meta:
model = Company
11 changes: 11 additions & 0 deletions svjis/articles/tests/factories/preferences.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import factory

from ...models import Preferences


class PreferencesFactory(factory.django.DjangoModelFactory):
key = factory.Faker("word")
value = factory.Faker("word")

class Meta:
model = Preferences
195 changes: 195 additions & 0 deletions svjis/articles/tests/test_articles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
from django.test import TestCase
from django.urls import reverse

from .testdata import ArticleDataMixin


class ArticleListTest(ArticleDataMixin, TestCase):

def do_user_test(self, username, password, for_all, for_owners, for_board, article_list):
# Login user
if username == 'anonymous':
self.client.logout()
else:
logged_in = self.client.login(username=username, password=password)
self.assertTrue(logged_in)

# Article for all
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_all.slug}))
self.assertEqual(response.status_code, for_all)

# Article for Owners
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_owners.slug}))
self.assertEqual(response.status_code, for_owners)

# Article for Board
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_board.slug}))
self.assertEqual(response.status_code, for_board)

# Main page
response = self.client.get(reverse('main'))
self.assertEqual(response.status_code, 200)

# List of Articles
res_articles = response.context['article_list']
self.assertEqual([a.header for a in res_articles], article_list)

def test_admin_user(self):
self.do_user_test(
'jarda',
'jarda',
200,
200,
200,
['For Board', 'For Owners and Board', 'For Owners', 'For All'],
)

def test_board_user(self):
self.do_user_test(
'jiri',
'jiri',
200,
200,
200,
['For Board', 'For Owners and Board', 'For Owners', 'For All'],
)

def test_owner_user(self):
self.do_user_test(
'petr',
'petr',
200,
200,
404,
['For Owners and Board', 'For Owners', 'For All'],
)

def test_vendor_user(self):
self.do_user_test(
'karel',
'karel',
200,
404,
404,
['For All'],
)

def test_anonymous_user(self):
self.do_user_test('anonymous', '', 200, 404, 404, ['For All'])

def test_top_articles(self):
# Login board user
logged_in = self.client.login(username='jiri', password='jiri')
self.assertTrue(logged_in)

# Article for all
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_all.slug}))
self.assertEqual(response.status_code, 200)

# Article for Board
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_board.slug}))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse('article', kwargs={'slug': self.article_for_board.slug}))
self.assertEqual(response.status_code, 200)

# Main page
response = self.client.get(reverse('main'))
self.assertEqual(response.status_code, 200)

# Top Articles
res_top = response.context['top_articles']
self.assertEqual(len(res_top), 2)
self.assertEqual(res_top[0]['article_id'], self.article_for_board.pk)
self.assertEqual(res_top[0]['total'], 2)
self.assertEqual(res_top[1]['article_id'], self.article_for_all.pk)
self.assertEqual(res_top[1]['total'], 1)

# Login owner user
logged_in = self.client.login(username='petr', password='petr')
self.assertTrue(logged_in)

# Main page
response = self.client.get(reverse('main'))
self.assertEqual(response.status_code, 200)

# Top Articles
res_top = response.context['top_articles']
self.assertEqual(len(res_top), 1)
self.assertEqual(res_top[0]['article_id'], self.article_for_all.pk)
self.assertEqual(res_top[0]['total'], 1)

# Logout user
self.client.logout()

# Main page
response = self.client.get(reverse('main'))
self.assertEqual(response.status_code, 200)

# Top Articles
res_top = response.context['top_articles']
self.assertEqual(len(res_top), 1)
self.assertEqual(res_top[0]['article_id'], self.article_for_all.pk)
self.assertEqual(res_top[0]['total'], 1)

def test_send_article_notifications(self):
# Login board user
logged_in = self.client.login(username='jiri', password='jiri')
self.assertTrue(logged_in)

# Send notifications for article not published
response = self.client.get(
reverse('redaction_article_notifications', kwargs={'pk': self.article_not_published.pk})
)
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 0)

# Send notifications for no one
response = self.client.get(
reverse('redaction_article_notifications', kwargs={'pk': self.article_for_no_one.pk})
)
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 0)

# Send notifications for all
response = self.client.get(reverse('redaction_article_notifications', kwargs={'pk': self.article_for_all.pk}))
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 4)
self.assertEqual(res_recipients[0].last_name, 'Beran')
self.assertEqual(res_recipients[1].last_name, 'Brambůrek')
self.assertEqual(res_recipients[2].last_name, 'Lukáš')
self.assertEqual(res_recipients[3].last_name, 'Nebus')

# Send notifications for owners
response = self.client.get(
reverse('redaction_article_notifications', kwargs={'pk': self.article_for_owners.pk})
)
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 3)
self.assertEqual(res_recipients[0].last_name, 'Beran')
self.assertEqual(res_recipients[1].last_name, 'Brambůrek')
self.assertEqual(res_recipients[2].last_name, 'Nebus')

# Send notifications for board
response = self.client.get(
reverse('redaction_article_notifications', kwargs={'pk': self.article_for_board.pk})
)
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 2)
self.assertEqual(res_recipients[0].last_name, 'Beran')
self.assertEqual(res_recipients[1].last_name, 'Brambůrek')

# Send notifications for board
response = self.client.get(
reverse('redaction_article_notifications', kwargs={'pk': self.article_for_owners_and_board.pk})
)
self.assertEqual(response.status_code, 200)
res_recipients = response.context['object_list']
self.assertEqual(len(res_recipients), 3)
self.assertEqual(res_recipients[0].last_name, 'Beran')
self.assertEqual(res_recipients[1].last_name, 'Brambůrek')
self.assertEqual(res_recipients[2].last_name, 'Nebus')
Loading

0 comments on commit c133ba5

Please sign in to comment.