Skip to content

Commit

Permalink
Introduce Access Card management (#3506)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszkarykowski authored and romcheg committed Jan 16, 2020
1 parent c649389 commit 720c12c
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 0 deletions.
Empty file.
33 changes: 33 additions & 0 deletions src/ralph/access_cards/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.utils.translation import ugettext_lazy as _

from ralph.access_cards.models import AccessCard
from ralph.admin import RalphAdmin, register


@register(AccessCard)
class AccessCardAdmin(RalphAdmin):
list_display = ['status', 'visual_number', 'system_number', 'user',
'owner']
list_select_related = ['user', 'owner']
raw_id_fields = ['user', 'owner', 'region']
list_filter = ['status', 'issue_date', 'visual_number',
'system_number', 'user', 'owner', 'user__segment',
'user__company', 'user__department', 'user__employee_id']
search_fields = ['visual_number', 'system_number', 'user__first_name',
'user__last_name', 'user__username']

fieldsets = (
(
_('Access Card Info'),
{
'fields': ('visual_number', 'system_number',
'status', 'region', 'issue_date', 'notes')
}
),
(
_('User Info'),
{
'fields': ('user', 'owner')
}
)
)
25 changes: 25 additions & 0 deletions src/ralph/access_cards/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from ralph.access_cards.models import AccessCard
from ralph.accounts.api import RalphUserSimpleSerializer, RegionSerializer
from ralph.api import RalphAPISerializer, RalphAPIViewSet, router


class AccessCardSerializer(RalphAPISerializer):
user = RalphUserSimpleSerializer()
owner = RalphUserSimpleSerializer()
region = RegionSerializer()

class Meta:
model = AccessCard
fields = ['id', 'status', 'user', 'owner', 'created', 'modified',
'visual_number', 'system_number', 'issue_date', 'notes',
'region']


class AccessCardViewSet(RalphAPIViewSet):
queryset = AccessCard.objects.order_by('id').all()
select_related = ['user', 'owner', 'region']
serializer_class = AccessCardSerializer


router.register(r'access-card', AccessCardViewSet)
urlpatterns = []
41 changes: 41 additions & 0 deletions src/ralph/access_cards/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import dj.choices.fields
from django.conf import settings
import django.db.models.deletion
import ralph.access_cards.models
import ralph.lib.mixins.models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0006_remove_ralphuser_gender'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='AccessCard',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('created', models.DateTimeField(verbose_name='date created', auto_now_add=True)),
('modified', models.DateTimeField(verbose_name='last modified', auto_now=True)),
('visual_number', models.CharField(max_length=255, unique=True, help_text='Number visible on the access card')),
('system_number', models.CharField(max_length=255, unique=True, help_text='Internal number in the access system')),
('issue_date', models.DateField(blank=True, null=True, help_text='Date of issue to the User')),
('notes', models.TextField(blank=True, null=True, help_text='Optional notes')),
('status', dj.choices.fields.ChoiceField(default=1, choices=ralph.access_cards.models.AccessCardStatus, help_text='Access card status')),
('owner', models.ForeignKey(blank=True, null=True, help_text='Owner of the card', related_name='+', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
('region', models.ForeignKey(to='accounts.Region')),
('user', models.ForeignKey(blank=True, null=True, help_text='User of the card', related_name='+', on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('-modified', '-created'),
'abstract': False,
},
bases=(ralph.lib.mixins.models.AdminAbsoluteUrlMixin, models.Model),
),
]
Empty file.
81 changes: 81 additions & 0 deletions src/ralph/access_cards/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from dj.choices import Choice, Choices
from dj.choices.fields import ChoiceField
from django.db import models
from django.utils.translation import ugettext_lazy as _

from ralph.accounts.models import RalphUser, Regionalizable
from ralph.lib.mixins.models import AdminAbsoluteUrlMixin, TimeStampMixin


class AccessCardStatus(Choices):
_ = Choice

new = _('new')
in_progress = _('in progress')
lost = _('lost')
damaged = _('damaged')
used = _('in use')
free = _('free')
return_in_progress = _('return in progres')
liquidated = _('liquidated')


class AccessCard(
AdminAbsoluteUrlMixin, TimeStampMixin, Regionalizable, models.Model
):
visual_number = models.CharField(
max_length=255,
null=False,
blank=False,
unique=True,
help_text=_('Number visible on the access card')
)
system_number = models.CharField(
max_length=255,
null=False,
blank=False,
unique=True,
help_text=_('Internal number in the access system')
)
issue_date = models.DateField(
null=True,
blank=True,
help_text=_('Date of issue to the User')
)
notes = models.TextField(
null=True,
blank=True,
help_text=_('Optional notes')
)
user = models.ForeignKey(
RalphUser,
null=True,
blank=True,
related_name='+',
help_text=_('User of the card'),
on_delete=models.SET_NULL
)
owner = models.ForeignKey(
RalphUser,
null=True,
blank=True,
related_name='+',
help_text=('Owner of the card'),
on_delete=models.SET_NULL
)
status = ChoiceField(
choices=AccessCardStatus,
default=AccessCardStatus.new.id,
null=False,
blank=False,
help_text=_('Access card status')
)

def __str__(self):
return _('Access Card: {}').format(self.visual_number)

@classmethod
def get_autocomplete_queryset(cls):
return cls._default_manager.exclude(
status=AccessCardStatus.liquidated.id
)
Empty file.
16 changes: 16 additions & 0 deletions src/ralph/access_cards/tests/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import factory
from factory.django import DjangoModelFactory

from ralph.access_cards.models import AccessCard, AccessCardStatus
from ralph.accounts.tests.factories import RegionFactory


class AccessCardFactory(DjangoModelFactory):
visual_number = factory.Sequence(lambda n: '000000000000{}'.format(n))
system_number = factory.Sequence(lambda n: '000000000000{}'.format(n))
region = factory.SubFactory(RegionFactory)
status = AccessCardStatus.new

class Meta:
model = AccessCard
django_get_or_create = ['visual_number', 'system_number']
101 changes: 101 additions & 0 deletions src/ralph/access_cards/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from datetime import datetime

from rest_framework import status
from rest_framework.reverse import reverse

from ralph.access_cards.tests.factories import AccessCardFactory
from ralph.accounts.tests.factories import RegionFactory
from ralph.api.tests._base import RalphAPITestCase
from ralph.tests.factories import UserFactory


class AccessCardTestCase(RalphAPITestCase):
def assertAccessCardHasCertainFieldsAndValues(
self, access_card, response_data
):
self.assertEqual(response_data['status'], access_card.status.name)
self.assertEqual(
response_data['system_number'],
access_card.system_number
)
self.assertEqual(
response_data['visual_number'],
access_card.visual_number
)
self.assertEqual(
response_data['issue_date'],
access_card.issue_date.strftime('%Y-%m-%d')
)
self.assertEqual(response_data['notes'], access_card.notes)
self.assertEqual(
response_data['user']['username'],
access_card.user.username
)
self.assertEqual(
response_data['owner']['username'],
access_card.owner.username
)
self.assertEqual(
response_data['region']['id'],
access_card.region.id
)

def test_detail_access_card_returns_expected_fields(self):
access_card = AccessCardFactory(
issue_date=datetime.now(),
user=UserFactory(),
owner=UserFactory(),
notes='test'
)

url = reverse('accesscard-detail', args=(access_card.id,))
response = self.client.get(url)
self.assertEqual(status.HTTP_200_OK, response.status_code)

self.assertAccessCardHasCertainFieldsAndValues(
access_card, response.data
)

def test_list_access_card_returns_expected_fields(self):
access_card1 = AccessCardFactory(
issue_date=datetime.now(),
user=UserFactory(),
owner=UserFactory(),
notes='test'
)
access_card2 = AccessCardFactory(
issue_date=datetime.now(),
user=UserFactory(),
owner=UserFactory(),
notes='test'
)

url = reverse('accesscard-list')
response = self.client.get(url)
self.assertEqual(status.HTTP_200_OK, response.status_code)

self.assertAccessCardHasCertainFieldsAndValues(
access_card1, response.data['results'][0]
)

self.assertAccessCardHasCertainFieldsAndValues(
access_card2, response.data['results'][1]
)

def test_class_access_card_test_case(self):
region = RegionFactory()

access_card = {
'status': "in use",
'visual_number': '654321',
'system_number': 'F9876DSGV',
'notes': 'test note',
'issue_date': '2020-01-02',
'region': region.id
}
url = reverse('accesscard-list')
response = self.client.post(url, data=access_card)
self.assertEqual(status.HTTP_201_CREATED, response.status_code)

for field in access_card:
self.assertEqual(response.data[field], access_card[field])
1 change: 1 addition & 0 deletions src/ralph/admin/sitetrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def section(section_name, app, model):
url_as_pattern=False,
perms_mode_all=False,
children=[
section(_('Access Cards'), 'access_cards', 'AccessCard'),
section(_('Hardware'), 'back_office', 'backofficeasset'),
section(_('SIM Cards'), 'sim_cards', 'SIMCard'),
]
Expand Down
1 change: 1 addition & 0 deletions src/ralph/admin/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

FACTORY_MAP = {
'django.contrib.auth.models.Group': 'ralph.accounts.tests.factories.GroupFactory', # noqa
'ralph.access_cards.models.AccessCard': 'ralph.access_cards.tests.factories.AccessCardFactory', # noqa
'ralph.accounts.models.RalphUser': 'ralph.accounts.tests.factories.UserFactory', # noqa
'ralph.accounts.models.Region': 'ralph.accounts.tests.factories.RegionFactory', # noqa
'ralph.accounts.models.Team': 'ralph.accounts.tests.factories.TeamFactory',
Expand Down
1 change: 1 addition & 0 deletions src/ralph/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def get_sentinels(sentinels_string):
'mptt',
'reversion',
'sitetree',
'ralph.access_cards',
'ralph.accounts',
'ralph.assets',
'ralph.attachments',
Expand Down
1 change: 1 addition & 0 deletions src/ralph/urls/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# notice that each module should have `urlpatters` variable defined
# (as empty list if there is any custom url)
api_urls = list(map(lambda u: url(r'^', include(u)), [
'ralph.access_cards.api',
'ralph.accounts.api',
'ralph.assets.api.routers',
'ralph.back_office.api',
Expand Down

0 comments on commit 720c12c

Please sign in to comment.