[IMP]14.0-pms_api_rest: service OCR supplier generic

This commit is contained in:
braisab
2024-04-11 19:25:59 +02:00
committed by Darío Lodeiros
parent 54963776be
commit 447becce0b
11 changed files with 371 additions and 163 deletions

View File

@@ -5,7 +5,9 @@ from odoo.addons.datamodel.core import Datamodel
class PmsOcrInput(Datamodel): class PmsOcrInput(Datamodel):
_name = "pms.ocr.input" _name = "pms.ocr.input"
imageBase64 = fields.String(required=True, allow_none=False) imageBase64Front = fields.String(required=True, allow_none=False)
imageBase64Back = fields.String(required=False, allow_none=False)
pmsPropertyId = fields.Integer(required=True, allow_none=False)
class PmsOcrCheckinResult(Datamodel): class PmsOcrCheckinResult(Datamodel):
@@ -24,3 +26,5 @@ class PmsOcrCheckinResult(Datamodel):
residenceStreet = fields.String(required=False, allow_none=True) residenceStreet = fields.String(required=False, allow_none=True)
residenceCity = fields.String(required=False, allow_none=True) residenceCity = fields.String(required=False, allow_none=True)
countryState = fields.Integer(required=False, allow_none=True) countryState = fields.Integer(required=False, allow_none=True)
documentCountryId = fields.Integer(required=False, allow_none=True)
zip = fields.String(required=False, allow_none=True)

View File

@@ -31,3 +31,4 @@ class PmsPropertyInfo(Datamodel):
simpleFutureColor = fields.String(required=False, allow_none=True) simpleFutureColor = fields.String(required=False, allow_none=True)
language = fields.String(required=True, allow_none=False) language = fields.String(required=True, allow_none=False)
hotelImageUrl = fields.String(required=False, allow_none=True) hotelImageUrl = fields.String(required=False, allow_none=True)
isUsedOCR = fields.Boolean(required=True, allow_none=False)

View File

@@ -111,6 +111,12 @@ class PmsProperty(models.Model):
inverse_name="pms_property_id", inverse_name="pms_property_id",
) )
ocr_checkin_supplier = fields.Selection(
string="OCR Checkin Supplier",
help="Select ocr supplier for checkin documents",
selection=[],
)
# PUSH API NOTIFICATIONS # PUSH API NOTIFICATIONS
def get_payload_avail(self, avails, client): def get_payload_avail(self, avails, client):
self.ensure_one() self.ensure_one()

View File

@@ -44,3 +44,4 @@ from . import pms_avail_service
from . import pms_user_service from . import pms_user_service
from . import pms_dashboard_service from . import pms_dashboard_service
from . import feed_post_service from . import feed_post_service
from . import ocr_document_service

View File

