Skip to content

Commit

Permalink
Merge pull request #42 from openimis/feature/OM-315
Browse files Browse the repository at this point in the history
OM-315: Upload of workers - backend
  • Loading branch information
malinowskikam authored Oct 22, 2024
2 parents d43bc7a + 0b09b90 commit 2305fbe
Show file tree
Hide file tree
Showing 24 changed files with 1,582 additions and 20 deletions.
23 changes: 22 additions & 1 deletion worker_voucher/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
"gql_worker_voucher_acquire_unassigned_perms": ["204006"],
"gql_worker_voucher_acquire_assigned_perms": ["204007"],
"gql_worker_voucher_assign_vouchers_perms": ["204008"],
"gql_group_of_worker_search_perms": ["205001"],
"gql_group_of_worker_create_perms": ["205002"],
"gql_group_of_worker_update_perms": ["205003"],
"gql_group_of_worker_delete_perms": ["205004"],
"gql_group_of_worker_search_all_perms": ["205005"],
"unassigned_voucher_enabled": True,
"price_per_voucher": "100.00",
"max_generic_vouchers": 1000,
Expand All @@ -24,7 +29,9 @@
# voucher_expiry_type = "fixed_period" or "end_of_year"
"voucher_expiry_type": "end_of_year",
"yearly_worker_voucher_limit": 120,
"validate_created_worker_online": False
"validate_created_worker_online": False,
"csv_worker_upload_errors_column": "errors",
"worker_upload_chf_id_type": "national_id"
}


Expand All @@ -40,6 +47,11 @@ class WorkerVoucherConfig(AppConfig, ConfigUtilMixin):
gql_worker_voucher_acquire_unassigned_perms = None
gql_worker_voucher_acquire_assigned_perms = None
gql_worker_voucher_assign_vouchers_perms = None
gql_group_of_worker_search_perms = None
gql_group_of_worker_create_perms = None
gql_group_of_worker_update_perms = None
gql_group_of_worker_delete_perms = None
gql_group_of_worker_search_all_perms = None

unassigned_voucher_enabled = None
price_per_voucher = None
Expand All @@ -49,9 +61,18 @@ class WorkerVoucherConfig(AppConfig, ConfigUtilMixin):
voucher_expiry_type = None
yearly_worker_voucher_limit = None
validate_created_worker_online = None
csv_worker_upload_errors_column = None
worker_upload_chf_id_type = None

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

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

@staticmethod
def get_worker_upload_payment_file_path(economic_unit_code, file_name=None):
if file_name:
return f"csv_worker_upload/economic_unit_{economic_unit_code}/{file_name}"
return f"csv_worker_upload/economic_unit_{economic_unit_code}"

94 changes: 93 additions & 1 deletion worker_voucher/gql_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from policyholder.services import PolicyHolderInsuree as PolicyHolderInsureeService
from worker_voucher.apps import WorkerVoucherConfig
from worker_voucher.models import WorkerVoucher
from worker_voucher.services import WorkerVoucherService, validate_acquire_unassigned_vouchers, \
from worker_voucher.services import WorkerVoucherService, GroupOfWorkerService, validate_acquire_unassigned_vouchers, \
validate_acquire_assigned_vouchers, validate_assign_vouchers, create_assigned_voucher, create_voucher_bill, \
create_unassigned_voucher, assign_voucher, economic_unit_user_filter, check_existing_active_vouchers

