From 28eb8a853ac14172eed04d676a9309f7aa9e7e2c Mon Sep 17 00:00:00 2001 From: Ayushmina-20 Date: Wed, 4 May 2022 14:59:03 +0530 Subject: [PATCH] squashed commits --- odk-connector/models/odk_submissions_model.py | 1 + openg2p/models/beneficiary_to_batch_wizard.py | 1 + openg2p/models/openg2p_beneficiary.py | 5 +- openg2p/services/matching_service.py | 2 +- openg2p/views/openg2p_beneficiary.xml | 5 +- .../models/openg2p_disbursement_batch.py | 16 +- .../models/openg2p_disbursement_rule.py | 2 +- .../models/openg2p_disbursement_main.py | 1 + .../views/openg2p_disbursement_main.xml | 1 + openg2p_registration/models/__init__.py | 1 + .../openg2p_demographic_authentication.py | 175 ++++++++++++++++++ .../models/openg2p_registration.py | 121 ++++++++---- .../models/openg2p_registration_api.py | 6 + .../openg2p_registration_identification.py | 4 +- .../views/openg2p_registration.xml | 4 +- 15 files changed, 295 insertions(+), 50 deletions(-) create mode 100644 openg2p_registration/models/openg2p_demographic_authentication.py diff --git a/odk-connector/models/odk_submissions_model.py b/odk-connector/models/odk_submissions_model.py index 65710ee..c18c60f 100644 --- a/odk-connector/models/odk_submissions_model.py +++ b/odk-connector/models/odk_submissions_model.py @@ -172,6 +172,7 @@ def create_registration_from_submission(self, data, extra_data=None): ].create_registration_from_odk(data) return registration except BaseException as e: + print(e) print("Failed in creating registration!") return None diff --git a/openg2p/models/beneficiary_to_batch_wizard.py b/openg2p/models/beneficiary_to_batch_wizard.py index 1607bb2..5303b17 100644 --- a/openg2p/models/beneficiary_to_batch_wizard.py +++ b/openg2p/models/beneficiary_to_batch_wizard.py @@ -124,6 +124,7 @@ def task_create_batch(self, batch_name, beneficiary_ids): "date_end": datetime.now(), "currency_id": bank_id[0].currency_id.id, "payment_mode": bank_id[0].payment_mode, + "payment_address": b.payment_address, } ) m.generate_uuid() diff --git a/openg2p/models/openg2p_beneficiary.py b/openg2p/models/openg2p_beneficiary.py index 8d854ec..3ca6047 100644 --- a/openg2p/models/openg2p_beneficiary.py +++ b/openg2p/models/openg2p_beneficiary.py @@ -349,6 +349,7 @@ def _default_image(self): ) odk_batch_id = fields.Char(default=lambda *args: uuid.uuid4().hex) + payment_address = fields.Char(string="Payment Address", required=False) def api_json(self): return { @@ -466,7 +467,7 @@ def _compute_org_fields(self): [ "&", ("beneficiary_id", "=", rec.id), - ("field_name", "=", "grand_total_le"), + ("field_name", "=", "grand_total"), ] ) try: @@ -731,7 +732,7 @@ def _compute_email_formatted(self): for beneficiary in self: if beneficiary.email: beneficiary.email_formatted = tools.formataddr( - (beneficiary.name or u"False", beneficiary.email or u"False") + (beneficiary.name or "False", beneficiary.email or "False") ) else: beneficiary.email_formatted = "" diff --git a/openg2p/services/matching_service.py b/openg2p/services/matching_service.py index 083a929..2caf76d 100644 --- a/openg2p/services/matching_service.py +++ b/openg2p/services/matching_service.py @@ -83,7 +83,7 @@ def match(self, query): for ID, number in query.get_identities() ) matches = ( - self.with_context(active_test=False) + query.with_context(active_test=False) .env["openg2p.beneficiary.id_number"] .search(domain) ) diff --git a/openg2p/views/openg2p_beneficiary.xml b/openg2p/views/openg2p_beneficiary.xml index a41b899..2ce446e 100644 --- a/openg2p/views/openg2p_beneficiary.xml +++ b/openg2p/views/openg2p_beneficiary.xml @@ -160,10 +160,11 @@ + + - @@ -190,7 +191,7 @@ - + diff --git a/openg2p_disbursement/models/openg2p_disbursement_batch.py b/openg2p_disbursement/models/openg2p_disbursement_batch.py index 6ce54d6..f59f947 100644 --- a/openg2p_disbursement/models/openg2p_disbursement_batch.py +++ b/openg2p_disbursement/models/openg2p_disbursement_batch.py @@ -161,16 +161,12 @@ def _compute_can_generate(self): @api.multi def _compute_can_cancel(self): self.ensure_one() - self.can_cancel = ( - self.state - in ( - "generating", - "draft", - "confirm", - "approved", - ) - and not isinstance(self.id, models.NewId) - ) + self.can_cancel = self.state in ( + "generating", + "draft", + "confirm", + "approved", + ) and not isinstance(self.id, models.NewId) @api.multi def _compute_can_confirm(self): diff --git a/openg2p_disbursement/models/openg2p_disbursement_rule.py b/openg2p_disbursement/models/openg2p_disbursement_rule.py index f90687f..69d3755 100644 --- a/openg2p_disbursement/models/openg2p_disbursement_rule.py +++ b/openg2p_disbursement/models/openg2p_disbursement_rule.py @@ -25,7 +25,7 @@ class Openg2pDisbursementRule(models.Model): default="1.0", help="It is used in computation for percentage and fixed amount. " "For e.g. A rule for Meal Voucher having fixed amount of " - u"1€ per worked day can have its quantity defined in expression " + "1€ per worked day can have its quantity defined in expression " "like days.WORK100.number_of_days.", required=True, ) diff --git a/openg2p_disbursement_advice/models/openg2p_disbursement_main.py b/openg2p_disbursement_advice/models/openg2p_disbursement_main.py index ea025ca..3cea1a7 100644 --- a/openg2p_disbursement_advice/models/openg2p_disbursement_main.py +++ b/openg2p_disbursement_advice/models/openg2p_disbursement_main.py @@ -84,6 +84,7 @@ class DisbursementMain(models.Model): required=False, default="", ) + payment_address = fields.Char(string="Payment Address", required=False) def generate_uuid(self): for rec in self: diff --git a/openg2p_disbursement_advice/views/openg2p_disbursement_main.xml b/openg2p_disbursement_advice/views/openg2p_disbursement_main.xml index aa951f3..cf3a4d7 100644 --- a/openg2p_disbursement_advice/views/openg2p_disbursement_main.xml +++ b/openg2p_disbursement_advice/views/openg2p_disbursement_main.xml @@ -25,6 +25,7 @@ + diff --git a/openg2p_registration/models/__init__.py b/openg2p_registration/models/__init__.py index 03e5d68..7bc0deb 100644 --- a/openg2p_registration/models/__init__.py +++ b/openg2p_registration/models/__init__.py @@ -11,3 +11,4 @@ from . import openg2p_registration_org_map from . import openg2p_registration_api from . import openg2p_deduplication +from . import openg2p_demographic_authentication diff --git a/openg2p_registration/models/openg2p_demographic_authentication.py b/openg2p_registration/models/openg2p_demographic_authentication.py new file mode 100644 index 0000000..26cbef5 --- /dev/null +++ b/openg2p_registration/models/openg2p_demographic_authentication.py @@ -0,0 +1,175 @@ +import requests +import json +import logging +from odoo import models + +_logger = logging.getLogger(__name__) + +UN_SUCCESS_WITH_ERRORS = "Unsuccessful with Errors" +SUCCESS_WITH_ERRORS = "Successful with Errors" +SUCCESS = "Successful" + + +class Openg2pDemographicAuthentication(models.Model): + _inherit = "openg2p.registration" + + def demo_auth(self, data): + import os + + DEMO_AUTHENTICATE_URL = os.getenv( + "DEMO_AUTHENTICATE_URL", + "http://openg2p-mosip-auth-mediator.openg2p-mosip/demoAuth", + ) + response = requests.post(DEMO_AUTHENTICATE_URL, json=data) + _logger.info("Demo Auth Response: " + str(response.content)) + return json.loads(response.content) + + def demo_auth_merge(self, data): + auth_res = self.demo_auth(data) + should_merge = False + should_create_beneficiary = False + stage_id = 0 + if auth_res["authIdStatus"] == SUCCESS: + stage_id = 6 + should_merge = self.post_auth_find_duplicate_beneficiary( + auth_res["authId"], auth_res["authIdType"] + ) + if not should_merge: + should_create_beneficiary = True + elif auth_res["authIdStatus"] == SUCCESS_WITH_ERRORS: + stage_id = 2 + elif auth_res["authIdStatus"] == UN_SUCCESS_WITH_ERRORS: + stage_id = 2 + return { + "stage_id": stage_id, + "should_merge": should_merge, + "should_create_beneficiary": should_create_beneficiary, + "auth_id": auth_res["authId"], + "auth_id_type": auth_res["authIdType"], + "auth_id_status": auth_res["authIdStatus"], + "auth_id_message": auth_res["authIdMessage"], + } + + def post_auth_create_id(self, response): + return self.env["openg2p.registration.identity"].create( + { + "name": response["auth_id"], + "type": response["auth_id_type"], + "status": response["auth_id_status"], + "message": response["auth_id_message"], + "registration_id": self.id, + } + ) + res = self.env["openg2p.registration.identity"].search( + [("registration_id", "=", self.id)] + ) + if res: + self.write({"identities": res.ids}) + + def post_auth_find_duplicate_beneficiary(self, auth_id, auth_id_type): + type_code_id = ( + self.env["openg2p.beneficiary.id_category"] + .search([("code", "=", auth_id_type)], limit=1) + .id + ) + length = len( + self.env["openg2p.beneficiary.id_number"].search( + [("name", "=", auth_id), ("category_id", "=", type_code_id)] + ) + ) + _logger.info(f"auth_id : {auth_id}. Post Auth. Size of duplicates: {length}") + return length > 0 + + def post_auth_merge(self, response): + auth_id = response["auth_id"] + auth_id_type = response["auth_id_type"] + + type_code_id = ( + self.env["openg2p.beneficiary.id_category"] + .search([("code", "=", auth_id_type)], limit=1) + .id + ) + auth_id_object = self.env["openg2p.beneficiary.id_number"].search( + [("name", "=", auth_id), ("category_id", "=", type_code_id)] + ) + existing_beneficiary = auth_id_object.beneficiary_id + _logger.info(f"auth_id: {auth_id}. Entered Post Auth Merge.") + # Fields to be merged + overwrite_data = { + "firstname": self.firstname, + "lastname": self.lastname, + "location_id": self.location_id.id, + "street": self.street, + "street2": self.street2, + "city": self.city, + "state_id": self.state_id.id, + "zip": self.zip, + "country_id": self.country_id.id, + "phone": self.phone, + "mobile": self.mobile, + "email": self.email, + "lang": self.lang, + "image": self.image, + "marital": self.marital, + "bank_account_id": self.bank_account_id.id, + "emergency_contact": self.emergency_contact, + "emergency_phone": self.emergency_phone, + } + program_ids = self.program_ids.ids + # Removing None fields + cleaned_overwrite_data = self.del_none(overwrite_data) + + # Deriving existing fields to create new beneficiary + existing_data = { + "firstname": existing_beneficiary.firstname, + "lastname": existing_beneficiary.lastname, + "othernames": existing_beneficiary.othernames, + "location_id": existing_beneficiary.location_id.id, + "street": existing_beneficiary.street, + "street2": existing_beneficiary.street2, + "city": existing_beneficiary.city, + "state_id": existing_beneficiary.state_id.id, + "zip": existing_beneficiary.zip, + "country_id": existing_beneficiary.country_id.id, + "phone": existing_beneficiary.phone, + "mobile": existing_beneficiary.mobile, + "email": existing_beneficiary.email, + "title": existing_beneficiary.title.id, + "lang": existing_beneficiary.lang, + "gender": existing_beneficiary.gender, + "birthday": existing_beneficiary.birthday, + "image": existing_beneficiary.image, + "marital": existing_beneficiary.marital, + "bank_account_id": existing_beneficiary.bank_account_id.id, + "emergency_contact": existing_beneficiary.emergency_contact, + "emergency_phone": existing_beneficiary.emergency_phone, + "program_ids": [ + (4, program) for program in existing_beneficiary.program_ids.ids + ], + } + + cleaned_existing_data = self.del_none(existing_data) + + # Merging specfic fields to beneficiary + existing_beneficiary.write(cleaned_overwrite_data) + + # Creating new beneficiary whose active=False + new_beneficiary = self.env["openg2p.beneficiary"].create(cleaned_existing_data) + # Create new registration with existing data + self.write({"beneficiary_id": existing_beneficiary.id}) + + # Storing merged id's in fields + existing_beneficiary.write( + {"merged_beneficiary_ids": [(4, new_beneficiary.id)]} + ) + existing_beneficiary.write( + {"program_ids": [(4, program) for program in program_ids]} + ) + + # Setting active false + new_beneficiary.active = False + + # self.clear_beneficiaries() + + # Archiving the current Registration + # self.archive_registration() diff --git a/openg2p_registration/models/openg2p_registration.py b/openg2p_registration/models/openg2p_registration.py index 85d483f..fd9b09b 100644 --- a/openg2p_registration/models/openg2p_registration.py +++ b/openg2p_registration/models/openg2p_registration.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- import json +import string import uuid +import logging import requests from odoo.addons.openg2p.services.matching_service import ( @@ -12,6 +14,8 @@ from odoo.exceptions import UserError, ValidationError from odoo.tools.translate import _ +_logger = logging.getLogger(__name__) + AVAILABLE_PRIORITIES = [("0", "Urgent"), ("1", "High"), ("2", "Normal"), ("3", "Low")] @@ -206,6 +210,7 @@ def _default_company_id(self): store=True, required=False, ) + # will be return registration details on api call def api_json(self): data = { @@ -305,7 +310,7 @@ def _compute_org_fields(self): rec.total_equity = 0 field = self.env["openg2p.registration.orgmap"].search( - ["&", ("regd_id", "=", rec.id), ("field_name", "=", "grand_total_le")] + ["&", ("regd_id", "=", rec.id), ("field_name", "=", "grand_total")] ) try: rec.grand_total = int(field.field_value) if field else 0 @@ -325,7 +330,7 @@ def _compute_org_fields(self): else: rec.school_approved = "yes" except BaseException as e: - print(e) + _logger.error(e) rec.school_approved = "no" # example for filtering on org custom fields @@ -468,7 +473,7 @@ def _search_approved(self, operator, val2): try: val = rec.school_approved except BaseException as e: - print(e) + _logger.error(e) continue if operator == "=": if val == val2: @@ -503,9 +508,7 @@ def create_registration_from_odk(self, odk_data): if not str(k).startswith("_"): temp[str(k).replace("-", "_").lower()] = v - country_name = ( - temp["country"] if "country" in temp.keys() else "Sierra Leone" - ) + country_name = temp["country"] if "country" in temp.keys() else "Sierra Leone" state_name = temp["state"] if "state" in temp.keys() else "Freetown" country_id = self.env["res.country"].search([("name", "=", country_name)])[0].id @@ -513,6 +516,41 @@ def create_registration_from_odk(self, odk_data): self.env["res.country.state"].search([("name", "=", state_name)])[0].id ) + _logger.info("Country ID:" + str(country_id) + " State ID:" + str(state_id)) + # calling demo auth url with data + temp["lang"] = "en_US" + + _logger.debug("Raw Data From ODK: " + json.dumps(temp)) + # check both Bank Account No and Payment address are empty or filled + if "bank_account_number" in temp.keys() and "payment_address" in temp.keys(): + if temp["bank_account_number"] is None and temp["payment_address"] is None: + raise Exception("Both the fields are empty") + return None + elif ( + temp["bank_account_number"] is not None + and temp["payment_address"] is not None + ): + raise Exception("Both the fields are present") + return None + elif ( + "bank_account_number" not in temp.keys() + and "payment_address" not in temp.keys() + ): + raise Exception("Both the fields are empty") + return None + + import os + + should_merge = False + should_create_beneficiary = False + demo_auth_res = {} + if os.getenv("SHOULD_DEMO_AUTH", "true").lower() == "true": + demo_auth_res = self.demo_auth_merge(temp) + temp["stage_id"] = demo_auth_res["stage_id"] + should_merge = demo_auth_res["should_merge"] + should_create_beneficiary = demo_auth_res["should_create_beneficiary"] + temp["gender"] = temp["gender"].lower() + try: regd = self.create( { @@ -530,12 +568,19 @@ def create_registration_from_odk(self, odk_data): else "Freetown", "country_id": country_id, "state_id": state_id, - "gender": "male", + "gender": (temp["gender"] if "gender" in temp.keys() else "male"), + "stage_id": ( + temp["stage_id"] if "stage_id" in temp.keys() else "-" + ), + "marital": temp["status_sibil"] + if "status_sibil" in temp.keys() + and temp["status_sibil"] is not None + else "single", } ) id = regd.id except BaseException as e: - print(e) + _logger.error(e) return None from datetime import datetime @@ -554,27 +599,23 @@ def create_registration_from_odk(self, odk_data): ]: org_data[k] = v continue - if ( - k - in [ - "Status", - "AttachmentsExpected", - "AttachmentsPresent", - "SubmitterName", - "SubmitterID", - "KEY", - "meta-instanceID", - "__version__", - "bank_name", - "city", - "district", - "chiefdom", - "region", - ] - or k.startswith("_") - ): + if k in [ + "Status", + "AttachmentsExpected", + "AttachmentsPresent", + "SubmitterName", + "SubmitterID", + "KEY", + "meta-instanceID", + "__version__", + "bank_name", + "city", + "district", + "chiefdom", + "region", + ] or k.startswith("_"): continue - if k == "bank_account_number": + if k == "bank_account_number" and v is not None: if len(str(v) or "") != 0: data["bank_account_number"] = str(v) res = self.env["res.partner.bank"].search( @@ -607,6 +648,8 @@ def create_registration_from_odk(self, odk_data): } ) data["bank_account_id"] = res.id + elif k == "payment_address" and v is not None: + data["payment_address"] = odk_data["payment_address"] elif k == "phone": data["phone"] = odk_data["phone"] elif hasattr(self, k): @@ -674,7 +717,7 @@ def create_registration_from_odk(self, odk_data): else: org_data.update({k: v}) except Exception as e: - print(e) + _logger.error(e) for k, v in org_data.items(): try: self.env["openg2p.registration.orgmap"].create( @@ -685,13 +728,21 @@ def create_registration_from_odk(self, odk_data): } ) except BaseException as e: - print(e) + _logger.error(e) try: regd.write(data) # Updating Program for Registration regd.program_ids = [(6, 0, temp["program_ids"])] except BaseException as e: - print(e) + _logger.error(e) + + if os.getenv("SHOULD_DEMO_AUTH", "true").lower() == "true": + regd.post_auth_create_id(demo_auth_res) + if should_merge: + regd.post_auth_merge(demo_auth_res) + if should_create_beneficiary: + regd.create_beneficiary_from_registration() + return regd @api.depends("date_open", "date_closed") @@ -890,6 +941,7 @@ def create_beneficiary_from_registration(self): "emergency_contact": self.emergency_contact, "emergency_phone": self.emergency_phone, "odk_batch_id": self.odk_batch_id, + "payment_address": self.payment_address, } beneficiary = self.env["openg2p.beneficiary"].create(data) @@ -909,7 +961,7 @@ def create_beneficiary_from_registration(self): ) for code, number in self.get_identities(): category = self.env["openg2p.beneficiary.id_category"].search( - [("type", "=", code)] + [("code", "=", code)] ) self.env["openg2p.beneficiary.id_number"].create( { @@ -963,3 +1015,8 @@ def reset_registration(self): ) default_stage_id = self._default_stage_id() self.write({"active": True, "stage_id": default_stage_id}) + + @api.multi + @api.depends("identities", "identities.name", "identities.type") + def _compute_identification(self, field_name, category_code): + """Overriding from openg2p.beneficiary model.""" diff --git a/openg2p_registration/models/openg2p_registration_api.py b/openg2p_registration/models/openg2p_registration_api.py index 9627d22..5703f9c 100644 --- a/openg2p_registration/models/openg2p_registration_api.py +++ b/openg2p_registration/models/openg2p_registration_api.py @@ -1,7 +1,10 @@ import json import asyncio +import logging from odoo.http import Controller, route, request +_logger = logging.getLogger(__name__) + class Openg2pRegistrationApi(Controller): @route("/registrations", type="json", auth="user", methods=["GET"]) @@ -61,6 +64,9 @@ def create_registration(self, **kwargs): response["id"] = new_regd.id return response except BaseException as e: + import traceback + + _logger.error(traceback.format_exc()) return {"status": 400, "error": str(e)} @route("/duplicates/", type="json", auth="user", methods=["GET"]) diff --git a/openg2p_registration/models/openg2p_registration_identification.py b/openg2p_registration/models/openg2p_registration_identification.py index 3aba6e2..702b8ce 100644 --- a/openg2p_registration/models/openg2p_registration_identification.py +++ b/openg2p_registration/models/openg2p_registration_identification.py @@ -20,8 +20,10 @@ def _get_supported_id_categories(self): type = fields.Selection( selection=lambda x: x._get_supported_id_categories(), required=True ) + status = fields.Char("Status of ID", required=False) + message = fields.Char("Message from ID Provider", required=False) registration_id = fields.Many2one("openg2p.registration", required=True, index=True) _sql_constraints = [ - ("id_uniq", "unique (type, name)", "ID already exists !"), + ("id_uniq", "unique (type, name, registration_id)", "ID already exists !"), ] diff --git a/openg2p_registration/views/openg2p_registration.xml b/openg2p_registration/views/openg2p_registration.xml index 5c90457..efc64b6 100644 --- a/openg2p_registration/views/openg2p_registration.xml +++ b/openg2p_registration/views/openg2p_registration.xml @@ -157,11 +157,13 @@ + + - +