@@ -34,130 +34,33 @@ class PmsOcr(Component):
output_param=Datamodel("pms.ocr.checkin.result", is_list=False), output_param=Datamodel("pms.ocr.checkin.result", is_list=False),
auth="jwt_api_pms", auth="jwt_api_pms",
) )
def process_ocr_document_regula(self, input_param): def process_ocr_document(self, input_param):
PmsOcrCheckinResult = self.env.datamodels["pms.ocr.checkin.result"] pms_property = self.env['pms.property'].browse(input_param.pmsPropertyId)
pms_ocr_checkin_result = PmsOcrCheckinResult() ocr_find_method_name = '_%s_document_process' % pms_property.ocr_checkin_supplier
ocr_regula_url = ( checkin_data_dict = hasattr(self, ocr_find_method_name)(
self.env["ir.config_parameter"].sudo().get_param("ocr_regula_url") input_param.imageBase64Front,
input_param.imageBase64Back
)
PmsOcrCheckinResult = self.env.datamodels["pms.ocr.checkin.result"]
return PmsOcrCheckinResult(
nationality=checkin_data_dict.get('nationality') or None,
countryId=checkin_data_dict.get('country_id') or None,
firstname=checkin_data_dict.get('firstname') or None,
lastname=checkin_data_dict.get('lastname') or None,
lastname2=checkin_data_dict.get('lastname2') or None,
gender=checkin_data_dict.get('gender') or None,
birthdate=checkin_data_dict.get('gender') or None,
documentType=checkin_data_dict.get('document_type') or None,
documentExpeditionDate=checkin_data_dict.get('document_expedition_date') or None,
documentSupportNumber=checkin_data_dict.get('document_support_number') or None,
documentNumber=checkin_data_dict.get('document_number') or None,
residenceStreet=checkin_data_dict.get('residence_street') or None,
residenceCity=checkin_data_dict.get('residence_city') or None,
countryState=checkin_data_dict.get('country_state') or None,
documentCountryId=checkin_data_dict.get('document_country_id') or None,
zip=checkin_data_dict.get('zip') or None
) )
with DocumentReaderApi(host=ocr_regula_url) as api:
params = ProcessParams(
scenario=Scenario.FULL_PROCESS,
result_type_output=[
Result.TEXT,
Result.STATUS,
Result.VISUAL_TEXT,
Result.DOCUMENT_TYPE,
],
)
request = RecognitionRequest(
process_params=params, images=[input_param.imageBase64]
)
response = api.process(request)
if response.text and response.text.field_list:
# for elemento in response.text.field_list:
# print("campo: ", elemento.field_name)
# print("valor: ", elemento.value)
# print('-')
id_country_spain = (
self.env["res.country"].search([("code", "=", "ES")]).id
)
country_id = self.process_nationality(
response.text.get_field(TextFieldType.NATIONALITY),
response.text.get_field(TextFieldType.NATIONALITY_CODE),
response.text.get_field(TextFieldType.NATIONALITY_CODE_NUMERIC),
)
firstname, lastname, lastname2 = self.process_name(
id_country_spain,
country_id,
response.text.get_field(TextFieldType.GIVEN_NAMES),
response.text.get_field(TextFieldType.FIRST_SURNAME),
response.text.get_field(TextFieldType.SECOND_SURNAME),
response.text.get_field(TextFieldType.SURNAME),
response.text.get_field(TextFieldType.SURNAME_AND_GIVEN_NAMES),
)
if country_id:
pms_ocr_checkin_result.nationality = country_id
if firstname:
pms_ocr_checkin_result.firstname = firstname
if lastname:
pms_ocr_checkin_result.lastname = lastname
if lastname2:
pms_ocr_checkin_result.lastname2 = lastname2
gender = response.text.get_field(TextFieldType.SEX)
if gender and gender.value != "":
pms_ocr_checkin_result.gender = (
"male"
if gender.value == "M"
else "female"
if gender.value == "F"
else "other"
)
date_of_birth = response.text.get_field(TextFieldType.DATE_OF_BIRTH)
if date_of_birth and date_of_birth.value != "":
pms_ocr_checkin_result.birthdate = (
datetime.strptime(
date_of_birth.value.replace("-", "/"), "%Y/%m/%d"
)
.date()
.isoformat()
)
date_of_expiry = response.text.get_field(TextFieldType.DATE_OF_EXPIRY)
age = response.text.get_field(TextFieldType.AGE)
document_class_code = response.text.get_field(
TextFieldType.DOCUMENT_CLASS_CODE
)
if (
document_class_code
and document_class_code.value != ""
and document_class_code.value == "P"
):
pms_ocr_checkin_result.documentType = (
self.env["res.partner.id_category"]
.search([("code", "=", "P")])
.id
)
date_of_issue = response.text.get_field(TextFieldType.DATE_OF_ISSUE)
if country_id == id_country_spain and (
not date_of_issue or date_of_issue.value == ""
):
date_of_issue = self.calc_expedition_date(
document_class_code,
date_of_expiry,
age,
date_of_birth,
)
pms_ocr_checkin_result.documentExpeditionDate = date_of_issue
elif date_of_issue and date_of_issue.value != "":
pms_ocr_checkin_result.documentExpeditionDate = (
date_of_issue.value.replace("-", "/")
)
support_number, document_number = self.proccess_document_number(
id_country_spain,
country_id,
document_class_code,
response.text.get_field(TextFieldType.DOCUMENT_NUMBER),
response.text.get_field(TextFieldType.PERSONAL_NUMBER),
)
if support_number:
pms_ocr_checkin_result.documentSupportNumber = support_number
if document_number:
pms_ocr_checkin_result.documentNumber = document_number
address_street, address_city, address_area = self.process_address(
id_country_spain,
country_id,
response.text.get_field(TextFieldType.ADDRESS_STREET),
response.text.get_field(TextFieldType.ADDRESS_CITY),
response.text.get_field(TextFieldType.ADDRESS_AREA),
response.text.get_field(TextFieldType.ADDRESS),
)
if address_street:
pms_ocr_checkin_result.residenceStreet = address_street
if address_city:
pms_ocr_checkin_result.residenceCity = address_city
if address_area:
pms_ocr_checkin_result.countryState = address_area
return pms_ocr_checkin_result
def process_nationality( def process_nationality(
self, nationality, nationality_code, nationality_code_numeric self, nationality, nationality_code, nationality_code_numeric

View File

@@ -62,6 +62,7 @@ class PmsPropertyService(Component):
simpleInColor=prop.simple_in_color, simpleInColor=prop.simple_in_color,
simpleFutureColor=prop.simple_future_color, simpleFutureColor=prop.simple_future_color,
language=prop.lang, language=prop.lang,
isUsedOCR=True if prop.ocr_checkin_supplier else False,
hotelImageUrl=url_image_pms_api_rest( hotelImageUrl=url_image_pms_api_rest(
"pms.property", prop.id, "hotel_image_pms_api_rest" "pms.property", prop.id, "hotel_image_pms_api_rest"
), ),
@@ -104,6 +105,7 @@ class PmsPropertyService(Component):
toAssignReservationColor=pms_property.to_assign_reservation_color, toAssignReservationColor=pms_property.to_assign_reservation_color,
pendingPaymentReservationColor=pms_property.pending_payment_reservation_color, pendingPaymentReservationColor=pms_property.pending_payment_reservation_color,
language=pms_property.lang, language=pms_property.lang,
isUsedOCR=True if pms_property.ocr_checkin_supplier else False,
) )
return res return res

