Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Merge Main into mngoe #42

Merged
merged 62 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
dc7b53d
OTC-1098: jsonext changed type from text to nvchar (#64)
lruzicki Jun 15, 2023
caee987
Adding missing entries in Insuree Policy table while moving a member …
hirensoni913 Jul 14, 2023
558596f
CM-256: Add sonar-project.properties
dborowiecki Jul 27, 2023
cf20637
Merge pull request #67 from openimis/sonar_attach
jdolkowski Jul 27, 2023
1ba369c
ONI-7: Added option to force FSP for insuree.
wzgliniecki Aug 9, 2023
32b3d2f
Finish feature/ONI-7
dragos-dobre Aug 21, 2023
aafe047
OP-1518: load config (#71)
jdolkowski Sep 18, 2023
7627065
Feature/op 1518 (#73)
dragos-dobre Sep 18, 2023
5068cd5
CI update
dborowiecki Sep 19, 2023
7bf83e8
CI Update 2
dborowiecki Sep 19, 2023
a93c89d
Merge pull request #75 from openimis/ci_update
jdolkowski Sep 20, 2023
8f86cd6
Removed whitespace from yaml file (#78)
dborowiecki Sep 20, 2023
736ec48
Update apps.py (#79)
delcroip Sep 22, 2023
7c338f7
Default photo path (#80)
delcroip Sep 22, 2023
816dc8d
Hot fix
delcroip Sep 22, 2023
55bbc45
hot fix
delcroip Sep 22, 2023
dc59ba9
Fix photo , iexact for uuid, improve helper, improve save
delcroip Sep 28, 2023
6dc9f31
show insuree without familly (#86)
delcroip Sep 28, 2023
3651a72
better helpers (#87)
delcroip Oct 4, 2023
680e51d
Better helpers (#88)
delcroip Oct 4, 2023
036a3b5
ONI-3: Insuree status model added. (#74)
Oct 5, 2023
05a13ac
ONI-5: Added is confirmation number required column to confirmation t…
Oct 6, 2023
8e55988
Merge branch 'release/23.10' into develop
dragos-dobre Oct 18, 2023
f3bdf18
MERGING RELEASE branches (#90)
dragos-dobre Oct 18, 2023
711d11d
better helpers
delcroip Oct 20, 2023
0fbb4ce
Fix insuree loc filter (#93)
delcroip Oct 23, 2023
2f7c8bd
change insuree loc filter appraoch (#94)
delcroip Oct 23, 2023
c86f1f1
OM-10: create insuree as worker (#77)
jdolkowski Oct 30, 2023
02f6c00
OM-10: update translations (#95)
jdolkowski Oct 31, 2023
d35e727
Better helpers (#92)
delcroip Nov 9, 2023
778f41c
Fix family admin filter (#96)
delcroip Nov 10, 2023
2ec6140
Merge branch 'release/23.10' into develop
hirensoni913 Nov 13, 2023
3714ead
Merge pull request #97 from openimis/develop
hirensoni913 Nov 13, 2023
371ea4b
Merge pull request #98 from openimis/release/23.10
hirensoni913 Nov 13, 2023
ebd0e92
Using location manager (#100)
delcroip Nov 23, 2023
2d8ff53
fix family list
delcroip Nov 28, 2023
6f09d94
Merge pull request #101 from openimis/fix-family-queryset
delcroip Nov 28, 2023
24e2b01
FileNotFoundError handled while opening a photo of an insuree
hirensoni913 Dec 1, 2023
e541bb5
Merge pull request #103 from openimis/develop
delcroip Dec 1, 2023
871ce92
Single claim report test added
hirensoni913 Dec 4, 2023
54518b2
support translation in glq messages
delcroip Dec 5, 2023
90cc761
Merge pull request #102 from openimis/feature/OP-1668
delcroip Dec 5, 2023
5b1aa80
Merge pull request #104 from openimis/feature/OP-1675
delcroip Dec 6, 2023
b1589d3
Merge branch 'release/23.10' into mmerge
delcroip Dec 6, 2023
8dc4f51
Merge pull request #99 from openimis/mmerge
delcroip Dec 6, 2023
9c9f1cf
gettext error
delcroip Dec 6, 2023
bebcd02
Merge pull request #106 from openimis/delcroip-patch-1
delcroip Dec 6, 2023
a894c30
Merge pull request #105 from openimis/develop
delcroip Dec 6, 2023
49925f4
OP-1686: Removed redundant validation.
wzgliniecki Dec 7, 2023
5f87f9c
Merge pull request #108 from openimis/feature/OP-1686
delcroip Dec 7, 2023
289cc75
Merge pull request #109 from openimis/feature/OP-1686
delcroip Dec 7, 2023
6181b9f
Merge pull request #107 from openimis/release/23.10
delcroip Dec 11, 2023
7f980ae
allow uuid in gql family and insuree and fix picture update
delcroip Dec 15, 2023
bc26d63
Merge branch 'develop' into allow-uuid-gql
delcroip Dec 15, 2023
50900a0
Merge pull request #110 from openimis/allow-uuid-gql
delcroip Dec 15, 2023
ef5d1b5
hotfix merge issue
delcroip Dec 15, 2023
5cc8ce8
hotfix iexact
delcroip Dec 15, 2023
676c1d2
change photo uuid if phot changes
delcroip Dec 15, 2023
b39ee52
typo
delcroip Dec 15, 2023
09d8565
mising validation phot uuid
delcroip Dec 15, 2023
985266b
Merge pull request #111 from openimis/develop
delcroip Dec 15, 2023
b9b1c1f
Merge pull request #112 from openimis/release/23.10
hirensoni913 Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 30 additions & 36 deletions insuree/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,24 @@
"gql_mutation_create_insurees_perms": ["101102"],
"gql_mutation_update_insurees_perms": ["101103"],
"gql_mutation_delete_insurees_perms": ["101104"],
"insuree_photos_root_path": None,
"insuree_photos_root_path": os.path.abspath("./images/insurees"),
"excluded_insuree_chfids": ['999999999'], # fake insurees (and bound families) used, for example, in 'funding'
"renewal_photo_age_adult": 60, # age (in months) of a picture due for renewal for adults
"renewal_photo_age_child": 12, # age (in months) of a picture due for renewal for children
"insuree_number_validator": None, # Insuree number *function* that validates the insuree number
"insuree_number_validator": None, # Insuree number *function* that validates the insuree number for example
# 'msystems.utils.is_valid_resident_identifier'
"insuree_number_length": None, # Insuree number length to validate
"insuree_number_modulo_root": None, # modulo base for checksum on last digit, requires length to be set too
"validation_code_taken_insuree_number": 1,
"validation_code_no_insuree_number": 2,
"validation_code_invalid_insuree_number_len": 3,
"validation_code_invalid_insuree_number_checksum": 4,
"validation_code_invalid_insuree_number_exception": 5,
"validation_code_validator_import_error": 6,
"validation_code_validator_function_error": 7,
"insuree_fsp_mandatory": False,
"insuree_as_worker": False,

}


Expand All @@ -47,49 +58,32 @@ class InsureeConfig(AppConfig):
gql_mutation_create_insurees_perms = []
gql_mutation_update_insurees_perms = []
gql_mutation_delete_insurees_perms = []
validation_code_taken_insuree_number = 1
validation_code_no_insuree_number = 2
validation_code_invalid_insuree_number_len = 3
validation_code_invalid_insuree_number_checksum = 4
validation_code_invalid_insuree_number_exception = 5
validation_code_taken_insuree_number = None
validation_code_no_insuree_number = None
validation_code_invalid_insuree_number_len = None
validation_code_invalid_insuree_number_checksum = None
validation_code_invalid_insuree_number_exception = None
validation_code_validator_import_error = None
validation_code_validator_function_error = None
insuree_photos_root_path = None
excluded_insuree_chfids = ['999999999']
renewal_photo_age_adult = 60
renewal_photo_age_child = 12
excluded_insuree_chfids = []
renewal_photo_age_adult = None
renewal_photo_age_child = None
insuree_number_validator = None
insuree_number_length = None
insuree_number_modulo_root = None
insuree_fsp_mandatory = None
insuree_as_worker = None

def _configure_permissions(self, cfg):
InsureeConfig.gql_query_insurees_perms = cfg["gql_query_insurees_perms"]
InsureeConfig.gql_query_insuree_perms = cfg["gql_query_insuree_perms"]
InsureeConfig.gql_query_insuree_photo_perms = cfg["gql_query_insuree_photo_perms"]
InsureeConfig.gql_query_insuree_officers_perms = cfg["gql_query_insuree_officers_perms"]
InsureeConfig.gql_query_insuree_family_members = cfg["gql_query_insuree_family_members"]
InsureeConfig.gql_query_families_perms = cfg["gql_query_families_perms"]
InsureeConfig.gql_query_insuree_policy_perms = cfg["gql_query_insuree_policy_perms"]
InsureeConfig.gql_mutation_create_families_perms = cfg["gql_mutation_create_families_perms"]
InsureeConfig.gql_mutation_update_families_perms = cfg["gql_mutation_update_families_perms"]
InsureeConfig.gql_mutation_create_insurees_perms = cfg["gql_mutation_create_insurees_perms"]
InsureeConfig.gql_mutation_update_insurees_perms = cfg["gql_mutation_update_insurees_perms"]
InsureeConfig.gql_mutation_delete_insurees_perms = cfg["gql_mutation_delete_insurees_perms"]
InsureeConfig.insuree_number_validator = cfg["insuree_number_validator"]
InsureeConfig.insuree_number_length = cfg["insuree_number_length"]
InsureeConfig.insuree_number_modulo_root = cfg["insuree_number_modulo_root"]

def _configure_fake_insurees(self, cfg):
InsureeConfig.excluded_insuree_chfids = cfg["excluded_insuree_chfids"]

def _configure_renewal(self, cfg):
InsureeConfig.renewal_photo_age_adult = cfg["renewal_photo_age_adult"]
InsureeConfig.renewal_photo_age_child = cfg["renewal_photo_age_child"]
def __load_config(self, cfg):
for field in cfg:
if hasattr(InsureeConfig, field):
setattr(InsureeConfig, field, cfg[field])

def ready(self):
from core.models import ModuleConfiguration
cfg = ModuleConfiguration.get_or_default(MODULE_NAME, DEFAULT_CFG)
self._configure_permissions(cfg)
self._configure_fake_insurees(cfg)
self._configure_renewal(cfg)
self.__load_config(cfg)
self._configure_photo_root(cfg)

# Getting these at runtime for easier testing
Expand Down
72 changes: 35 additions & 37 deletions insuree/gql_mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import pathlib
import base64
import graphene
from insuree.apps import InsureeConfig
from insuree.services import validate_insuree_number, InsureeService, FamilyService, InsureePolicyService

from insuree.services import validate_insuree_number, InsureeService, FamilyService

from .apps import InsureeConfig
from core.schema import OpenIMISMutation
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ValidationError, PermissionDenied
Expand All @@ -33,7 +32,7 @@ class InsureeBase:
chf_id = graphene.String(max_length=12, required=False)
last_name = graphene.String(max_length=100, required=True)
other_names = graphene.String(max_length=100, required=True)
gender_id = graphene.String(max_length=1, required=True, description="Was mandatory in Legacy but not in modular")
gender_id = graphene.String(max_length=1, required=True)
dob = graphene.Date(required=True)
head = graphene.Boolean(required=False)
marital = graphene.String(max_length=1, required=False)
Expand All @@ -55,6 +54,9 @@ class InsureeBase:
health_facility_id = graphene.Int(required=False)
offline = graphene.Boolean(required=False)
json_ext = graphene.types.json.JSONString(required=False)
status = graphene.String(required=False)
status_reason = graphene.String(required=False)
status_date = graphene.Date(required=False)


class CreateInsureeInputType(InsureeBase, OpenIMISMutation.Input):
Expand Down Expand Up @@ -99,23 +101,6 @@ class UpdateFamilyInputType(FamilyInputType):
pass


def create_file(date, insuree_id, photo_bin):
date_iso = date.isoformat()
root = InsureeConfig.insuree_photos_root_path
file_dir = '%s/%s/%s/%s' % (
date_iso[0:4],
date_iso[5:7],
date_iso[8:10],
insuree_id
)
file_name = uuid.uuid4()
file_path = '%s/%s' % (file_dir, file_name)
pathlib.Path('%s/%s' % (root, file_dir)).mkdir(parents=True, exist_ok=True)
f = open('%s/%s' % (root, file_path), "xb")
f.write(base64.b64decode(photo_bin))
f.close()
return file_dir, file_name


def update_or_create_insuree(data, user):
data.pop('client_mutation_id', None)
Expand Down Expand Up @@ -152,7 +137,8 @@ def async_mutate(cls, user, **data):
data['validity_from'] = TimeUtils.now()
client_mutation_id = data.get("client_mutation_id")
family = update_or_create_family(data, user)
FamilyMutation.object_mutated(user, client_mutation_id=client_mutation_id, family=family)
FamilyMutation.object_mutated(
user, client_mutation_id=client_mutation_id, family=family)
return None
except Exception as exc:
logger.exception("insuree.mutation.failed_to_create_family")
Expand Down Expand Up @@ -183,7 +169,8 @@ def async_mutate(cls, user, **data):
data['audit_user_id'] = user.id_for_audit
client_mutation_id = data.get("client_mutation_id")
family = update_or_create_family(data, user)
FamilyMutation.object_mutated(user, client_mutation_id=client_mutation_id, family=family)
FamilyMutation.object_mutated(
user, client_mutation_id=client_mutation_id, family=family)
return None
except Exception as exc:
logger.exception("insuree.mutation.failed_to_update_family")
Expand Down Expand Up @@ -212,15 +199,16 @@ def async_mutate(cls, user, **data):
for family_uuid in data["uuids"]:
family = Family.objects \
.prefetch_related('members') \
.filter(uuid=family_uuid) \
.filter(uuid=(family_uuid)) \
.first()
if family is None:
errors.append({
'title': family_uuid,
'list': [{'message': _("insuree.mutation.failed_to_delete_family") % {'uuid': family_uuid}}]
})
continue
errors += FamilyService(user).set_deleted(family, data["delete_members"])
errors += FamilyService(user).set_deleted(family,
data["delete_members"])
if len(errors) == 1:
errors = errors[0]['list']
return errors
Expand Down Expand Up @@ -249,7 +237,8 @@ def async_mutate(cls, user, **data):
data['validity_from'] = TimeUtils.now()
client_mutation_id = data.get("client_mutation_id")
insuree = update_or_create_insuree(data, user)
InsureeMutation.object_mutated(user, client_mutation_id=client_mutation_id, insuree=insuree)
InsureeMutation.object_mutated(
user, client_mutation_id=client_mutation_id, insuree=insuree)
return None
except Exception as exc:
logger.exception("insuree.mutation.failed_to_create_insuree")
Expand Down Expand Up @@ -278,11 +267,13 @@ def async_mutate(cls, user, **data):
if not user.has_perms(InsureeConfig.gql_mutation_create_insurees_perms):
raise PermissionDenied(_("unauthorized"))
if 'uuid' not in data:
raise ValidationError("There is no uuid in updateMutation input!")
raise ValidationError(
"There is no uuid in updateMutation input!")
data['audit_user_id'] = user.id_for_audit
client_mutation_id = data.get("client_mutation_id")
insuree = update_or_create_insuree(data, user)
InsureeMutation.object_mutated(user, client_mutation_id=client_mutation_id, insuree=insuree)
InsureeMutation.object_mutated(
user, client_mutation_id=client_mutation_id, insuree=insuree)
return None
except Exception as exc:
logger.exception("insuree.mutation.failed_to_update_insuree")
Expand All @@ -300,7 +291,8 @@ class DeleteInsureesMutation(OpenIMISMutation):
_mutation_class = "DeleteInsureesMutation"

class Input(OpenIMISMutation.Input):
uuid = graphene.String(required=False) # family uuid, to 'lock' family while mutation is processed
# family uuid, to 'lock' family while mutation is processed
uuid = graphene.String(required=False)
uuids = graphene.List(graphene.String)

@classmethod
Expand All @@ -311,7 +303,7 @@ def async_mutate(cls, user, **data):
for insuree_uuid in data["uuids"]:
insuree = Insuree.objects \
.prefetch_related('family') \
.filter(uuid=insuree_uuid) \
.filter(uuid__iexact=insuree_uuid) \
.first()
if insuree is None:
errors.append({
Expand Down Expand Up @@ -353,7 +345,7 @@ def async_mutate(cls, user, **data):
for insuree_uuid in data["uuids"]:
insuree = Insuree.objects \
.prefetch_related('family') \
.filter(uuid=insuree_uuid) \
.filter(uuid=(insuree_uuid)) \
.first()
if insuree is None:
errors += {
Expand Down Expand Up @@ -394,8 +386,8 @@ def async_mutate(cls, user, **data):
if not user.has_perms(InsureeConfig.gql_mutation_update_families_perms):
raise PermissionDenied(_("unauthorized"))
try:
family = Family.objects.get(uuid=data['uuid'])
insuree = Insuree.objects.get(uuid=data['insuree_uuid'])
family = Family.objects.get(uuid=(data['uuid']))
insuree = Insuree.objects.get(uuid=(data['insuree_uuid']))
family.save_history()
prev_head = family.head_insuree
if prev_head:
Expand Down Expand Up @@ -434,16 +426,22 @@ def async_mutate(cls, user, **data):
not user.has_perms(InsureeConfig.gql_mutation_update_insurees_perms):
raise PermissionDenied(_("unauthorized"))
try:
family = Family.objects.get(uuid=data['family_uuid'])
insuree = Insuree.objects.get(uuid=data['insuree_uuid'])
family = Family.objects.get(uuid=(data['family_uuid']))
insuree = Insuree.objects.get(uuid=(data['insuree_uuid']))
insuree.save_history()
insuree.family = family
insuree.save()

if data['cancel_policies']:
return InsureeService(user).cancel_policies(insuree)
InsureeService(user).cancel_policies(insuree)

# Assign all the valid policies from the new family
InsureePolicyService(user).add_insuree_policy(insuree)

return None
except Exception as exc:
logger.exception("insuree.mutation.failed_to_change_insuree_family")
logger.exception(
"insuree.mutation.failed_to_change_insuree_family")
return [{
'message': _("insuree.mutation.failed_to_change_insuree_family"),
'detail': str(exc)}
Expand Down
21 changes: 17 additions & 4 deletions insuree/gql_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from .apps import InsureeConfig
from .models import Insuree, InsureePhoto, Education, Profession, Gender, IdentificationType, \
Family, FamilyType, ConfirmationType, Relation, InsureePolicy, FamilyMutation, InsureeMutation
Family, FamilyType, ConfirmationType, Relation, InsureePolicy, FamilyMutation, InsureeMutation, InsureeStatusReason
from location.schema import LocationGQLType
from policy.gql_queries import PolicyGQLType
from core import prefix_filterset, filter_validity, ExtendedConnection
Expand Down Expand Up @@ -90,6 +90,18 @@ class Meta:
}


class InsureeStatusReasonGQLType(DjangoObjectType):
class Meta:
model = InsureeStatusReason
interfaces = (graphene.relay.Node,)
filter_fields = {
"code": ["exact"],
"insuree_status_reason": ["exact", 'icontains', 'istartswith'],
"status_type": ["exact"]
}
connection_class = ExtendedConnection


class InsureeGQLType(DjangoObjectType):
age = graphene.Int(source='age')
client_mutation_id = graphene.String()
Expand Down Expand Up @@ -128,7 +140,7 @@ def resolve_photo(self, info):
class Meta:
model = Insuree
filter_fields = {
"uuid": ["exact"],
"uuid": ["exact","iexact"],
"chf_id": ["exact", "istartswith", "icontains", "iexact"],
"last_name": ["exact", "istartswith", "icontains", "iexact"],
"other_names": ["exact", "istartswith", "icontains", "iexact"],
Expand All @@ -139,6 +151,7 @@ class Meta:
"passport": ["exact", "istartswith", "icontains", "iexact", "isnull"],
"gender__code": ["exact", "isnull"],
"marital": ["exact", "isnull"],
"status": ["exact"],
"validity_from": ["exact", "lt", "lte", "gt", "gte", "isnull"],
"validity_to": ["exact", "lt", "lte", "gt", "gte", "isnull"],
**prefix_filterset("photo__", PhotoGQLType._meta.filter_fields),
Expand Down Expand Up @@ -178,7 +191,7 @@ def resolve_head_insuree(self, info):
class Meta:
model = Family
filter_fields = {
"uuid": ["exact"],
"uuid": ["exact","iexact"],
"poverty": ["exact", "isnull"],
"confirmation_no": ["exact", "istartswith", "icontains", "iexact"],
"confirmation_type": ["exact"],
Expand All @@ -188,7 +201,7 @@ class Meta:
"is_offline": ["exact"],
**prefix_filterset("location__", LocationGQLType._meta.filter_fields),
**prefix_filterset("head_insuree__", InsureeGQLType._meta.filter_fields),
** prefix_filterset("members__", InsureeGQLType._meta.filter_fields)
**prefix_filterset("members__", InsureeGQLType._meta.filter_fields)
}
interfaces = (graphene.relay.Node,)
connection_class = ExtendedConnection
Expand Down
2 changes: 0 additions & 2 deletions insuree/management/commands/generateinsurees.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def handle(self, *args, **options):
last_name=fake.last_name(),
other_names=fake.first_name(),
dob=fake.date_between(start_date='-105y', end_date='today'),
chf_id=random.randrange(100000000, 999999999),
)
family_props = dict(
location_id=self.get_random_village(),
Expand All @@ -61,7 +60,6 @@ def handle(self, *args, **options):
props["other_names"] = fake.first_name()
props["dob"] = fake.date_between(start_date='-105y', end_date='today')
props["family_id"] = insuree.family_id
props["chf_id"] = random.randrange(100000000, 999999999)
member = create_test_insuree(with_family=False, custom_props=props)
if verbose:
print("Created family member", member_num, member.other_names)
Expand Down
24 changes: 24 additions & 0 deletions insuree/migrations/0016_alter_jsonext_column.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.2.18 on 2023-06-02 12:04
from django.conf import settings
from django.db import migrations


class Migration(migrations.Migration):

psql_code = 'select 1'

dependencies = [
('insuree', '0015_set_managed_to_true_in_all_models'),
]

operations = [
migrations.RunSQL('ALTER TABLE [tblInsuree] ALTER COLUMN [JsonExt] NVARCHAR(MAX)'
if settings.MSSQL else psql_code,
reverse_sql='ALTER TABLE [tblInsuree] ALTER COLUMN [JsonExt] TEXT'
if settings.MSSQL else psql_code),
migrations.RunSQL('ALTER TABLE [tblFamilies] ALTER COLUMN [JsonExt] NVARCHAR(MAX)'
if settings.MSSQL else psql_code,
reverse_sql='ALTER TABLE [tblFamilies] ALTER COLUMN [JsonExt] TEXT'
if settings.MSSQL else psql_code),
]

Loading
Loading