Expand Down Expand Up @@ -379,3 +379,95 @@ def _mutate(cls, user, count=None, economic_unit_code=None, workers=None, date_r

class Input(AssignVouchersMutationInput):
pass


class CreateOrUpdateGroupOfWorkerMutation(BaseMutation):
"""
Create a new group of worker or update existing group
"""
_mutation_module = "worker_voucher"
_mutation_class = "CreateOrUpdateGroupOfWorkerMutation"

class Input(OpenIMISMutation.Input):
id = graphene.UUID(required=False)
name = graphene.String(required=True, max_length=50)
economic_unit_code = graphene.String(required=True)
insurees_chf_id = graphene.List(graphene.String, required=True)

@classmethod
def _validate_mutation(cls, user, **data):
if type(user) is AnonymousUser or not user.id or not user.has_perms(
WorkerVoucherConfig.gql_worker_voucher_acquire_assigned_perms):
raise ValidationError("mutation.authentication_required")

@classmethod
def _mutate(cls, user, **data):
try:
data.pop('client_mutation_id', None)
data.pop('client_mutation_label', None)
eu_code = data.pop('economic_unit_code', None)
eu_uuid = (PolicyHolder.objects
.filter(economic_unit_user_filter(user), code=eu_code)
.values_list('uuid', flat=True)
.first())
if not eu_uuid:
return [{"message": _("worker_voucher.validation.economic_unit_not_exists")}]
with transaction.atomic():
data['policyholder_id'] = eu_uuid
service = GroupOfWorkerService(user)
result = service.create_or_update(data, eu_code)
if not result.get("success"):
return result
return None
except Exception as exc:
return [
{
'message': "worker_voucher.mutation.failed_to_create_or_update_group_of_worker",
'detail': str(exc)
}]


class DeleteGroupOfWorkerMutation(BaseMutation):
"""
Delete a chosen group of worker
"""
_mutation_module = "worker_voucher"
_mutation_class = "DeleteGroupOfWorkerMutation"

class Input(OpenIMISMutation.Input):
uuid = graphene.String(required=False)
uuids = graphene.List(graphene.String, required=False)
economic_unit_code = graphene.String(required=True)

@classmethod
def _validate_mutation(cls, user, **data):
if type(user) is AnonymousUser or not user.id or not user.has_perms(
WorkerVoucherConfig.gql_group_of_worker_delete_perms):
raise ValidationError("mutation.authentication_required")

@classmethod
def _mutate(cls, user, uuid=None, uuids=None, economic_unit_code=None, **data):
uuids_to_delete = [uuid] if uuid else uuids
if not uuids_to_delete:
return [{"message": _("workers.validation.no_group_of_workers_to_delete")}]

eu_uuid = (PolicyHolder.objects
.filter(economic_unit_user_filter(user), code=economic_unit_code)
.values_list('uuid', flat=True)
.first())

if not eu_uuid:
return [{"message": _("worker_voucher.validation.economic_unit_not_exists")}]

errors = []
service = GroupOfWorkerService(user)
try:
with transaction.atomic():
for group_id in uuids_to_delete:
errors += service.delete(group_id, eu_uuid)
if errors:
raise ValueError("Errors during mutation")
except ValueError:
pass

return errors
38 changes: 37 additions & 1 deletion worker_voucher/gql_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from insuree.models import Insuree
from invoice.models import Bill
from policyholder.gql import PolicyHolderGQLType
from worker_voucher.models import WorkerVoucher
from worker_voucher.models import WorkerVoucher, GroupOfWorker, WorkerGroup
from worker_voucher.services import get_worker_yearly_voucher_count_counts


Expand Down Expand Up @@ -89,3 +89,39 @@ class OnlineWorkerDataGQLType(graphene.ObjectType):
other_names = graphene.String()
last_name = graphene.String()
photo = graphene.String()


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

class Meta:
model = GroupOfWorker
interfaces = (graphene.relay.Node,)
filter_fields = {
"id": ["exact"],
"name": ["exact", "istartswith", "icontains", "iexact"],
**prefix_filterset("policyholder__", PolicyHolderGQLType._meta.filter_fields),

"date_created": ["exact", "lt", "lte", "gt", "gte"],
"date_updated": ["exact", "lt", "lte", "gt", "gte"],
"is_deleted": ["exact"],
}
connection_class = ExtendedConnection


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

class Meta:
model = WorkerGroup
interfaces = (graphene.relay.Node,)
filter_fields = {
"id": ["exact"],
"insuree_id": ["exact"],
**prefix_filterset("group__", GroupOfWorkerGQLType._meta.filter_fields),

"date_created": ["exact", "lt", "lte", "gt", "gte"],
"date_updated": ["exact", "lt", "lte", "gt", "gte"],
"is_deleted": ["exact"],
}
connection_class = ExtendedConnection
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 4.2.15 on 2024-08-13 10:50

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


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('worker_voucher', '0005_assign_voucher_rigths'),
]