View File

@@ -1 +0,0 @@
from . import pms_property

View File

@@ -1,8 +0,0 @@
from marshmallow import fields
from odoo.addons.datamodel.core import Datamodel
class PmsPropertyInfo(Datamodel):
_inherit = "pms.property.info"
isUsedRegula = fields.Boolean(required=False, allow_none=True)

View File

@@ -1,9 +1,337 @@
from regula.documentreader.webclient import (
DocumentReaderApi,
ProcessParams,
RecognitionRequest,
Result,
Scenario,
TextFieldType,
)
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
from odoo import fields, models from odoo import fields, models
class PmsProperty(models.Model): class PmsProperty(models.Model):
_inherit = "pms.property" _inherit = "pms.property"
is_used_regula = fields.Boolean( ocr_checkin_supplier = fields.Selection(
string="Used regula", help="True if this property uses regula's OCR" selection_add=["regula", "Regula"]
) )
def _regula_document_process(self, image_base_64_front, image_base_64_back=False):
ocr_regula_url = (
self.env["ir.config_parameter"].sudo().get_param("ocr_regula_url")
)
with DocumentReaderApi(host=ocr_regula_url) as api:
params = ProcessParams(
scenario=Scenario.FULL_PROCESS,
result_type_output=[
Result.TEXT,
Result.STATUS,
Result.VISUAL_TEXT,
Result.DOCUMENT_TYPE,
],
)
request = RecognitionRequest(
process_params=params, images=[image_base_64_front]
)
response = api.process(request)
if response.text and response.text.field_list:
id_country_spain = (
self.env["res.country"].search([("code", "=", "ES")]).id
)
country_id = self._process_nationality(
response.text.get_field(TextFieldType.NATIONALITY),
response.text.get_field(TextFieldType.NATIONALITY_CODE),
response.text.get_field(TextFieldType.NATIONALITY_CODE_NUMERIC),
)
firstname, lastname, lastname2 = self._process_name(
id_country_spain,
country_id,
response.text.get_field(TextFieldType.GIVEN_NAMES),
response.text.get_field(TextFieldType.FIRST_SURNAME),
response.text.get_field(TextFieldType.SECOND_SURNAME),
response.text.get_field(TextFieldType.SURNAME),
response.text.get_field(TextFieldType.SURNAME_AND_GIVEN_NAMES),
)
pms_ocr_checkin_result = dict()
if country_id:
pms_ocr_checkin_result['nationality'] = country_id
if firstname:
pms_ocr_checkin_result['firstname'] = firstname
if lastname:
pms_ocr_checkin_result['lastname'] = lastname
if lastname2:
pms_ocr_checkin_result['lastname2'] = lastname2
gender = response.text.get_field(TextFieldType.SEX)
if gender and gender.value != "":
pms_ocr_checkin_result['gender'] = (
"male"
if gender.value == "M"
else "female"
if gender.value == "F"
else "other"
)
date_of_birth = response.text.get_field(TextFieldType.DATE_OF_BIRTH)
if date_of_birth and date_of_birth.value != "":
pms_ocr_checkin_result['birthdate'] = (
datetime.strptime(
date_of_birth.value.replace("-", "/"), "%Y/%m/%d"
)
.date()
.isoformat()
)
date_of_expiry = response.text.get_field(TextFieldType.DATE_OF_EXPIRY)
age = response.text.get_field(TextFieldType.AGE)
document_class_code = response.text.get_field(
TextFieldType.DOCUMENT_CLASS_CODE
)
if (
document_class_code
and document_class_code.value != ""
and document_class_code.value == "P"
):
pms_ocr_checkin_result['documentType'] = (
self.env["res.partner.id_category"]
.search([("code", "=", "P")])
.id
)
date_of_issue = response.text.get_field(TextFieldType.DATE_OF_ISSUE)
if country_id == id_country_spain and (
not date_of_issue or date_of_issue.value == ""
):
date_of_issue = self._calc_expedition_date(
document_class_code,
date_of_expiry,
age,
date_of_birth,
)
pms_ocr_checkin_result['documentExpeditionDate'] = date_of_issue
elif date_of_issue and date_of_issue.value != "":
pms_ocr_checkin_result['documentExpeditionDate'] = (
date_of_issue.value.replace("-", "/")
)
support_number, document_number = self._proccess_document_number(
id_country_spain,
country_id,
document_class_code,
response.text.get_field(TextFieldType.DOCUMENT_NUMBER),
response.text.get_field(TextFieldType.PERSONAL_NUMBER),
)
if support_number:
pms_ocr_checkin_result['documentSupportNumber'] = support_number
if document_number:
pms_ocr_checkin_result['documentNumber'] = document_number
address_street, address_city, address_area = self._process_address(
id_country_spain,
country_id,
response.text.get_field(TextFieldType.ADDRESS_STREET),
response.text.get_field(TextFieldType.ADDRESS_CITY),
response.text.get_field(TextFieldType.ADDRESS_AREA),
response.text.get_field(TextFieldType.ADDRESS),
)
if address_street:
pms_ocr_checkin_result['residenceStreet'] = address_street
if address_city:
pms_ocr_checkin_result['residenceCity'] = address_city
if address_area:
pms_ocr_checkin_result['countryState'] = address_area
return pms_ocr_checkin_result
def _process_nationality(
self, nationality, nationality_code, nationality_code_numeric
):
country_id = False
country = False
if nationality_code_numeric and nationality_code_numeric.value != "":
country = self.env["res.country"].search(
[("code_numeric", "=", nationality_code_numeric.value)]
)
elif nationality_code and nationality_code.value != "":
country = self.env["res.country"].search(
[("code_alpha3", "=", nationality_code.value)]
)
elif nationality and nationality.value != "":
country = self.env["res.country"].search([("name", "=", nationality.value)])
if country:
country_id = country.id
return country_id
def _process_address(
self,
id_country_spain,
country_id,
address_street,
address_city,
address_area,
address,
):
res_address_street = False
res_address_city = False
res_address_area = False
state = False
if country_id == id_country_spain:
if address_street and address_street.value != "":
res_address_street = address_street.value
if address_city and address_city.value != "":
res_address_city = address_city.value
if address_area and address_area.value != "":
res_address_area = address_area.value
if (
address
and address != ""
and not (all([address_street, address_city, address_area]))
):
address = address.value.replace("^", " ")
address_list = address.split(" ")
if not res_address_area:
res_address_area = address_list[-1]
if not res_address_city:
res_address_city = address_list[-2]
if not res_address_street:
res_address_street = address.replace(
res_address_area, "", 1
).replace(res_address_city, "", 1)
if res_address_area:
state = self.env["res.country.state"].search(
[("name", "ilike", res_address_area)]
)
if state and len(state) == 1:
state = state.id
else:
if address and address.value != "":
res_address_street = address.value.replace("^", " ")
return res_address_street, res_address_city, state
def _process_name(
self,
id_country_spain,
country_id,
given_names,
first_surname,
second_surname,
surname,
surname_and_given_names,
):
firstname = False
lastname = False
lastname2 = False
if surname_and_given_names.value and surname_and_given_names.value != "":
surname_and_given_names = surname_and_given_names.value.replace("^", " ")
if given_names and given_names.value != "":
firstname = given_names.value
if first_surname and first_surname.value != "":
lastname = first_surname.value
if second_surname and second_surname.value != "":
lastname2 = second_surname.value
if country_id == id_country_spain and not (
all([firstname, lastname, lastname2])
):
if surname and surname.value != "":
lastname = lastname if lastname else surname.value.split(" ")[0]
lastname2 = lastname2 if lastname2 else surname.value.split(" ")[1:][0]
if (
surname_and_given_names
and surname_and_given_names != ""
and not firstname
):
firstname = surname_and_given_names.replace(
lastname, "", 1
).replace(lastname2, "", 1)
elif surname_and_given_names and surname_and_given_names != "":
lastname = (
lastname if lastname else surname_and_given_names.split(" ")[0]
)
lastname2 = (
lastname2 if lastname2 else surname_and_given_names.split(" ")[1]
)
firstname = (
firstname
if firstname
else surname_and_given_names.replace(lastname, "", 1).replace(
lastname2, "", 1
)
)
elif (
country_id
and country_id != id_country_spain
and not (all([firstname, lastname]))
):
if surname and surname.value != "":
lastname = lastname if lastname else surname.value
if (
surname_and_given_names
and surname_and_given_names != ""
and not firstname
):
firstname = surname_and_given_names.replace(lastname, "", 1)
elif surname_and_given_names and surname_and_given_names != "":
lastname = (
lastname if lastname else surname_and_given_names.split(" ")[0]
)
firstname = (
firstname
if firstname
else surname_and_given_names.replace(lastname, "", 1)
)
return firstname, lastname, lastname2
def _calc_expedition_date(
self, document_class_code, date_of_expiry, age, date_of_birth
):
result = False
person_age = False
if age and age.value != "":
person_age = int(age.value)
elif date_of_birth and date_of_birth.value != "":
date_of_birth = datetime.strptime(
date_of_birth.value.replace("-", "/"), "%Y/%m/%d"
).date()
person_age = relativedelta(date.today(), date_of_birth).years
if date_of_expiry and date_of_expiry.value != "" and person_age:
date_of_expiry = datetime.strptime(
date_of_expiry.value.replace("-", "/"), "%Y/%m/%d"
).date()
if person_age < 30:
result = date_of_expiry - relativedelta(years=5)
elif (
person_age >= 30
and document_class_code
and document_class_code.value == "P"
):
result = date_of_expiry - relativedelta(years=10)
elif 30 <= person_age < 70:
result = date_of_expiry - relativedelta(years=10)
return result.isoformat() if result else False
def _proccess_document_number(
self,
id_country_spain,
country_id,
document_class_code,
document_number,
personal_number,
):
res_support_number = False
res_document_number = False
if personal_number and personal_number.value != "":
res_document_number = personal_number.value
if document_number and document_number.value != "":
res_support_number = document_number.value
if (
country_id == id_country_spain
and document_class_code
and document_class_code.value != "P"
):
return res_support_number, res_document_number
else:
return False, res_support_number

View File

@@ -1,2 +0,0 @@
from . import ocr_document_service
from . import pms_property_service

View File

@@ -1,26 +0,0 @@
from odoo.addons.base_rest import restapi
from odoo.addons.base_rest_datamodel.restapi import Datamodel
from odoo.addons.component.core import Component
class PmsPropertyService(Component):
_inherit = "pms.property.service"
@restapi.method(
[
(
[
"/",
],
"GET",
)
],
output_param=Datamodel("pms.property.info", is_list=True),
auth="jwt_api_pms",
)
def get_properties(self):
result_properties = super(PmsPropertyService, self).get_properties()
for prop_info in result_properties:
pms_property = self.env["pms.property"].browse(prop_info.id)
prop_info.isUsedRegula = pms_property.is_used_regula
return result_properties