Skip to content

Commit

Permalink
Merge pull request #1 from openimis/feature/OM-77
Browse files Browse the repository at this point in the history
  • Loading branch information
dborowiecki authored Nov 27, 2023
2 parents 6f21b47 + b320c9a commit ce36c7e
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 36 deletions.
9 changes: 4 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ on:
jobs:
call:
name: Default CI Flow
uses: openimis/openimis-be_py/.github/workflows/ci_module.yml@develop
uses: openimis/openimis-be_py/.github/workflows/ci_module.yml@moldova
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
SONAR_PROJECT_KEY: openimis_openimis-be-tasks_management_py
SONAR_PROJECT_KEY: openimis_openimis-be-worker_voucher_py
SONAR_ORGANIZATION: openimis-1
SONAR_PROJECT_NAME: openimis-be-tasks_management_py
SONAR_PROJECT_NAME: openimis-be-worker_voucher_py
SONAR_PROJECT_VERSION: 1.0
SONAR_SOURCES: tasks_management
SONAR_SOURCES: worker_voucher
SONAR_EXCLUSIONS: "**/migrations/**,**/static/**,**/media/**,**/tests/**"

4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
jobs:
deploy:

runs-on: ubuntu-20.04
runs-on: ubuntu-latest

steps:
- uses: olegtarasov/get-tag@v2.1
Expand All @@ -24,7 +24,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine jq
- name: update setup.py
run: |
echo "tag to use $GIT_TAG_NAME"
Expand Down
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
'django',
'django-db-signals',
'djangorestframework',
'openimis-be-core'
'openimis-be-insuree'
''
'openimis-be-core',
'openimis-be-insuree',
'openimis-be-policyholder',
'openimis-be-msystems'
],
classifiers=[
'Environment :: Web Environment',
Expand Down
27 changes: 27 additions & 0 deletions worker_voucher/apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
from django.apps import AppConfig

DEFAULT_CONFIG = {
"gql_worker_voucher_search_perms": ["204001"],
"gql_worker_voucher_create_perms": ["204002"],
"gql_worker_voucher_update_perms": ["204003"],
"gql_worker_voucher_delete_perms": ["204004"],
}


class WorkerVoucherConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'worker_voucher'

gql_worker_voucher_search_perms = None
gql_worker_voucher_create_perms = None
gql_worker_voucher_update_perms = None
gql_worker_voucher_delete_perms = None

def ready(self):
from core.models import ModuleConfiguration

cfg = ModuleConfiguration.get_or_default(self.name, DEFAULT_CONFIG)
self._load_config(cfg)

@classmethod
def _load_config(cls, cfg):
"""
Load all config fields that match current AppConfig class fields, all custom fields have to be loaded separately
"""
for field in cfg:
if hasattr(cls, field):
setattr(cls, field, cfg[field])
32 changes: 32 additions & 0 deletions worker_voucher/gql_queries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import graphene

from graphene_django import DjangoObjectType
from core import ExtendedConnection, prefix_filterset
from insuree.gql_queries import InsureeGQLType
from policyholder.gql import PolicyHolderGQLType
from worker_voucher.models import WorkerVoucher


class WorkerVoucherGQLType(DjangoObjectType):
uuid = graphene.String(source='uuid')

class Meta:
model = WorkerVoucher
interfaces = (graphene.relay.Node,)
filter_fields = {
"id": ["exact"],

"code": ["exact", "iexact", "istartswith", "icontains"],
"status": ["exact", "iexact", "istartswith", "icontains"],
"assigned_date": ["exact", "lt", "lte", "gt", "gte"],
"expiry_date": ["exact", "lt", "lte", "gt", "gte"],

**prefix_filterset("insuree__", InsureeGQLType._meta.filter_fields),
**prefix_filterset("policyholder__", PolicyHolderGQLType._meta.filter_fields),

"date_created": ["exact", "lt", "lte", "gt", "gte"],
"date_updated": ["exact", "lt", "lte", "gt", "gte"],
"is_deleted": ["exact"],
"version": ["exact"],
}
connection_class = ExtendedConnection
78 changes: 78 additions & 0 deletions worker_voucher/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Generated by Django 3.2.22 on 2023-11-24 08:36

import core.fields
import dirtyfields.dirtyfields
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import simple_history.models


class Migration(migrations.Migration):

initial = True

dependencies = [
('policyholder', '0017_auto_20230126_0903'),
('insuree', '0019_auto_20231026_1205'),
('core', '0025_mutationlog_json_ext'),
('msystems', '0005_fix_ward'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='WorkerVoucher',
fields=[
('id', models.UUIDField(db_column='UUID', default=None, editable=False, primary_key=True, serialize=False)),
('is_deleted', models.BooleanField(db_column='isDeleted', default=False)),
('json_ext', models.JSONField(blank=True, db_column='Json_ext', null=True)),
('date_created', core.fields.DateTimeField(db_column='DateCreated', null=True)),
('date_updated', core.fields.DateTimeField(db_column='DateUpdated', null=True)),
('version', models.IntegerField(default=1)),
('code', models.CharField(blank=True, max_length=255, null=True)),
('status', models.CharField(blank=True, choices=[('AWAITING_PAYMENT', 'Awaiting Payment'), ('UNASSIGNED', 'Unassigned'), ('ASSIGNED', 'Assigned'), ('EXPIRED', 'Expired'), ('CANCELED', 'Canceled'), ('CLOSED', 'Closed')], default='AWAITING_PAYMENT', max_length=255, null=True)),
('assigned_date', core.fields.DateField(blank=True, null=True)),
('expiry_date', core.fields.DateField(blank=True, null=True)),
('insuree', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='insuree.insuree')),
('policyholder', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='policyholder.policyholder')),
('user_created', models.ForeignKey(db_column='UserCreatedUUID', on_delete=django.db.models.deletion.DO_NOTHING, related_name='workervoucher_user_created', to=settings.AUTH_USER_MODEL)),
('user_updated', models.ForeignKey(db_column='UserUpdatedUUID', on_delete=django.db.models.deletion.DO_NOTHING, related_name='workervoucher_user_updated', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model),
),
migrations.CreateModel(
name='HistoricalWorkerVoucher',
fields=[
('id', models.UUIDField(db_column='UUID', db_index=True, default=None, editable=False)),
('is_deleted', models.BooleanField(db_column='isDeleted', default=False)),
('json_ext', models.JSONField(blank=True, db_column='Json_ext', null=True)),
('date_created', core.fields.DateTimeField(db_column='DateCreated', null=True)),
('date_updated', core.fields.DateTimeField(db_column='DateUpdated', null=True)),
('version', models.IntegerField(default=1)),
('code', models.CharField(blank=True, max_length=255, null=True)),
('status', models.CharField(blank=True, choices=[('AWAITING_PAYMENT', 'Awaiting Payment'), ('UNASSIGNED', 'Unassigned'), ('ASSIGNED', 'Assigned'), ('EXPIRED', 'Expired'), ('CANCELED', 'Canceled'), ('CLOSED', 'Closed')], default='AWAITING_PAYMENT', max_length=255, null=True)),
('assigned_date', core.fields.DateField(blank=True, null=True)),
('expiry_date', core.fields.DateField(blank=True, null=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('insuree', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='insuree.insuree')),
('policyholder', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='policyholder.policyholder')),
('user_created', models.ForeignKey(blank=True, db_column='UserCreatedUUID', db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
('user_updated', models.ForeignKey(blank=True, db_column='UserUpdatedUUID', db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical worker voucher',
'verbose_name_plural': 'historical worker vouchers',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
46 changes: 46 additions & 0 deletions worker_voucher/migrations/0002_voucher_rights.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from django.db import migrations

rights = ['204001', '204002', '204003', '204001']
roles = ['Employer', 'Inspector', 'IMIS Administrator']


def add_rights(role_name, role_model, role_right_model):
role = role_model.objects.get(name=role_name)
for right_id in rights:
if not role_right_model.objects.filter(validity_to__isnull=True, role=role, right_id=right_id).exists():
_add_right_for_role(role, right_id, role_right_model)


def _add_right_for_role(role, right_id, role_right_model):
role_right_model.objects.create(role=role, right_id=right_id, audit_user_id=1)


def remove_rights(role_id, role_right_model):
role_right_model.objects.filter(
role__is_system=role_id,
right_id__in=rights,
validity_to__isnull=True
).delete()


def on_migration(apps, schema_editor):
role_model = apps.get_model("core", "role")
role_right_model = apps.get_model("core", "roleright")
for role in roles:
add_rights(role, role_model, role_right_model)


def on_reverse_migration(apps, schema_editor):
role_right_model = apps.get_model("core", "roleright")
for role in roles:
remove_rights(role, role_right_model)


class Migration(migrations.Migration):
dependencies = [
('worker_voucher', '0001_initial'),
]

operations = [
migrations.RunPython(on_migration, on_reverse_migration),
]
23 changes: 22 additions & 1 deletion worker_voucher/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
from django.db import models
from django.utils.translation import gettext_lazy as _

# Create your models here.
from core.models import HistoryModel
from core import fields
from insuree.models import Insuree
from policyholder.models import PolicyHolder


class WorkerVoucher(HistoryModel):
class Status(models.TextChoices):
PENDING = 'AWAITING_PAYMENT', _('Awaiting Payment')
UNASSIGNED = 'UNASSIGNED', _('Unassigned')
ASSIGNED = 'ASSIGNED', _('Assigned')
EXPIRED = 'EXPIRED', _('Expired')
CANCELED = 'CANCELED', _('Canceled')
CLOSED = 'CLOSED', _('Closed')

insuree = models.ForeignKey(Insuree, null=True, blank=True, on_delete=models.DO_NOTHING)
policyholder = models.ForeignKey(PolicyHolder, null=True, blank=True, on_delete=models.DO_NOTHING)
code = models.CharField(max_length=255, blank=True, null=True)
status = models.CharField(max_length=255, blank=True, null=True, choices=Status.choices, default=Status.PENDING)
assigned_date = fields.DateField(blank=True, null=True)
expiry_date = fields.DateField(blank=True, null=True)
36 changes: 36 additions & 0 deletions worker_voucher/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import graphene
import graphene_django_optimizer as gql_optimizer

from django.db.models import Q
from django.contrib.auth.models import AnonymousUser
from core.schema import OrderedDjangoFilterConnectionField
from core.utils import append_validity_filter
from worker_voucher.apps import WorkerVoucherConfig
from worker_voucher.gql_queries import WorkerVoucherGQLType
from worker_voucher.models import WorkerVoucher


class Query(graphene.ObjectType):
module_name = "tasks_management"

worker_voucher = OrderedDjangoFilterConnectionField(
WorkerVoucherGQLType,
orderBy=graphene.List(of_type=graphene.String),
client_mutation_id=graphene.String(),
)

def resolve_worker_voucher(self, info, **kwargs):
Query._check_permissions(info.context.user, WorkerVoucherConfig.gql_worker_voucher_search_perms)
filters = append_validity_filter(**kwargs)

client_mutation_id = kwargs.get("client_mutation_id", None)
if client_mutation_id:
filters.append(Q(mutations__mutation__client_mutation_id=client_mutation_id))

query = WorkerVoucher.objects.filter(*filters)
return gql_optimizer.query(query, info)

@staticmethod
def _check_permissions(user, perms):
if type(user) is AnonymousUser or not user.id or not user.has_perms(perms):
raise PermissionError("Unauthorized")
27 changes: 19 additions & 8 deletions worker_voucher/services.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import logging
import warnings

from core.services import BaseService
from core.signals import register_service_signal
from worker_voucher.models import WorkerVoucher
from worker_voucher.validation import WorkerVoucherValidation

logger = logging.getLogger(__name__)

# Remove this code when implementing services
warnings.warn("The example code in service is still present.")

class WorkerVoucherService(BaseService):
OBJECT_TYPE = WorkerVoucher

def __init__(self, user, validation_class=WorkerVoucherValidation):
super().__init__(user, validation_class)

def example_service_function_job():
pass
@register_service_signal('worker_voucher_service.create')
def create(self, obj_data):
return super().create(obj_data)

@register_service_signal('worker_voucher_service.update')
def update(self, obj_data):
return super().update(obj_data)

class ExampleService:
def example_service_method_job(self):
pass
@register_service_signal('worker_voucher_service.delete')
def delete(self, obj_data):
return super().delete(obj_data)
17 changes: 0 additions & 17 deletions worker_voucher/tests.py
Original file line number Diff line number Diff line change
@@ -1,17 +0,0 @@
import warnings

from django.test import TestCase
from worker_voucher.services import example_service_function_job, ExampleService


class ExampleImisTest(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Remove this code when implementing tests
warnings.warn("The example code in test case is still present.")

def test_example_module_loaded_correctly(self):
example_service_function_job()
ExampleService().example_service_method_job()
self.assertTrue(True)
6 changes: 6 additions & 0 deletions worker_voucher/validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from core.validation import BaseModelValidation
from worker_voucher.models import WorkerVoucher


class WorkerVoucherValidation(BaseModelValidation):
OBJECT_TYPE = WorkerVoucher

0 comments on commit ce36c7e

Please sign in to comment.