operations = [
migrations.AlterField(
model_name='historicalworkervoucher',
name='date_created',
field=core.fields.DateTimeField(db_column='DateCreated', default=datetime.datetime.now, null=True),
),
migrations.AlterField(
model_name='historicalworkervoucher',
name='date_updated',
field=core.fields.DateTimeField(db_column='DateUpdated', default=datetime.datetime.now, null=True),
),
migrations.AlterField(
model_name='workervoucher',
name='date_created',
field=core.fields.DateTimeField(db_column='DateCreated', default=datetime.datetime.now, null=True),
),
migrations.AlterField(
model_name='workervoucher',
name='date_updated',
field=core.fields.DateTimeField(db_column='DateUpdated', default=datetime.datetime.now, null=True),
),
migrations.AlterField(
model_name='workervoucher',
name='user_created',
field=models.ForeignKey(db_column='UserCreatedUUID', on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(class)s_user_created', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='workervoucher',
name='user_updated',
field=models.ForeignKey(db_column='UserUpdatedUUID', on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(class)s_user_updated', to=settings.AUTH_USER_MODEL),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 4.2.15 on 2024-10-03 14:56

import core.fields
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('worker_voucher', '0006_alter_historicalworkervoucher_date_created_and_more'),
]

operations = [
migrations.AlterField(
model_name='historicalworkervoucher',
name='assigned_date',
field=core.fields.DateTimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='historicalworkervoucher',
name='expiry_date',
field=core.fields.DateTimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='workervoucher',
name='assigned_date',
field=core.fields.DateTimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='workervoucher',
name='expiry_date',
field=core.fields.DateTimeField(blank=True, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Generated by Django 4.2.15 on 2024-10-10 11:14

import core.fields
import datetime
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):

dependencies = [
('policyholder', '0018_alter_historicalpolicyholder_date_created_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('worker_voucher', '0007_alter_historicalworkervoucher_assigned_date_and_more'),
]

operations = [
migrations.CreateModel(
name='WorkerUpload',
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', default=datetime.datetime.now, null=True)),
('date_updated', core.fields.DateTimeField(db_column='DateUpdated', default=datetime.datetime.now, null=True)),
('version', models.IntegerField(default=1)),
('status', models.CharField(choices=[('TRIGGERED', 'Triggered'), ('IN_PROGRESS', 'In progress'), ('SUCCESS', 'Success'), ('FAIL', 'Fail')], default='TRIGGERED', max_length=255)),
('error', models.JSONField(blank=True, default=dict)),
('file_name', models.CharField(blank=True, max_length=255, null=True)),
('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='%(class)s_user_created', to=settings.AUTH_USER_MODEL)),
('user_updated', models.ForeignKey(db_column='UserUpdatedUUID', on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(class)s_user_updated', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model),
),
migrations.CreateModel(
name='HistoricalWorkerUpload',
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', default=datetime.datetime.now, null=True)),
('date_updated', core.fields.DateTimeField(db_column='DateUpdated', default=datetime.datetime.now, null=True)),
('version', models.IntegerField(default=1)),
('status', models.CharField(choices=[('TRIGGERED', 'Triggered'), ('IN_PROGRESS', 'In progress'), ('SUCCESS', 'Success'), ('FAIL', 'Fail')], default='TRIGGERED', max_length=255)),
('error', models.JSONField(blank=True, default=dict)),
('file_name', models.CharField(blank=True, max_length=255, 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)),
('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 upload',
'verbose_name_plural': 'historical worker uploads',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.15 on 2024-10-11 16:57

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('worker_voucher', '0008_workerupload_historicalworkerupload'),
]

operations = [
migrations.AlterField(
model_name='historicalworkerupload',
name='status',
field=models.CharField(choices=[('TRIGGERED', 'Triggered'), ('IN_PROGRESS', 'In progress'), ('SUCCESS', 'Success'), ('PARTIAL_SUCCESS', 'Partial success'), ('FAIL', 'Fail')], default='TRIGGERED', max_length=255),
),
migrations.AlterField(
model_name='workerupload',
name='status',
field=models.CharField(choices=[('TRIGGERED', 'Triggered'), ('IN_PROGRESS', 'In progress'), ('SUCCESS', 'Success'), ('PARTIAL_SUCCESS', 'Partial success'), ('FAIL', 'Fail')], default='TRIGGERED', max_length=255),
),
]
Loading

0 comments on commit 2305fbe

Please sign in to comment.