diff --git a/worker_voucher/apps.py b/worker_voucher/apps.py index 901dec3..3a597ef 100644 --- a/worker_voucher/apps.py +++ b/worker_voucher/apps.py @@ -11,6 +11,10 @@ "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"], "unassigned_voucher_enabled": True, "price_per_voucher": "100.00", "max_generic_vouchers": 1000, @@ -42,6 +46,10 @@ 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 unassigned_voucher_enabled = None price_per_voucher = None diff --git a/worker_voucher/gql_mutations.py b/worker_voucher/gql_mutations.py index 7a3e22c..839be3a 100644 --- a/worker_voucher/gql_mutations.py +++ b/worker_voucher/gql_mutations.py @@ -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 @@ -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 diff --git a/worker_voucher/gql_queries.py b/worker_voucher/gql_queries.py index 9195592..8427c27 100644 --- a/worker_voucher/gql_queries.py +++ b/worker_voucher/gql_queries.py @@ -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 @@ -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 diff --git a/worker_voucher/migrations/0010_groupofworker_workergroup_historicalworkergroup_and_more.py b/worker_voucher/migrations/0010_groupofworker_workergroup_historicalworkergroup_and_more.py new file mode 100644 index 0000000..635f2d4 --- /dev/null +++ b/worker_voucher/migrations/0010_groupofworker_workergroup_historicalworkergroup_and_more.py @@ -0,0 +1,111 @@ +# Generated by Django 4.2.15 on 2024-10-15 13:05 + +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 = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('insuree', '0023_alter_family_head_insuree'), + ('worker_voucher', '0009_alter_historicalworkerupload_status_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='GroupOfWorker', + 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)), + ('name', models.CharField(max_length=50)), + ('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='WorkerGroup', + 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)), + ('group', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='group_workers', to='worker_voucher.groupofworker')), + ('insuree', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='insuree.insuree')), + ('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='HistoricalWorkerGroup', + 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)), + ('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)), + ('group', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='worker_voucher.groupofworker')), + ('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')), + ('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 group', + 'verbose_name_plural': 'historical worker groups', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='HistoricalGroupOfWorker', + 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)), + ('name', models.CharField(max_length=50)), + ('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)), + ('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 group of worker', + 'verbose_name_plural': 'historical group of workers', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/worker_voucher/migrations/0011_historicalworkergroup_date_valid_from_and_more.py b/worker_voucher/migrations/0011_historicalworkergroup_date_valid_from_and_more.py new file mode 100644 index 0000000..f2b45e6 --- /dev/null +++ b/worker_voucher/migrations/0011_historicalworkergroup_date_valid_from_and_more.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.15 on 2024-10-15 14:30 + +import core.fields +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('worker_voucher', '0010_groupofworker_workergroup_historicalworkergroup_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='historicalworkergroup', + name='date_valid_from', + field=core.fields.DateTimeField(db_column='DateValidFrom', default=datetime.datetime.now), + ), + migrations.AddField( + model_name='historicalworkergroup', + name='date_valid_to', + field=core.fields.DateTimeField(blank=True, db_column='DateValidTo', null=True), + ), + migrations.AddField( + model_name='historicalworkergroup', + name='replacement_uuid', + field=models.UUIDField(blank=True, db_column='ReplacementUUID', null=True), + ), + migrations.AddField( + model_name='workergroup', + name='date_valid_from', + field=core.fields.DateTimeField(db_column='DateValidFrom', default=datetime.datetime.now), + ), + migrations.AddField( + model_name='workergroup', + name='date_valid_to', + field=core.fields.DateTimeField(blank=True, db_column='DateValidTo', null=True), + ), + migrations.AddField( + model_name='workergroup', + name='replacement_uuid', + field=models.UUIDField(blank=True, db_column='ReplacementUUID', null=True), + ), + ] diff --git a/worker_voucher/migrations/0012_groupofworker_policyholder_and_more.py b/worker_voucher/migrations/0012_groupofworker_policyholder_and_more.py new file mode 100644 index 0000000..b9fae2a --- /dev/null +++ b/worker_voucher/migrations/0012_groupofworker_policyholder_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.15 on 2024-10-17 09:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('policyholder', '0018_alter_historicalpolicyholder_date_created_and_more'), + ('worker_voucher', '0011_historicalworkergroup_date_valid_from_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='groupofworker', + name='policyholder', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='policyholder.policyholder'), + ), + migrations.AddField( + model_name='historicalgroupofworker', + name='policyholder', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='policyholder.policyholder'), + ), + ] diff --git a/worker_voucher/migrations/0013_alter_groupofworker_name_and_more.py b/worker_voucher/migrations/0013_alter_groupofworker_name_and_more.py new file mode 100644 index 0000000..be6f138 --- /dev/null +++ b/worker_voucher/migrations/0013_alter_groupofworker_name_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.15 on 2024-10-17 17:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('worker_voucher', '0012_groupofworker_policyholder_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='groupofworker', + name='name', + field=models.CharField(max_length=50, unique=True), + ), + migrations.AlterField( + model_name='historicalgroupofworker', + name='name', + field=models.CharField(db_index=True, max_length=50), + ), + ] diff --git a/worker_voucher/migrations/0014_alter_groupofworker_name_and_more.py b/worker_voucher/migrations/0014_alter_groupofworker_name_and_more.py new file mode 100644 index 0000000..ee9952b --- /dev/null +++ b/worker_voucher/migrations/0014_alter_groupofworker_name_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.15 on 2024-10-17 19:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('worker_voucher', '0013_alter_groupofworker_name_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='groupofworker', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='historicalgroupofworker', + name='name', + field=models.CharField(max_length=50), + ), + ] diff --git a/worker_voucher/migrations/0015_group_of_worker_rights.py b/worker_voucher/migrations/0015_group_of_worker_rights.py new file mode 100644 index 0000000..aa081e4 --- /dev/null +++ b/worker_voucher/migrations/0015_group_of_worker_rights.py @@ -0,0 +1,46 @@ +from django.db import migrations + +rights = ['205001', '205002', '205003', '205004'] +roles = ['Employer', 'IMIS Administrator'] + + +def add_rights(role_name, role_model, role_right_model): + role = role_model.objects.get(name=role_name, validity_to__isnull=True) + 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', '0014_alter_groupofworker_name_and_more'), + ] + + operations = [ + migrations.RunPython(on_migration, on_reverse_migration), + ] diff --git a/worker_voucher/models.py b/worker_voucher/models.py index c2fb623..59b96fc 100644 --- a/worker_voucher/models.py +++ b/worker_voucher/models.py @@ -1,7 +1,7 @@ from django.db import models from django.conf import settings from django.utils.translation import gettext_lazy as _ -from core.models import HistoryModel +from core.models import HistoryModel, HistoryBusinessModel from core import fields from insuree.models import Insuree from policyholder.models import PolicyHolder @@ -51,3 +51,26 @@ class Status(models.TextChoices): status = models.CharField(max_length=255, choices=Status.choices, default=Status.TRIGGERED) error = models.JSONField(blank=True, default=dict) file_name = models.CharField(max_length=255, null=True, blank=True) + + +class GroupOfWorker(HistoryModel): + name = models.CharField(max_length=50) + policyholder = models.ForeignKey(PolicyHolder, models.DO_NOTHING, null=True, blank=True) + + @classmethod + def get_queryset(cls, queryset, user): + from worker_voucher.services import get_voucher_user_filters + + queryset = cls.filter_queryset(queryset) + if isinstance(user, ResolveInfo): + user = user.context.user + if settings.ROW_SECURITY: + if user.is_anonymous: + queryset = queryset.filter(id=None) + queryset = queryset.filter(*get_voucher_user_filters(user)) + return queryset + + +class WorkerGroup(HistoryBusinessModel): + group = models.ForeignKey(GroupOfWorker, related_name="group_workers", on_delete=models.DO_NOTHING) + insuree = models.ForeignKey(Insuree, null=True, blank=True, on_delete=models.DO_NOTHING) diff --git a/worker_voucher/schema.py b/worker_voucher/schema.py index 1f24098..5f4e95e 100644 --- a/worker_voucher/schema.py +++ b/worker_voucher/schema.py @@ -16,13 +16,21 @@ from policyholder.models import PolicyHolder from worker_voucher.apps import WorkerVoucherConfig from worker_voucher.gql_queries import WorkerVoucherGQLType, AcquireVouchersValidationSummaryGQLType, WorkerGQLType, \ - OnlineWorkerDataGQLType + OnlineWorkerDataGQLType, GroupOfWorkerGQLType, WorkerGroupGQLType from worker_voucher.gql_mutations import CreateWorkerVoucherMutation, UpdateWorkerVoucherMutation, \ DeleteWorkerVoucherMutation, AcquireUnassignedVouchersMutation, AcquireAssignedVouchersMutation, \ - DateRangeInclusiveInputType, AssignVouchersMutation, CreateWorkerMutation, DeleteWorkerMutation -from worker_voucher.models import WorkerVoucher -from worker_voucher.services import get_voucher_worker_enquire_filters, validate_acquire_unassigned_vouchers, \ - validate_acquire_assigned_vouchers, validate_assign_vouchers, economic_unit_user_filter, worker_user_filter + DateRangeInclusiveInputType, AssignVouchersMutation, CreateWorkerMutation, DeleteWorkerMutation, \ + CreateOrUpdateGroupOfWorkerMutation, DeleteGroupOfWorkerMutation +from worker_voucher.models import WorkerVoucher, GroupOfWorker, WorkerGroup +from worker_voucher.services import ( + get_voucher_worker_enquire_filters, + validate_acquire_unassigned_vouchers, + validate_acquire_assigned_vouchers, + validate_assign_vouchers, + economic_unit_user_filter, + worker_user_filter, + get_group_worker_user_filters +) class Query(ExportableQueryMixin, graphene.ObjectType): @@ -80,6 +88,13 @@ class Query(ExportableQueryMixin, graphene.ObjectType): economic_unit_code=graphene.ID(), ) + group_of_worker = OrderedDjangoFilterConnectionField( + GroupOfWorkerGQLType, + orderBy=graphene.List(of_type=graphene.String), + economic_unit_code=graphene.String(), + client_mutation_id=graphene.String(), + ) + def resolve_worker(self, info, client_mutation_id=None, economic_unit_code=None, **kwargs): Query._check_permissions(info.context.user, InsureeConfig.gql_query_insurees_perms) filters = filter_validity(**kwargs) @@ -204,6 +219,17 @@ def resolve_online_worker_data(self, info, national_id=None, economic_unit_code= photo=online_result["data"]["Photo"] ) + def resolve_group_of_worker(self, info, economic_unit_code=None, **kwargs): + if not info.context.user.has_perms(WorkerVoucherConfig.gql_group_of_worker_search_perms): + raise PermissionError("Unauthorized") + filters = [] + query = GroupOfWorker.objects + client_mutation_id = kwargs.get("client_mutation_id", None) + if client_mutation_id: + filters.append(Q(mutations__mutation__client_mutation_id=client_mutation_id)) + filters.extend(get_group_worker_user_filters(info.context.user)) + return gql_optimizer.query(query.filter(*filters, policyholder__code=economic_unit_code), info) + @staticmethod def _check_permissions(user, perms): if type(user) is AnonymousUser or not user.id or not user.has_perms(perms): @@ -221,3 +247,6 @@ class Mutation(graphene.ObjectType): acquire_unassigned_vouchers = AcquireUnassignedVouchersMutation.Field() acquire_assigned_vouchers = AcquireAssignedVouchersMutation.Field() assign_vouchers = AssignVouchersMutation.Field() + + create_or_update_group_of_workers = CreateOrUpdateGroupOfWorkerMutation.Field() + delete_group_of_workers = DeleteGroupOfWorkerMutation.Field() diff --git a/worker_voucher/services.py b/worker_voucher/services.py index 0ddfad0..9992f17 100644 --- a/worker_voucher/services.py +++ b/worker_voucher/services.py @@ -5,6 +5,7 @@ from typing import Iterable, Dict, Union, List from uuid import uuid4 +from django.core.exceptions import ValidationError from django.db import transaction from django.db.models import Q, QuerySet, UUIDField, Count from django.db.models.functions import Cast @@ -13,6 +14,11 @@ from core import datetime from core.models import InteractiveUser, User from core.services import BaseService +from core.services.utils import ( + output_exception, + model_representation, + output_result_success +) from core.signals import register_service_signal from insuree.models import Insuree from insuree.gql_mutations import update_or_create_insuree @@ -22,7 +28,7 @@ from policyholder.services import PolicyHolderInsuree as PolicyHolderInsureeService from msystems.services.mconnect_worker_service import MConnectWorkerService from worker_voucher.apps import WorkerVoucherConfig -from worker_voucher.models import WorkerVoucher +from worker_voucher.models import WorkerVoucher, GroupOfWorker, WorkerGroup from worker_voucher.validation import WorkerVoucherValidation logger = logging.getLogger(__name__) @@ -60,7 +66,7 @@ def get_voucher_worker_enquire_filters(national_id: str) -> Iterable[Q]: policyholder__is_deleted=False, is_deleted=False, status=WorkerVoucher.Status.ASSIGNED, - assigned_date=today, + assigned_date__date=today, expiry_date__gte=today, )] @@ -75,6 +81,16 @@ def get_voucher_user_filters(user: InteractiveUser) -> Iterable[Q]: )] if not user.user.has_perms(WorkerVoucherConfig.gql_worker_voucher_search_all_perms) else [] +def get_group_worker_user_filters(user: InteractiveUser) -> Iterable[Q]: + return [Q( + policyholder__policyholderuser__user__i_user=user.i_user, + policyholder__is_deleted=False, + policyholder__policyholderuser__is_deleted=False, + policyholder__policyholderuser__user__validity_to__isnull=True, + policyholder__policyholderuser__user__i_user__validity_to__isnull=True, + )] if user.has_perms(WorkerVoucherConfig.gql_group_of_worker_search_perms) else [] + + def validate_acquire_unassigned_vouchers(user: User, eu_code: str, count: Union[int, str]) -> Dict: try: price_per_voucher = Decimal(WorkerVoucherConfig.price_per_voucher) @@ -552,6 +568,91 @@ def _add_worker_to_system(self, chf_id, economic_unit, data_from_mconnect, error return errors +class GroupOfWorkerService(BaseService): + OBJECT_TYPE = GroupOfWorker + + def __init__(self, user, validation_class=None): + super().__init__(user, validation_class) + + @register_service_signal('group_of_worker_service.create_or_update') + def create_or_update(self, obj_data, eu_code): + try: + with transaction.atomic(): + import datetime + now = datetime.datetime.now() + group_id = obj_data.pop('id') if 'id' in obj_data else None + insurees_chf_id = obj_data.pop('insurees_chf_id') if "insurees_chf_id" in obj_data else None + insurees = _check_insurees(insurees_chf_id, eu_code, self.user) if len(insurees_chf_id) > 0 else set() + if group_id: + group = GroupOfWorker.objects.get(id=group_id) + if group.name != obj_data['name']: + if GroupOfWorker.objects.filter(name=obj_data['name'], is_deleted=False).count() > 0: + raise ValidationError(_("This name for group already exists.")) + [setattr(group, k, v) for k, v in obj_data.items()] + group.save(user=self.user) + if insurees is not None: + worker_group_currently_assigned = WorkerGroup.objects.filter(group=group_id) + worker_group_currently_assigned.delete() + for insuree in insurees: + worker_group = WorkerGroup( + group_id=group_id, + insuree_id=insuree.id, + ) + worker_group.save(user=self.user) + else: + if GroupOfWorker.objects.filter(name=obj_data['name'], is_deleted=False).count() > 0: + raise ValidationError(_("This name for group already exists.")) + group = GroupOfWorker(**obj_data) + group.save(user=self.user) + if insurees: + for insuree in insurees: + worker_group = WorkerGroup( + **{ + "group_id": group.id, + "insuree_id": insuree.id + } + ) + worker_group.save(user=self.user) + dict_repr = model_representation(group) + return output_result_success(dict_representation=dict_repr) + except Exception as exc: + return output_exception(model_name=self.OBJECT_TYPE.__name__, method="create_or_update", exception=exc) + + @register_service_signal('group_of_worker_service.create') + def create(self, obj_data): + raise NotImplementedError() + + @register_service_signal('group_of_worker_service.update') + def update(self, obj_data): + raise NotImplementedError() + + @register_service_signal('group_of_worker_service.delete') + def delete(self, group_id, eu_uuid): + try: + with transaction.atomic(): + gow = GroupOfWorker.objects.filter( + id=group_id, + policyholder__uuid=eu_uuid, + policyholder__is_deleted=False, + is_deleted=False, + ).first() + + if not gow: + return [{"message": _("worker_voucher.validation.group_of_worker_not_exists"), "detail": group_id}] + + worker_group = WorkerGroup.objects.filter( + group__id=group_id, + group__policyholder__uuid=eu_uuid, + group__policyholder__is_deleted=False, + is_deleted=False, + ) + worker_group.delete() + gow.delete(user=self.user) + return [] + except Exception as exc: + return output_exception(model_name=self.OBJECT_TYPE.__name__, method="delete", exception=exc) + + def worker_voucher_bill_user_filter(qs: QuerySet, user: User) -> QuerySet: if user.is_imis_admin: return qs diff --git a/worker_voucher/tests/data/gql_payloads.py b/worker_voucher/tests/data/gql_payloads.py index 02a01f3..d2ebab0 100644 --- a/worker_voucher/tests/data/gql_payloads.py +++ b/worker_voucher/tests/data/gql_payloads.py @@ -73,3 +73,69 @@ } } """ + +gql_mutation_create_group_of_worker = """ +mutation addGroupOfWorker { + createOrUpdateGroupOfWorkers(input: { + insureesChfId: ["%s"], + economicUnitCode: "%s", + name: "%s", + clientMutationId: "%s" + }) { + clientMutationId + } +} +""" + +gql_mutation_create_group_of_worker_empty = """ +mutation addGroupOfWorker { + createOrUpdateGroupOfWorkers(input: { + insureesChfId: [], + economicUnitCode: "%s", + name: "%s", + clientMutationId: "%s" + }) { + clientMutationId + } +} +""" + +gql_mutation_update_group_of_worker_multiple = """ +mutation updateGroupOfWorker { + createOrUpdateGroupOfWorkers(input: { + id: "%s", + insureesChfId: ["%s", "%s"], + economicUnitCode: "%s", + name: "%s", + clientMutationId: "%s" + }) { + clientMutationId + } +} +""" + +gql_mutation_update_group_of_worker_single = """ +mutation updateGroupOfWorker { + createOrUpdateGroupOfWorkers(input: { + id: "%s", + insureesChfId: ["%s"], + economicUnitCode: "%s", + name: "%s", + clientMutationId: "%s" + }) { + clientMutationId + } +} +""" + +gql_mutation_group_of_worker_delete = """ +mutation deleteGroupOfWorker { + deleteGroupOfWorkers(input: { + uuid: "%s" + economicUnitCode: "%s" + clientMutationId: "%s" + }) { + clientMutationId + } +} +""" diff --git a/worker_voucher/tests/test_gql_group_of_worker_create.py b/worker_voucher/tests/test_gql_group_of_worker_create.py new file mode 100644 index 0000000..283a27d --- /dev/null +++ b/worker_voucher/tests/test_gql_group_of_worker_create.py @@ -0,0 +1,120 @@ +from django.test import TestCase +from core.models import MutationLog, Role +from graphene import Schema +from graphene.test import Client +from core.test_helpers import create_test_interactive_user +from worker_voucher.models import GroupOfWorker, WorkerGroup +from insuree.test_helpers import generate_random_insuree_number +from insuree.apps import InsureeConfig +from worker_voucher.schema import Query, Mutation +from worker_voucher.tests.data.gql_payloads import ( + gql_mutation_create_group_of_worker, + gql_mutation_create_group_of_worker_empty +) +from worker_voucher.tests.util import ( + create_test_eu_for_user, + create_test_worker_for_eu +) + + +class GQLGroupOfWorkerCreateTestCase(TestCase): + class GQLContext: + def __init__(self, user): + self.user = user + + user = None + eu = None + chf_id = None + name = None + existing_worker = None + + @classmethod + def setUpClass(cls): + super(GQLGroupOfWorkerCreateTestCase, cls).setUpClass() + role_employer = Role.objects.get(name='Employer', validity_to__isnull=True) + cls.user = create_test_interactive_user(username='VoucherTestUser2', roles=[role_employer.id]) + cls.eu = create_test_eu_for_user(cls.user, code='test_eu2') + cls.chf_id = F"{generate_random_insuree_number()}" + cls.existing_worker = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.name = 'Group Test' + + gql_schema = Schema( + query=Query, + mutation=Mutation + ) + + cls.gql_client = Client(gql_schema) + cls.gql_context = cls.GQLContext(cls.user) + + def test_create_group_of_worker_success(self): + InsureeConfig.reset_validation_settings() + mutation_id = "93g453h5g77h04gh35" + payload = gql_mutation_create_group_of_worker % ( + self.existing_worker.chf_id, + self.eu.code, + self.name, + mutation_id + ) + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_success(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 1) + + def test_create_group_of_worker_empty_success(self): + InsureeConfig.reset_validation_settings() + mutation_id = "39g453h5g92h74klj78" + payload = gql_mutation_create_group_of_worker_empty % ( + self.eu.code, + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_success(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 0) + + def test_create_group_of_worker_false_not_existing_economic_unit(self): + InsureeConfig.reset_validation_settings() + mutation_id = "39g453h5g92h04gh36" + payload = gql_mutation_create_group_of_worker % ( + self.chf_id, + 'NOT-EXISTS', + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + self.assertEquals(group.count(), 0) + + def test_create_group_of_worker_false_insuree_not_exist(self): + InsureeConfig.reset_validation_settings() + mutation_id = "19g453h5g92h04gh99" + national_id = F"{generate_random_insuree_number()}" + payload = gql_mutation_create_group_of_worker % ( + national_id, + self.eu.code, + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + self.assertEquals(group.count(), 0) + + def _assert_mutation_success(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 2) + self.assertFalse(mutation_log.error) + + def _assert_mutation_failed(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 1) + self.assertTrue(mutation_log.error) diff --git a/worker_voucher/tests/test_gql_group_of_worker_delete.py b/worker_voucher/tests/test_gql_group_of_worker_delete.py new file mode 100644 index 0000000..27be27a --- /dev/null +++ b/worker_voucher/tests/test_gql_group_of_worker_delete.py @@ -0,0 +1,135 @@ +from uuid import uuid4 + +from django.test import TestCase +from core.models import MutationLog, Role +from graphene import Schema +from graphene.test import Client +from core.test_helpers import create_test_interactive_user +from insuree.test_helpers import generate_random_insuree_number +from insuree.apps import InsureeConfig +from worker_voucher.schema import Query, Mutation +from worker_voucher.tests.data.gql_payloads import gql_mutation_group_of_worker_delete +from worker_voucher.tests.util import ( + create_test_eu_for_user, + create_test_worker_for_eu, + create_test_group_of_worker, + create_test_worker_group +) +from worker_voucher.models import GroupOfWorker, WorkerGroup + + +class GQLGroupOfWorkerDeleteTestCase(TestCase): + class GQLContext: + def __init__(self, user): + self.user = user + + user = None + user2 = None + eu = None + existing_worker = None + existing_worker2 = None + existing_worker3 = None + group = None + + @classmethod + def setUpClass(cls): + super(GQLGroupOfWorkerDeleteTestCase, cls).setUpClass() + role_employer = Role.objects.get(name='Employer', validity_to__isnull=True) + cls.user = create_test_interactive_user(username='VoucherTestUser4', roles=[role_employer.id]) + cls.eu = create_test_eu_for_user(cls.user, code="ECTest2") + cls.existing_worker = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.existing_worker2 = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.existing_worker3 = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.name = 'Test Group to Delete' + gql_schema = Schema( + query=Query, + mutation=Mutation + ) + + cls.gql_client = Client(gql_schema) + cls.gql_context = cls.GQLContext(cls.user) + cls.group = create_test_group_of_worker(cls.user, cls.eu, cls.name) + create_test_worker_group(cls.user, cls.existing_worker, cls.group) + create_test_worker_group(cls.user, cls.existing_worker2, cls.group) + create_test_worker_group(cls.user, cls.existing_worker3, cls.group) + + def test_delete_group_of_worker_success(self): + InsureeConfig.reset_validation_settings() + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 3) + + mutation_id = uuid4() + mutation = gql_mutation_group_of_worker_delete % ( + self.group.uuid, + self.eu.code, + mutation_id + ) + + self.gql_client.execute(mutation, context=self.gql_context) + self._assert_mutation_success(mutation_id) + + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 0) + self.assertEquals(workers_group.count(), 0) + + def test_delete_worker_failed_economic_unit_not_exist(self): + InsureeConfig.reset_validation_settings() + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 3) + + mutation_id = uuid4() + mutation = gql_mutation_group_of_worker_delete % ( + self.group.uuid, + 'NOT-EXIST', + mutation_id + ) + + self.gql_client.execute(mutation, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 3) + + def test_delete_worker_failed_no_group_not_exist(self): + InsureeConfig.reset_validation_settings() + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 3) + uuid_group_not_exist = "b47356b5-1423-4ca6-99e8-3b4b4642a640" + group2 = GroupOfWorker.objects.filter(id=uuid_group_not_exist, is_deleted=False) + self.assertEquals(group2.count(), 0) + + mutation_id = uuid4() + mutation = gql_mutation_group_of_worker_delete % ( + uuid_group_not_exist, + self.eu.code, + mutation_id + ) + + self.gql_client.execute(mutation, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + + group = GroupOfWorker.objects.filter(id=self.group.id, is_deleted=False) + workers_group = WorkerGroup.objects.filter(group__id=self.group.id) + self.assertEquals(group.count(), 1) + self.assertEquals(workers_group.count(), 3) + group2 = GroupOfWorker.objects.filter(id=uuid_group_not_exist, is_deleted=False) + self.assertEquals(group2.count(), 0) + + def _assert_mutation_success(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 2) + self.assertFalse(mutation_log.error) + + def _assert_mutation_failed(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 1) + self.assertTrue(mutation_log.error) diff --git a/worker_voucher/tests/test_gql_group_of_worker_update.py b/worker_voucher/tests/test_gql_group_of_worker_update.py new file mode 100644 index 0000000..c21177f --- /dev/null +++ b/worker_voucher/tests/test_gql_group_of_worker_update.py @@ -0,0 +1,184 @@ +from django.test import TestCase +from core.models import MutationLog, Role +from graphene import Schema +from graphene.test import Client +from core.test_helpers import create_test_interactive_user +from worker_voucher.models import GroupOfWorker, WorkerGroup +from insuree.test_helpers import generate_random_insuree_number +from insuree.apps import InsureeConfig +from worker_voucher.schema import Query, Mutation +from worker_voucher.tests.data.gql_payloads import ( + gql_mutation_update_group_of_worker_single, + gql_mutation_update_group_of_worker_multiple +) +from worker_voucher.tests.util import ( + create_test_eu_for_user, + create_test_worker_for_eu, + create_test_group_of_worker +) + + +class GQLGroupOfWorkerUpdateTestCase(TestCase): + class GQLContext: + def __init__(self, user): + self.user = user + + user = None + eu = None + chf_id = None + name = None + existing_worker = None + existing_worker2 = None + group = None + + @classmethod + def setUpClass(cls): + super(GQLGroupOfWorkerUpdateTestCase, cls).setUpClass() + role_employer = Role.objects.get(name='Employer', validity_to__isnull=True) + cls.user = create_test_interactive_user(username='VoucherTestUser3', roles=[role_employer.id]) + cls.eu = create_test_eu_for_user(cls.user, code='test_eu3') + cls.chf_id = F"{generate_random_insuree_number()}" + cls.existing_worker = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.existing_worker2 = create_test_worker_for_eu(cls.user, cls.eu, chf_id=F"{generate_random_insuree_number()}") + cls.name = 'Group Test Update' + + gql_schema = Schema( + query=Query, + mutation=Mutation + ) + + cls.gql_client = Client(gql_schema) + cls.gql_context = cls.GQLContext(cls.user) + cls.group = create_test_group_of_worker(cls.user, cls.eu, cls.name) + + def test_update_group_of_worker_success(self): + InsureeConfig.reset_validation_settings() + mutation_id = "93g453h5g77h04gh01" + payload = gql_mutation_update_group_of_worker_multiple % ( + self.group.id, + self.existing_worker.chf_id, + self.existing_worker2.chf_id, + self.eu.code, + self.name, + mutation_id + ) + + workers_group = WorkerGroup.objects.filter(group=self.group) + self.assertEquals(workers_group.count(), 0) + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_success(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(group.first().name, self.name) + self.assertEquals(workers_group.count(), 2) + + def test_update_group_of_worker_change_name_success(self): + InsureeConfig.reset_validation_settings() + mutation_id = "93g453h5g77h04gh00" + changed_name = 'ChangedName' + payload = gql_mutation_update_group_of_worker_multiple % ( + self.group.id, + self.existing_worker.chf_id, + self.existing_worker2.chf_id, + self.eu.code, + changed_name, + mutation_id + ) + workers_group = WorkerGroup.objects.filter(group=self.group) + self.assertEquals(workers_group.count(), 0) + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_success(mutation_id) + group = GroupOfWorker.objects.filter(name=changed_name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(group.first().name, changed_name) + self.assertEquals(workers_group.count(), 2) + + def test_update_group_of_worker_remove_one_of_worker_success(self): + InsureeConfig.reset_validation_settings() + mutation_id = "93g453h5g77h04gh01" + payload = gql_mutation_update_group_of_worker_multiple % ( + self.group.id, + self.existing_worker.chf_id, + self.existing_worker2.chf_id, + self.eu.code, + self.name, + mutation_id + ) + + workers_group = WorkerGroup.objects.filter(group=self.group) + self.assertEquals(workers_group.count(), 0) + _ = self.gql_client.execute(payload, context=self.gql_context) + group = GroupOfWorker.objects.filter(name=self.name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(group.first().name, self.name) + self.assertEquals(workers_group.count(), 2) + + mutation_id = "93g453h5g77h04gh09" + payload = gql_mutation_update_group_of_worker_single % ( + self.group.id, + self.existing_worker.chf_id, + self.eu.code, + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_success(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.count(), 1) + self.assertEquals(group.first().name, self.name) + self.assertEquals(workers_group.count(), 1) + self.assertEquals(workers_group.first().insuree.chf_id, self.existing_worker.chf_id) + + def test_update_group_of_worker_false_not_existing_economic_unit(self): + InsureeConfig.reset_validation_settings() + mutation_id = "39g453h5g92h04gh03" + payload = gql_mutation_update_group_of_worker_single % ( + self.group.id, + self.existing_worker.chf_id, + 'NOT-EXISTS', + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + self.assertEquals(group.count(), 1) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.first().name, self.name) + self.assertEquals(workers_group.count(), 0) + + def test_update_group_of_worker_insuree_not_exist(self): + InsureeConfig.reset_validation_settings() + mutation_id = "19g453h5g92h04gh04" + national_id = F"{generate_random_insuree_number()}" + payload = gql_mutation_update_group_of_worker_single % ( + self.group.id, + national_id, + self.eu.code, + self.name, + mutation_id + ) + + _ = self.gql_client.execute(payload, context=self.gql_context) + self._assert_mutation_failed(mutation_id) + group = GroupOfWorker.objects.filter(name=self.name) + self.assertEquals(group.count(), 1) + workers_group = WorkerGroup.objects.filter(group=group.first()) + self.assertEquals(group.first().name, self.name) + self.assertEquals(workers_group.count(), 0) + + def _assert_mutation_success(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 2) + self.assertFalse(mutation_log.error) + + def _assert_mutation_failed(self, mutation_id): + mutation_log = MutationLog.objects.get(client_mutation_id=mutation_id) + self.assertEquals(mutation_log.status, 1) + self.assertTrue(mutation_log.error) diff --git a/worker_voucher/tests/util.py b/worker_voucher/tests/util.py index 583f496..2ff6352 100644 --- a/worker_voucher/tests/util.py +++ b/worker_voucher/tests/util.py @@ -6,6 +6,7 @@ from insuree.models import Insuree from policyholder.models import PolicyHolder, PolicyHolderUser, PolicyHolderInsuree +from worker_voucher.models import GroupOfWorker, WorkerGroup def create_test_eu(user, code='test_eu'): @@ -96,3 +97,21 @@ def __enter__(self): def __exit__(self, exc_type, exc_val, exc_tb): for key in self.original_config: setattr(self.config_class, key, self.original_config[key]) + + +def create_test_group_of_worker(user, eu, name): + group = GroupOfWorker( + name=name, + policyholder=eu, + ) + group.save(user=user) + return group + + +def create_test_worker_group(user, insuree, group): + worker_group = WorkerGroup( + group=group, + insuree=insuree, + ) + worker_group.save(user=user) + return worker_group