idvpackage 3.0.11__py3-none-any.whl → 3.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
idvpackage/ocr_utils.py CHANGED
@@ -6,11 +6,11 @@ from google.cloud import vision_v1
6
6
  from idvpackage.constants import *
7
7
  import pkg_resources
8
8
  import base64
9
- from googletrans import Translator
10
9
  from rapidfuzz import fuzz
11
10
  import logging
11
+ from datetime import datetime
12
+
12
13
  logging.basicConfig(level=logging.INFO)
13
- translator = Translator()
14
14
 
15
15
  def create_final_result(dictionary):
16
16
  result = ""
@@ -53,7 +53,6 @@ def create_sub_result(document_report):
53
53
 
54
54
  return sub_result
55
55
 
56
-
57
56
  def mark_clear(data, keys):
58
57
  if isinstance(data, dict):
59
58
  for key, value in list(data.items()):
@@ -67,7 +66,6 @@ def mark_clear(data, keys):
67
66
  else:
68
67
  return data
69
68
 
70
-
71
69
  def mark_nested_result(data, value):
72
70
  if isinstance(data, dict):
73
71
  if 'result' in data:
@@ -81,20 +79,18 @@ def mark_nested_result(data, value):
81
79
  else:
82
80
  return data
83
81
 
84
- from datetime import datetime
85
- import logging
86
82
 
87
83
  def parse_date(date_str: str, fmt: str = "%d/%m/%Y"):
88
84
  """Safely parse a date string and return a datetime object or None."""
89
85
  if not date_str:
90
86
  return None
87
+ date_str = date_str.replace(".", "/").replace("-", "/") # unify separators
91
88
  try:
92
89
  return datetime.strptime(date_str, fmt)
93
90
  except Exception as e:
94
91
  logging.exception(f"Failed to parse date: {date_str}, Error: {e}")
95
92
  return None
96
93
 
97
-
98
94
  def validation_checks_passport(data: dict, id_number_type: str, country: str):
99
95
  """
100
96
  Perform validation checks for passport-related fields such as:
@@ -103,18 +99,28 @@ def validation_checks_passport(data: dict, id_number_type: str, country: str):
103
99
  - Expiry and Issue date validations
104
100
  - Gender consistency
105
101
  """
102
+ # Initialize validation_range with default value
103
+ validation_range = range(1823, 1829) # Default: 6 years +/- 2 days
104
+
106
105
  if country == 'SDN':
107
106
  validation_range = range(3648, 3654) # 10 years +/- 2 days for Sudanese passports
108
107
 
109
- if country == 'LBN':
108
+ elif country == 'LBN':
110
109
  validation_range = list(range(1823, 1828)) + list(range(3648, 3654)) # 5 years +/- 2 days for Lebanon passports
111
110
 
112
- if country == 'JOR':
111
+ elif country == 'JOR':
113
112
  validation_range = range(1823, 1828) # 5 years (1825) +/- 2 days for Jordan passports
114
113
 
114
+ elif country == 'IRQ': #range is 8 years , in days
115
+ validation_range = range(2920, 2928) # 8 years Iraq passports
116
+
117
+ elif country == 'PSE':
118
+ validation_range = range(1823, 1828) # 5 years +/- 2 days for Palestinian passports
119
+
120
+ elif country == 'SYR':
121
+ validation_range = [days for years in [2, 3, 6] for days in range(years * 365 - 2, years * 365 + 3)]
115
122
 
116
123
  logging.info(f"Performing validation checks for country: {country} and validation_range: {validation_range}")
117
- # --- Normalize dates ---
118
124
 
119
125
  dob = normalize_date_generic(data.get("dob"))
120
126
  dob_mrz = normalize_date_generic(data.get("dob_mrz"))
@@ -131,7 +137,11 @@ def validation_checks_passport(data: dict, id_number_type: str, country: str):
131
137
  gender = data.get("gender", "")
132
138
  gender_mrz = data.get("gender_mrz", "")
133
139
 
134
- logging.info(f"Extracted Data for Validation - DOB: {dob}, DOB MRZ: {dob_mrz}, Expiry Date: {expiry_date}, Expiry Date MRZ: {expiry_date_mrz}, Issue Date: {issue_date}, ID Number: {id_number}, ID Number MRZ: {id_number_mrz}, Gender: {gender}, Gender MRZ: {gender_mrz}")
140
+ if gender:
141
+ gender = gender[0].upper()
142
+ if gender_mrz:
143
+ gender_mrz = gender_mrz[0].upper()
144
+ logging.info(f"Extracted Data for Validation - DOB: {dob}, DOB MRZ: {dob_mrz}, Expiry Date: {expiry_date}, Expiry Date MRZ: {expiry_date_mrz}, Issue Date: {issue_date}, ID Number: {id_number}, ID Number MRZ: {id_number_mrz}, Gender: {gender}, Gender MRZ: {gender_mrz}")
135
145
  # --- Initialize Flags ---
136
146
  is_id_number_same_mrz = False
137
147
  is_expiry_date_same_mrz = False
@@ -140,13 +150,14 @@ def validation_checks_passport(data: dict, id_number_type: str, country: str):
140
150
  is_gender_mrz_match = False
141
151
 
142
152
  # --- ID Number Validation ---
153
+ logging.info(f"Comparing ID Number: data field {id_number} vs MRZ {id_number_mrz}")
154
+
143
155
  if id_number and id_number_mrz:
144
- logging.info(f"Comparing ID Number: data field {id_number} vs MRZ {id_number_mrz}")
145
156
  is_id_number_same_mrz = (id_number == id_number_mrz)
146
157
 
147
158
  # --- Expiry Date Match (OCR vs MRZ) ---
159
+ logging.info(f"Comparing Expiry Date: data field {expiry_date} vs MRZ {expiry_date_mrz}")
148
160
  if expiry_date and expiry_date_mrz:
149
- logging.info(f"Comparing Expiry Date: data field {expiry_date} vs MRZ {expiry_date_mrz}")
150
161
  is_expiry_date_same_mrz = (expiry_date == expiry_date_mrz)
151
162
 
152
163
  # --- Issue vs Expiry Duration (MRZ) ---
@@ -187,72 +198,6 @@ def validation_checks_passport(data: dict, id_number_type: str, country: str):
187
198
  "is_gender_mrz_match": is_gender_mrz_match
188
199
  }
189
200
 
190
- # def validation_checks_passport(data, country):
191
-
192
- # dob_back_str = data.get("dob", "")
193
- # dob_back_mrz_str = data.get("date_of_birth_mrz", "")
194
-
195
- # dob_back = normalize_date_generic(dob_back_str)
196
- # dob_back_mrz = normalize_date_generic(dob_back_mrz_str)
197
-
198
- # expiry_date = data.get("expiry_date", "")
199
- # issue_date = data.get("issue_date", "")
200
- # expiry_date_mrz = data.get("expiry_date_mrz", "")
201
-
202
- # id_number = data.get("id_number", "")
203
- # id_number_mrz = data.get("id_number_mrz", "")
204
-
205
- # if id_number and id_number_mrz:
206
- # if id_number == id_number_mrz:
207
- # is_id_number_same_mrz= True
208
- # else:
209
- # is_id_number_same_mrz = False
210
-
211
- # if data.get('expiry_date','') and data.get('expiry_date_mrz',''):
212
-
213
- # try:
214
- # #check if both dates are same
215
- # expiry_date_obj = datetime.strptime(data.get("expiry_date", ""), "%d/%m/%Y")
216
- # expiry_date_mrz_obj = datetime.strptime(data.get("expiry_date_mrz", ""), "%d/%m/%Y")
217
-
218
- # logging.info(f"expiry_date_obj: {expiry_date_obj}, expiry_date_mrz_obj: {expiry_date_mrz_obj}")
219
-
220
- # if expiry_date_obj == expiry_date_mrz_obj:
221
- # is_expiry_date_same_mrz = True
222
- # else:
223
- # is_expiry_date_same_mrz = False
224
- # except:
225
-
226
- # is_expiry_date_same_mrz = False
227
- # logging.info("Error in comparing expiry dates for SDN ID")
228
- # pass
229
-
230
- # if data.get('issue_date', '') and data.get("expiry_date_mrz",''):
231
- # try:
232
- # issue_date_obj = datetime.strptime(data.get("issue_date", ""), "%d/%m/%Y")
233
- # logging.info(f"difference_in_days issue_date_mrz_obj: {issue_date_obj}, expiry_date_mrz_obj: {expiry_date_mrz_obj} differece is : {(expiry_date_mrz_obj - issue_date_obj).days}")
234
- # difference_in_days_mrz_obj = (expiry_date_mrz_obj - issue_date_obj).days
235
-
236
- # valid_id_duration_mrz = difference_in_days_mrz_obj in [3649,3650, 3651, 3652, 3653]
237
- # except:
238
- # logging.info("Error in calculating date difference between issue and expiry dates for SDN ID")
239
- # pass
240
-
241
- # if data.get("issue_date",'') and data.get("expiry_date",''):
242
- # try:
243
-
244
- # logging.info(f"difference_in_days issue_date_obj: {issue_date_obj}, expiry_date_obj: {expiry_date_obj} differece is : {(expiry_date_obj - issue_date_obj).days}")
245
- # difference_in_days_obj = (expiry_date_obj - issue_date_obj).days
246
-
247
- # valid_id_duration = difference_in_days_obj in [ 3649,3650, 3651, 3652, 3653]
248
-
249
- # except:
250
- # logging.info("Error in calculating date difference between issue and expiry dates from MRZ for SDN ID")
251
- # pass
252
-
253
-
254
-
255
-
256
201
  def age_validation(dob, age_threshold=18):
257
202
  age_val = {
258
203
  "breakdown": {
@@ -319,46 +264,43 @@ def is_valid_and_not_expired(expiry_date, country):
319
264
  except:
320
265
  return 'consider'
321
266
 
322
- def identify_document_type(text, country, origial_text=None):
323
- text = text.upper()
324
- emirates_id_pattern = r'\b(ILARE\w*|IDARE\w*|RESIDENT IDENTITY)\b'
325
- iqama_id_pattern = r'KINGDOM OF SAUDI ARABIA|RESIDENT IDENTITY|MINISTRY OF INTERIOR'
326
- iraq_id_pattern = r'Register|Signature|Family Number|The Directorate of Nationality|IDIRQ|The Republic of Iraq|Ministry of|National Card|Iraq'
327
- lbn_id_pattern = r'Marital status|Family|Lebanon Republic|Republic of Lebanon'
328
- qtr_id_pattern = r'State of Qatar|Residency Permit|Director General of the General Department|Directorate of Passports|Passport number'
329
- passport_pattern = r'\b(PASSPORT|PPT)\b'
330
- driver_license_pattern = r'\b(DRIVER|LICENSE|DL)\b'
331
-
332
- if re.search(emirates_id_pattern, text, re.IGNORECASE):
333
- return "EID"
267
+ def normalize_gender(gender: str):
268
+ if not gender:
269
+ return None
334
270
 
335
- if country == 'IRQ' and (re.search(iraq_id_pattern, text, re.IGNORECASE) or re.search(iraq_id_pattern, origial_text, re.IGNORECASE)):
336
- return "INC"
337
-
338
- if country == 'LBN' and re.search(lbn_id_pattern, text, re.IGNORECASE):
339
- return "LBN"
340
-
341
- if country == 'QAT' and re.search(qtr_id_pattern, text, re.IGNORECASE):
342
- return "QAT"
343
-
344
- if re.search(passport_pattern, text, re.IGNORECASE):
345
- return "PASSPORT"
271
+ gender = gender.strip().lower()
346
272
 
347
- if re.search(driver_license_pattern, text, re.IGNORECASE):
348
- return "DL"
273
+ if gender in {"m", "male"}:
274
+ return "Male"
349
275
 
350
- return "Unknown"
276
+ if gender in {"f", "female"}:
277
+ return "Female"
351
278
 
352
- def identify_front_id(text):
353
- front_id_keywords = ['Resident Identity', 'United arab emirates', 'federal authority for identity', 'ID Number', 'Kingdom of saudi arabia', 'ministry of']
354
- pattern = '|'.join(map(re.escape, front_id_keywords))
355
-
356
- if re.search(pattern, text, re.IGNORECASE):
357
- return True
358
- else:
359
- return False
279
+ return None
280
+
281
+ def normalize_mrz_date(mrz_date, out_format="%Y-%m-%d"):
282
+ """
283
+ MRZ date format: YYMMDD
284
+ """
285
+ if not mrz_date or len(mrz_date) != 6:
286
+ return None
287
+
288
+ try:
289
+ yy = int(mrz_date[0:2])
290
+ mm = int(mrz_date[2:4])
291
+ dd = int(mrz_date[4:6])
292
+
293
+ # Century inference
294
+
295
+ year = 2000 + yy
296
+
297
+ dt = datetime(year, mm, dd)
298
+ return dt.strftime(out_format)
299
+
300
+ except Exception as e:
301
+ logging.info(f"Failed to parse MRZ date {mrz_date}: {e}")
302
+ return None
360
303
 
361
- from datetime import datetime
362
304
  def normalize_date_generic(date_str, out_format="%Y-%m-%d"):
363
305
  date_str = date_str.replace(".", "/").replace("-", "/") # unify separators
364
306
  logging.info(f"Normalizing date: {date_str}")
@@ -381,74 +323,6 @@ def normalize_date_generic(date_str, out_format="%Y-%m-%d"):
381
323
  logging.info(f"Unable to parse date: {date_str}")
382
324
  return None
383
325
 
384
- def identify_back_id(text):
385
- back_id_keywords = ['ILARE', 'IDARE', 'Signature']
386
- pattern = '|'.join(map(re.escape, back_id_keywords))
387
-
388
- if re.search(pattern, text, re.IGNORECASE):
389
- return True
390
- else:
391
- return False
392
-
393
- def identify_front_id_iraq(text):
394
- front_id_keywords = ['The Republic of Iraq', 'Ministry of', 'National Card', 'Passports and Residence', 'Republic', 'Ministry', 'Iraq']
395
- pattern = '|'.join(map(re.escape, front_id_keywords))
396
-
397
- if re.search(pattern, text, re.IGNORECASE):
398
- return True
399
- else:
400
- return False
401
-
402
- def identify_back_id_iraq(back_id_text, text):
403
- back_id_keywords = ['IDIRQ', 'Signature', 'Register', 'Family Number', 'The Directorate of Nationality', 'IDIR']
404
- pattern = '|'.join(map(re.escape, back_id_keywords))
405
-
406
- if re.search(pattern, text, re.IGNORECASE):
407
- return True
408
- else:
409
- if re.search(pattern, back_id_text, re.IGNORECASE):
410
- return True
411
- else:
412
- return False
413
-
414
- def identify_front_id_lebanon(text):
415
- front_id_keywords = ['Lebanon Republic', 'Ministry of', 'Republic of Lebanon']
416
- pattern = '|'.join(map(re.escape, front_id_keywords))
417
-
418
- if re.search(pattern, text, re.IGNORECASE):
419
- return True
420
- else:
421
- return False
422
-
423
- def identify_back_id_lebanon(text):
424
- logging.info(f'\n\nIdentifying back ID Lebanon with text: {text}\n')
425
- back_id_keywords = ['Marital status', 'Family']
426
- pattern = '|'.join(map(re.escape, back_id_keywords))
427
-
428
- if re.search(pattern, text, re.IGNORECASE):
429
- return True
430
- else:
431
- return False
432
-
433
- def identify_front_id_qatar(text):
434
- front_id_keywords = ['State of Qatar', 'Residency Permit']
435
- pattern = '|'.join(map(re.escape, front_id_keywords))
436
-
437
- if re.search(pattern, text, re.IGNORECASE):
438
- return True
439
- else:
440
- return False
441
-
442
- def identify_back_id_qatar(text):
443
- back_id_keywords = ['Director General of the General Department', 'Directorate of Passports', 'Passport number']
444
- pattern = '|'.join(map(re.escape, back_id_keywords))
445
-
446
- logging.info(f'{re.search(pattern, text, re.IGNORECASE)}')
447
- if re.search(pattern, text, re.IGNORECASE):
448
- return True
449
- else:
450
- return False
451
-
452
326
  def document_on_printed_paper(image, block_size=11, c_value=2, texture_threshold=0.4, contour_area_threshold=5000):
453
327
  image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
454
328
  image_thresh = cv2.adaptiveThreshold(image_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, block_size, c_value)
@@ -466,142 +340,6 @@ def document_on_printed_paper(image, block_size=11, c_value=2, texture_threshold
466
340
  else:
467
341
  return 'clear'
468
342
 
469
-
470
- def check_logo_existence_iraq(logo_content, id_card_content, threshold=3, good_mathces_filter=0.6):
471
- nparr_logo = np.frombuffer(logo_content, np.uint8)
472
- logo = cv2.imdecode(nparr_logo, cv2.IMREAD_GRAYSCALE)
473
-
474
- nparr_id_card = np.frombuffer(id_card_content, np.uint8)
475
- id_card = cv2.imdecode(nparr_id_card, cv2.IMREAD_COLOR)
476
- id_card_gray = cv2.cvtColor(id_card, cv2.COLOR_BGR2GRAY)
477
-
478
- sift = cv2.SIFT_create()
479
-
480
- kp1, des1 = sift.detectAndCompute(logo, None)
481
- kp2, des2 = sift.detectAndCompute(id_card_gray, None)
482
-
483
- FLANN_INDEX_KDTREE = 1
484
- index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
485
- search_params = dict(checks=50)
486
- flann = cv2.FlannBasedMatcher(index_params, search_params)
487
-
488
- matches = flann.knnMatch(des1, des2, k=2)
489
-
490
- good_matches = []
491
- for m, n in matches:
492
- if m.distance < good_mathces_filter * n.distance:
493
- good_matches.append(m)
494
-
495
- # 40
496
- min_good_matches = threshold
497
- # min_good_matches = 3
498
-
499
- if len(good_matches) >= min_good_matches:
500
- return True
501
- else:
502
- return False
503
-
504
-
505
- def detect_logo(client, input_image_content, country, compare_type=None, side=None):
506
- if country == 'UAE':
507
- reference_logo_path = pkg_resources.resource_filename('idvpackage', 'template_images/emirates_id_logo.jpeg')
508
-
509
- with open(reference_logo_path, 'rb') as logo_file:
510
- reference_image_content = logo_file.read()
511
-
512
- reference_image = vision_v1.types.Image(content=reference_image_content)
513
- input_image = vision_v1.types.Image(content=input_image_content)
514
-
515
- reference_response = client.logo_detection(image=reference_image)
516
- input_response = client.logo_detection(image=input_image)
517
-
518
- reference_logos = reference_response.logo_annotations
519
- input_logos = input_response.logo_annotations
520
-
521
- for reference_logo in reference_logos:
522
- for input_logo in input_logos:
523
- if reference_logo.description.lower() == input_logo.description.lower():
524
- return 'clear'
525
-
526
- return 'consider'
527
-
528
- if country in ['IRQ', 'LBN', 'QAT'] and compare_type != 'template':
529
- if country == 'IRQ':
530
- logo_path = 'template_images/iraq_id_logo.png'
531
- good_mathces_filter = 0.6
532
- elif country == 'QAT':
533
- logo_path = 'template_images/qatar_id_logo.jpeg'
534
- good_mathces_filter = 0.7
535
-
536
- reference_logo_path = pkg_resources.resource_filename('idvpackage', logo_path)
537
- with open(reference_logo_path, 'rb') as logo_file:
538
- reference_image_content = logo_file.read()
539
- result = check_logo_existence_iraq(reference_image_content, input_image_content, 3, good_mathces_filter)
540
-
541
- if result:
542
- return 'clear'
543
- else:
544
- return 'consider'
545
-
546
- if country in ['IRQ', 'LBN', 'QAT'] and compare_type == 'template':
547
- if side == 'front':
548
- if country == 'QAT':
549
- threshold = 300
550
- front_template_path = 'template_images/qatar_front_standard_template.jpeg'
551
- elif country == 'IRQ':
552
- threshold = 40
553
- front_template_path = 'template_images/iraq_standard_template.png'
554
- else: # LBN
555
- threshold = 60
556
- front_template_path = 'template_images/lbn_front_standard_template.png'
557
- reference_logo_path = pkg_resources.resource_filename('idvpackage', front_template_path)
558
- if side == 'back':
559
- if country == 'QAT':
560
- threshold = 235
561
- back_template_path = 'template_images/qatar_back_standard_template.jpeg'
562
- elif country == 'IRQ':
563
- threshold = 140
564
- back_template_path = 'template_images/iraq_back_standard_template.jpg'
565
- else: # LBN
566
- threshold = 120
567
- back_template_path = 'template_images/lbn_back_standard_template.png'
568
- reference_logo_path = pkg_resources.resource_filename('idvpackage', back_template_path)
569
-
570
- with open(reference_logo_path, 'rb') as logo_file:
571
- reference_image_content = logo_file.read()
572
-
573
- result = check_logo_existence_iraq(reference_image_content, input_image_content, threshold)
574
-
575
- if result:
576
- return 'clear'
577
- else:
578
- return 'consider'
579
-
580
-
581
-
582
- def detect_logo_saudi(client, input_image):
583
- reference_logo_path = pkg_resources.resource_filename('idvpackage', 'template_images/sau_id_logo.png')
584
-
585
- with open(reference_logo_path, 'rb') as logo_file:
586
- reference_image_content = logo_file.read()
587
-
588
- reference_image = vision_v1.types.Image(content=reference_image_content)
589
- input_image = vision_v1.types.Image(content=input_image)
590
-
591
- reference_response = client.logo_detection(image=reference_image)
592
- input_response = client.logo_detection(image=input_image)
593
-
594
- reference_logos = reference_response.logo_annotations
595
- input_logos = input_response.logo_annotations
596
-
597
- for reference_logo in reference_logos:
598
- for input_logo in input_logos:
599
- if reference_logo.description.lower() == input_logo.description.lower():
600
- return 'clear'
601
-
602
- return 'consider'
603
-
604
-
605
343
  def perform_feature_matching(image, template_image_path):
606
344
  template_image = cv2.imread(template_image_path, cv2.IMREAD_COLOR)
607
345
 
@@ -625,8 +363,6 @@ def perform_feature_matching(image, template_image_path):
625
363
 
626
364
  return similarity_score
627
365
 
628
-
629
- # part of detecting screenshot - checks for time values seen on phone
630
366
  def extract_time_values(text_annotations):
631
367
  time_values = []
632
368
  for annotation in text_annotations:
@@ -635,7 +371,6 @@ def extract_time_values(text_annotations):
635
371
  time_values.extend(time_matches)
636
372
  return time_values
637
373
 
638
-
639
374
  def detect_screenshot(client, image):
640
375
  icons = 0
641
376
  battery_value_and_time = 0
@@ -667,26 +402,20 @@ def detect_screenshot(client, image):
667
402
  else:
668
403
  return 'clear'
669
404
 
670
-
671
405
  def detect_photo_on_screen(client, image):
672
406
  flag = 'clear'
673
407
 
674
408
  image_data = vision_v1.Image(content=base64.b64decode(image))
675
-
676
409
  image_response = client.label_detection(image=image_data)
677
410
  image_labels = image_response.label_annotations
678
411
 
679
412
  confidence_threshold = 0.58
680
-
681
413
  # 'display device'
682
-
683
414
  keywords = ['mobile phone', 'mobile device', 'portable communications device', 'communication device', 'smartphone', 'cell phone', 'touchscreen', 'laptop', 'notebook', 'computer', 'screen', 'gadget']
684
415
 
685
416
  for label in image_labels:
686
417
  description = label.description.lower()
687
418
  confidence = label.score
688
- # print(f"Description: {description}")
689
- # print(f"Confidence: {confidence}")
690
419
  if confidence >= confidence_threshold:
691
420
  match = any(fuzz.ratio(description, keyword.lower()) >= 90 for keyword in keywords)
692
421
  if match:
@@ -699,28 +428,8 @@ def fuzzy_match_fields(field1, field2, threshold=55):
699
428
  # print(f"similarity: {similarity}")
700
429
  return similarity >= threshold
701
430
 
702
- def standardize_date(input_date):
703
- input_formats = [
704
- "%Y-%m-%d", "%m-%d-%Y", "%Y%m%d",
705
- "%Y/%m/%d", "%m/%d/%Y", "%d/%m/%Y",
706
- "%Y.%m.%d", "%d.%m.%Y", "%m.%d.%Y",
707
- "%Y %m %d", "%d %m %Y", "%m %d %Y",
708
- ]
709
-
710
- for format in input_formats:
711
- try:
712
- parsed_date = datetime.strptime(input_date, format)
713
- standardized_date = parsed_date.strftime("%d/%m/%Y")
714
- print(f"\n\n---------------Standardized date: { standardized_date}")
715
- return standardized_date
716
- except ValueError:
717
- pass
718
-
719
- return None
720
-
721
431
  def compare_dates(date_str1, date_str2):
722
432
  date_format = "%d/%m/%Y"
723
-
724
433
  date1 = datetime.strptime(date_str1, date_format)
725
434
  date2 = datetime.strptime(date_str2, date_format)
726
435
 
@@ -758,9 +467,6 @@ def data_comparison_check(data, country):
758
467
  data_comparison['breakdown']['gender']['result'] = 'clear'
759
468
  else:
760
469
  data_comparison['breakdown']['gender']['result'] = 'consider'
761
-
762
- # if not fuzzy_match_fields(data.get('gender', '').lower(),user_data.get('gender', '').lower()):
763
- # data_comparison['breakdown']['gender']['result'] = 'consider'
764
470
 
765
471
  if country == 'IRQ':
766
472
  if data.get('doc_type') == 'national_identity_card':
@@ -796,18 +502,12 @@ def data_comparison_check(data, country):
796
502
  last_name = data.get('last_name', '')
797
503
 
798
504
  if user_data.get('first_name', ''):
799
- # print(f'\n\n--------------------------- Extracted first name: {first_name}')
800
- # print(f"--------------------------- User first name: {user_data.get('first_name', '')}")
801
-
802
505
  if fuzzy_match_fields(first_name.lower(), user_data.get('first_name', '').lower()):
803
506
  data_comparison['breakdown']['first_name']['result'] = 'clear'
804
507
  else:
805
508
  data_comparison['breakdown']['first_name']['result'] = 'consider'
806
509
 
807
510
  if user_data.get('last_name', ''):
808
- # print(f"\n--------------------------- Extracted last name: {last_name}")
809
- # print(f"--------------------------- User last name: {user_data.get('last_name', '')}")
810
-
811
511
  if fuzzy_match_fields(last_name.lower().replace('-', '').replace('_', ''), user_data.get('last_name', '').lower().replace('-', '').replace('_', '')):
812
512
  data_comparison['breakdown']['last_name']['result'] = 'clear'
813
513
  else:
@@ -829,15 +529,7 @@ def data_comparison_check(data, country):
829
529
 
830
530
  return data_comparison
831
531
 
832
-
833
-
834
-
835
-
836
-
837
532
  def data_consistency_check(data, front_id_text, back_id_text, country, back_img):
838
- print(f"Country here: {country}")
839
- from deep_translator import GoogleTranslator
840
-
841
533
  data_consistency = DATA_CONSISTENCY
842
534
  data_consistency = mark_clear(data_consistency, ['breakdown', 'result'])
843
535
 
@@ -858,46 +550,26 @@ def data_consistency_check(data, front_id_text, back_id_text, country, back_img)
858
550
  if not fuzzy_match_fields(data.get('last_name').lower(),passport_data.get('passport_surname').lower()):
859
551
  data_consistency['breakdown']['last_name']['result'] = 'consider'
860
552
 
861
- #### For data consistency compare data from different sources, like id and passport.
862
- #### so the dob from id should match with dob extracted from passport
863
-
864
553
  if country == 'UAE':
865
- doc_type1 = identify_document_type(front_id_text, country)
866
- doc_type2 = identify_document_type(back_id_text, country)
867
- if doc_type1 == 'EID' or doc_type2=='EID':
868
- data_consistency['breakdown']['document_type']['result'] = 'clear'
869
- else:
870
- data_consistency['breakdown']['document_type']['result'] = 'consider'
871
-
872
- if data.get('id_number_front', '') and data.get('id_number', ''):
873
- if data.get('id_number_front', '') != data.get('id_number', ''):
554
+
555
+ data_consistency['breakdown']['document_type']['result'] = 'clear'
556
+ if data.get('id_number', '') and data.get('id_number_mrz', ''):
557
+ if data.get('id_number', '') != data.get('id_number_mrz', ''):
874
558
  data_consistency['breakdown']['multiple_data_sources_present']['result'] = 'consider'
875
-
876
-
877
-
878
- if country == 'SAU':
879
- doc_type1 = identify_front_id(front_id_text)
880
- if doc_type1:
881
- data_consistency['breakdown']['document_type']['result'] = 'clear'
882
- else:
883
- data_consistency['breakdown']['document_type']['result'] = 'consider'
884
559
 
885
560
  if country == 'IRQ':
886
- if data.get('doc_type') == 'passport':
887
- if 'passport' and ('iraq' or 'republic of iraq') in data.get('passport_data').lower():
888
- data_consistency['breakdown']['document_type']['result'] = 'clear'
889
- else:
890
- data_consistency['breakdown']['document_type']['result'] = 'clear'
891
- else:
892
-
893
- data_consistency['breakdown']['document_type']['result'] = 'clear'
561
+ data_consistency['breakdown']['document_type']['result'] = 'clear'
894
562
 
895
- front_id_number = data.get('id_number_front', '')
896
- back_id_number = data.get('id_number', '')
563
+ if data.get('doc_type') == 'national_identity_card':
564
+ front_id_number = data.get('id_number', '')
565
+ back_id_number = data.get('id_number_mrz', '')
566
+
567
+ logging.info(f'Front ID Number: {front_id_number}')
568
+ logging.info(f'Back ID Number: {back_id_number}')
897
569
 
898
- if front_id_number and back_id_number:
899
- if front_id_number != back_id_number:
900
- data_consistency['breakdown']['multiple_data_sources_present']['result'] = 'consider'
570
+ if front_id_number and back_id_number:
571
+ if front_id_number != back_id_number:
572
+ data_consistency['breakdown']['multiple_data_sources_present']['result'] = 'consider'
901
573
 
902
574
  if country == 'QAT':
903
575
  data_consistency['breakdown']['gender']['result'] = 'clear'
@@ -956,42 +628,38 @@ def data_consistency_check(data, front_id_text, back_id_text, country, back_img)
956
628
  if country in ['LBN', 'SDN', 'SYR', 'JOR', 'PSE']:
957
629
  data_consistency['breakdown']['document_type']['result'] = 'clear'
958
630
 
959
- ## set default to avoid any problems of cache
960
631
  data_consistency['result'] = 'clear'
961
-
962
632
  result = create_final_result(data_consistency)
963
633
  data_consistency['result'] = result
964
634
 
965
635
  if country == 'QAT' and data_consistency['breakdown']['multiple_data_sources_present']['result'] != 'consider':
966
636
  data_consistency['result'] = 'clear'
967
-
968
- logging.info(f"\n\n---------------------------- DATA CONSISTENCY: {data_consistency}")
637
+
638
+ logging.info(f"---------------------------- DATA CONSISTENCY: {data_consistency}")
969
639
 
970
640
  return data_consistency
971
641
 
972
-
973
-
642
+ def normalize_name_parts(name_parts):
643
+ cleaned = []
644
+ for part in name_parts:
645
+ # split on any non-letter characters #use . as well
646
+ tokens = re.split(r'[^A-Za-z]+', part)
647
+ cleaned.extend(token for token in tokens if token)
648
+ return cleaned
974
649
 
975
650
  def get_name_match_mrz(data, doc_type):
976
-
977
- if data['nationality'] == 'SDN' and doc_type != 'passport':
651
+ if (data['nationality'] == 'SDN' or data.get('country') == 'UAE') and doc_type != 'passport':
978
652
  name_mrz = []
979
653
  try:
980
654
  for word in data.get("mrz3", "").split("<"):
981
655
  if word and word.isalpha():
982
656
  name_mrz.append(word)
983
-
984
- # data['name_mrz'] = " ".join(name_mrz)
985
- name = data.get("full_name_generic", "")
986
- name = name.split(" ")
987
-
988
657
  except Exception as e:
989
- name = []
658
+ name_mrz = []
990
659
  logging.info(f"Error in extracting name from MRZ for SDN ID: {e}")
991
660
  pass
992
661
 
993
- elif doc_type == 'passport' and data['nationality'] in ['SDN', 'LBN', 'JOR']:
994
-
662
+ elif doc_type == 'passport' and data['nationality'] in ['SDN', 'LBN', 'JOR', 'IRQ', 'PSE', 'SYR']:
995
663
  name_mrz = []
996
664
  mrz1 = data.get('mrz1', '')
997
665
  logging.info(f"MRZ1 extracted: {mrz1}")
@@ -1005,10 +673,8 @@ def get_name_match_mrz(data, doc_type):
1005
673
 
1006
674
  except Exception as e:
1007
675
  logging.info(f"Error in extracting name from MRZ for passport: {e}")
1008
- name_mrz = []
1009
676
  pass
1010
677
 
1011
-
1012
678
  if data['nationality'] == 'SDN':
1013
679
  name = data.get("full_name_generic", "")
1014
680
 
@@ -1018,24 +684,43 @@ def get_name_match_mrz(data, doc_type):
1018
684
  elif data['nationality'] == 'JOR':
1019
685
  name = data.get("name", "")
1020
686
 
687
+ elif data['nationality'] == 'IRQ':
688
+ name = data.get("full_name", "")
689
+ logging.info(f"Name extracted for IRQ: {name}")
690
+
691
+ elif data['nationality'] == 'PSE':
692
+ name = data.get("full_name_openai", "")
693
+
694
+ elif data['nationality'] == 'SYR':
695
+ name = data.get("full_name", "")
696
+
697
+ elif data['country'] == 'UAE':
698
+ name = data.get("name", "")
699
+
1021
700
  name = name.split(" ")
701
+ logging.info(f"Name extracted from ID: {name}")
1022
702
  try:
1023
703
 
1024
704
  logging.info(f"name on card: {name}, name from mrz: {name_mrz}")
1025
705
 
1026
706
  # sort the name parts to ensure order does not affect comparison
707
+ name = normalize_name_parts(name)
708
+ name_mrz = normalize_name_parts(name_mrz)
709
+ logging.info(f"Name parts after removing special chars - Card: {name}, MRZ: {name_mrz}")
1027
710
  name = sorted(name)
1028
- name_mrz = sorted(name_mrz)
1029
- logging.info(f"Sorted name on card: {name}, Sorted name from mrz: {name_mrz}")
1030
- min_length = min(len(name), len(name_mrz))
711
+ sorted_name_mrz = sorted(name_mrz)
712
+ logging.info(f"Sorted name on card: {name}, Sorted name from mrz: {sorted_name_mrz}")
713
+ min_length = min(len(name), len(sorted_name_mrz))
714
+ logging.info(f"Name parts after removing special chars - Card: {name}, MRZ: {sorted_name_mrz}")
715
+ min_length = min(len(name), len(sorted_name_mrz))
1031
716
 
1032
717
  from rapidfuzz import fuzz
1033
718
  flag = True
1034
719
 
1035
720
  count = 0
1036
721
  for i in range(min_length):
1037
- ratio = fuzz.ratio(name[i].lower(), name_mrz[i].lower())
1038
- logging.info(f"Comparing name parts: {name[i]} and {name_mrz[i]}, ratio: {ratio}")
722
+ ratio = fuzz.ratio(name[i].lower(), sorted_name_mrz[i].lower())
723
+ logging.info(f"Comparing name parts: {name[i]} and {sorted_name_mrz[i]}, ratio: {ratio}")
1039
724
  if ratio < 70:
1040
725
  count = count +1
1041
726
 
@@ -1069,7 +754,6 @@ def is_age_18_above(dob_str):
1069
754
  logging.warning(f"Could not parse date: {dob_str}")
1070
755
  return False
1071
756
 
1072
-
1073
757
  def is_expired_id(expiry_date):
1074
758
  """
1075
759
  Checks if an ID is expired.
@@ -1120,7 +804,6 @@ def data_validation_check(data, country):
1120
804
 
1121
805
  try:
1122
806
  dob = data.get('dob')
1123
- # print(f"DOB: {dob}")
1124
807
  dob = get_dates_to_generic_format(dob)
1125
808
  parsed_date = datetime.strptime(dob, "%d/%m/%Y")
1126
809
  data_validation["breakdown"]['date_of_birth']["result"] = 'clear'
@@ -1216,7 +899,7 @@ def data_validation_check(data, country):
1216
899
  data_validation["breakdown"]['expiry_date']["result"] = 'clear'
1217
900
 
1218
901
  if country == 'IRQ' and data.get('doc_type') == 'national_identity_card' and not data.get('card_number'):
1219
- doc_no = data.get('card_number_front', '')
902
+ doc_no = data.get('card_number', '')
1220
903
  if len(doc_no)==9:
1221
904
  data_validation["breakdown"]['document_numbers']["result"] = 'clear'
1222
905
  else:
@@ -1246,7 +929,6 @@ def data_validation_check(data, country):
1246
929
  else:
1247
930
  data_validation['breakdown']['expiry_date']['result'] = 'consider'
1248
931
 
1249
-
1250
932
  result = create_final_result(data_validation)
1251
933
  data_validation['result'] = result
1252
934
 
@@ -1255,7 +937,6 @@ def data_validation_check(data, country):
1255
937
 
1256
938
  ## pending
1257
939
  def image_integrity_check(data, front_id_text, back_id_text, coloured, blurred, glare, missing_fields, country):
1258
- from deep_translator import GoogleTranslator
1259
940
  image_integrity = IMAGE_INTEGRITY
1260
941
  image_integrity = mark_clear(image_integrity, ['breakdown', 'result'])
1261
942
 
@@ -1275,14 +956,13 @@ def image_integrity_check(data, front_id_text, back_id_text, coloured, blurred,
1275
956
  image_quality_result = create_final_result(image_integrity['breakdown']['image_quality'])
1276
957
  image_integrity['breakdown']['image_quality']['result'] = image_quality_result
1277
958
 
1278
- f_result = 'clear'
1279
- if data.get('doc_type') == 'national_identity_card':
1280
- f_result = identify_front_id(front_id_text)
1281
-
959
+ f_result = True
1282
960
  front_doc_on_pp = data.get('front_doc_on_pp')
1283
961
 
1284
962
  if country == 'UAE' and not data.get('uae_pass_data', ''):
1285
- b_result = identify_back_id(back_id_text)
963
+ logging.info(f"UAE Image integrity check for ID card or passport {back_id_text}")
964
+ b_result = True
965
+ logging.info(f"UAE back id result: {b_result}")
1286
966
 
1287
967
  if back_id_text and b_result:
1288
968
  image_integrity['breakdown']['conclusive_document_quality']['properties']['missing_back'] = 'clear'
@@ -1293,21 +973,11 @@ def image_integrity_check(data, front_id_text, back_id_text, coloured, blurred,
1293
973
  image_integrity['breakdown']['supported_document']['result'] = 'clear'
1294
974
  else:
1295
975
  image_integrity['breakdown']['supported_document']['result'] = 'consider'
1296
-
1297
- if country == 'SAU':
1298
- if f_result:
1299
- image_integrity['breakdown']['supported_document']['result'] = 'clear'
1300
- else:
1301
- image_integrity['breakdown']['supported_document']['result'] = 'consider'
1302
-
1303
- image_integrity['breakdown']['conclusive_document_quality']['properties']['digital_document'] = front_doc_on_pp
1304
976
 
1305
977
  if country == 'IRQ' and data.get('doc_type') == 'national_identity_card':
1306
978
  image_integrity['breakdown']['conclusive_document_quality']['properties']['missing_back'] = 'clear'
1307
979
  image_integrity['breakdown']['supported_document']['result'] = 'clear'
1308
-
1309
-
1310
-
980
+
1311
981
  elif country == 'IRQ' and data.get('doc_type') == 'passport':
1312
982
  image_integrity['breakdown']['conclusive_document_quality']['properties']['missing_back'] = 'clear'
1313
983
  if 'passport' and ('iraq' or 'republic of iraq') in data.get('passport_data').lower():
@@ -1383,20 +1053,18 @@ def image_integrity_check(data, front_id_text, back_id_text, coloured, blurred,
1383
1053
  if country=='IRQ':
1384
1054
  image_integrity['result']='clear'
1385
1055
 
1386
-
1387
- logging.info(f"\n\n---------------------------- IMAGE INTEGRITY: {image_integrity}")
1056
+ logging.info(f"---------------------------- IMAGE INTEGRITY: {image_integrity}")
1388
1057
 
1389
1058
  return image_integrity
1390
1059
 
1391
1060
  def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_similarity, face_match_threshold, country):
1392
- from deep_translator import GoogleTranslator
1393
1061
  visual_authenticity = VISUAL_AUTHENTICITY
1394
1062
  visual_authenticity = mark_clear(visual_authenticity, ['breakdown', 'result'])
1395
1063
 
1396
1064
  if np.any(selfie):
1397
1065
  ## if facial similarity is matching the threshold or even if facial similarity comes above 40 then we say face was detected - approach can be changed
1398
1066
  logging.info(f'Facial similarity: {facial_similarity}, Threshold: {face_match_threshold}\n')
1399
- if facial_similarity > face_match_threshold:
1067
+ if facial_similarity >= face_match_threshold:
1400
1068
  visual_authenticity['breakdown']['face_detection'] = 'clear'
1401
1069
  visual_authenticity['breakdown']['security_features'] = 'clear'
1402
1070
  else:
@@ -1406,9 +1074,6 @@ def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_
1406
1074
  visual_authenticity['breakdown']['face_detection'] = ''
1407
1075
  visual_authenticity['breakdown']['security_features'] = ''
1408
1076
 
1409
- if data.get('doc_type') == 'national_identity_card':
1410
- doc_type1 = identify_document_type(front_id_text, country, front_id_text)
1411
-
1412
1077
  front_doc_on_pp = data.get('front_doc_on_pp')
1413
1078
  front_screenshot = data.get('front_screenshot_result')
1414
1079
  front_photo_on_screen_result = data.get('front_photo_on_screen_result')
@@ -1423,35 +1088,18 @@ def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_
1423
1088
  visual_authenticity['breakdown']['original_document_present']['properties']['photo_of_screen'] = 'consider'
1424
1089
 
1425
1090
  if country == 'UAE' and not data.get('uae_pass_data', ''):
1426
- doc_type2 = identify_document_type(back_id_text, country)
1427
- if doc_type1 == 'EID' and doc_type2 == 'EID':
1428
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1429
- else:
1430
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'consider'
1431
-
1432
- if country == 'SAU':
1433
- if identify_front_id(front_id_text):
1434
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1435
- else:
1436
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'consider'
1437
-
1438
- visual_authenticity['breakdown']['original_document_present']['properties']['document_on_printed_paper'] = front_doc_on_pp
1439
- visual_authenticity['breakdown']['original_document_present']['properties']['screenshot'] = front_screenshot
1440
- visual_authenticity['breakdown']['original_document_present']['properties']['photo_of_screen'] = front_photo_on_screen_result
1441
-
1091
+ visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1092
+ visual_authenticity['breakdown']['face_detection'] = 'clear'
1093
+ visual_authenticity['breakdown']['security_features'] = 'clear'
1094
+
1442
1095
  if country == 'IRQ':
1443
1096
  if data.get('doc_type') == 'passport':
1444
- if 'passport' and ('iraq' or 'republic of iraq') in data.get('passport_data').lower():
1445
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1446
- else:
1447
- visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1097
+ visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1448
1098
  else:
1449
-
1450
1099
  visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1451
1100
  visual_authenticity['breakdown']['template']['result'] = data.get('front_template_result')
1452
1101
  visual_authenticity['breakdown']['digital_tampering']['result'] = data.get('tampering_result')
1453
-
1454
-
1102
+
1455
1103
  if country == 'LBN':
1456
1104
  visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1457
1105
  visual_authenticity['breakdown']['original_document_present']['properties']['screenshot'] = 'clear'
@@ -1466,7 +1114,6 @@ def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_
1466
1114
  visual_authenticity['breakdown']['digital_tampering']['result'] = 'clear'
1467
1115
  visual_authenticity['breakdown']['template']['result'] = 'clear'
1468
1116
 
1469
-
1470
1117
  if country in ['SDN', 'SYR', 'JOR', 'PSE']:
1471
1118
  visual_authenticity['breakdown']['original_document_present']['properties']['scan'] = 'clear'
1472
1119
  visual_authenticity['breakdown']['original_document_present']['properties']['screenshot'] = 'clear'
@@ -1478,12 +1125,9 @@ def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_
1478
1125
 
1479
1126
  ## set default to avoid any problems of cache
1480
1127
  visual_authenticity['result'] = 'clear'
1481
-
1482
1128
  final_result = create_final_result(visual_authenticity)
1483
1129
  visual_authenticity['result'] = final_result
1484
1130
 
1485
- # print(f"\n\n------------------------- VISUAL AUTHENTICITY DOC: {visual_authenticity}")
1486
-
1487
1131
  back_doc_on_pp = data.get('doc_on_pp')
1488
1132
  if front_doc_on_pp == 'consider' or back_doc_on_pp == 'consider':
1489
1133
  visual_authenticity['breakdown']['original_document_present']['properties']['document_on_printed_paper'] = 'consider'
@@ -1493,7 +1137,7 @@ def visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_
1493
1137
  visual_authenticity['breakdown']['original_document_present']['properties']['document_on_printed_paper'] = 'clear'
1494
1138
  visual_authenticity['result'] = 'clear'
1495
1139
 
1496
- logging.info(f"\n\n---------------------------- VISUAL AUTHENTICITY: {visual_authenticity}")
1140
+ logging.info(f"---------------------------- VISUAL AUTHENTICITY: {visual_authenticity}")
1497
1141
  return visual_authenticity
1498
1142
 
1499
1143
  def main_details(data, country):
@@ -1689,15 +1333,30 @@ def main_details(data, country):
1689
1333
  for key in keys:
1690
1334
  main_properties[key] = data.get(key, '')
1691
1335
 
1692
- if country in ['IRQ', 'LBN', 'QAT', 'SDN', 'SYR', 'JOR', 'PSE']:
1336
+ if country in ['IRQ', 'LBN', 'QAT', 'SDN', 'SYR', 'JOR', 'PSE', 'UAE']:
1337
+
1338
+ if country == 'UAE':
1339
+ main_prop_data = {}
1340
+ if data.get('doc_type') == 'national_identity_card':
1341
+ keys = ['dob_mrz', 'expiry_date_mrz', 'id_number_mrz', 'name_mrz', 'card_number_mrz','is_name_match_mrz',
1342
+ 'id_number_front_back_mrz_match','card_number_back_mrz_match','dob_mrz_match','expiry_date_mrz_match','gender_mrz_match','name_mrz_match'
1343
+ ]
1344
+ keys_to_remove = []
1693
1345
  if country == 'IRQ':
1694
1346
  main_prop_data = {}
1695
1347
  if data.get('doc_type') == 'passport':
1348
+ logging.info(f"Extracting main details for IRQ passport")
1696
1349
  keys_to_remove = ['issuing_place', 'occupation', 'employer', 'mrz_line3', 'family_sponsor', 'issuing_authority_en', 'place_of_birth_en', 'gender_ar', 'name_en', 'name', 'first_name']
1697
- keys = ['full_name', 'id_number', 'mrz', 'issue_date','issuing_authority', 'mother_name', 'place_of_birth', 'mother_first_name', 'mother_first_name_en', 'mother_last_name', 'mother_last_name_en']
1350
+ keys = ['full_name', 'id_number', 'mrz', 'issue_date','issuing_authority', 'mother_name', 'place_of_birth', 'mother_first_name', 'mother_first_name_en', 'mother_last_name',
1351
+ 'mother_last_name_en','expiry_date_mrz','dob_mrz', 'gender_mrz','id_number_mrz','name_mrz','is_name_match_mrz',
1352
+ 'is_dob_match_mrz', 'is_id_number_match_mrz','is_expiry_date_match_mrz','is_valid_id_duration','is_valid_id_duration_mrz','is_gender_mrz_match']
1698
1353
  else:
1699
1354
  keys_to_remove = ['occupation', 'employer', 'family_sponsor', 'issuing_place']
1700
- keys = ['name_en', 'name', 'first_name', 'father_name', 'third_name', 'mother_first_name', 'mother_last_name', 'last_name', 'first_name_en', 'father_name_en', 'last_name_en', 'third_name_en', 'mother_first_name_en', 'mother_last_name_en', 'issuing_authority', 'nationality', 'gender', 'issuing_country', 'gender_ar', 'mrz', 'place_of_birth', 'issuing_authority_en', 'place_of_birth_en', "issue_date", "id_number", "card_number", 'family_number', 'family_number_en']
1355
+ keys = ['name_en', 'name', 'first_name', 'father_name', 'third_name', 'mother_first_name', 'mother_last_name',
1356
+ 'last_name', 'first_name_en', 'father_name_en', 'last_name_en', 'third_name_en', 'mother_first_name_en',
1357
+ 'mother_last_name_en', 'issuing_authority', 'nationality', 'gender', 'issuing_country', 'gender_ar', 'mrz',
1358
+ 'place_of_birth', 'issuing_authority_en', 'place_of_birth_en', "issue_date", "id_number", "card_number", 'family_number', 'family_number_en',
1359
+ 'card_number_mrz', 'id_number_mrz', 'valid_id_duration_mrz', 'dob_back_and_mrz_match', 'exp_date_back_and_mrz_match', 'gender_front_and_back_match', 'id_number_front_back_match']
1701
1360
 
1702
1361
  if country == 'LBN':
1703
1362
  main_prop_data = {}
@@ -1749,18 +1408,25 @@ def main_details(data, country):
1749
1408
  main_prop_data = {}
1750
1409
  keys_to_remove = ['name', 'issuing_place', 'occupation', 'employer', 'mrz_line3', 'family_sponsor', 'issuing_country']
1751
1410
  if data.get('doc_type') == 'passport':
1752
- keys = ['full_name', 'first_name', 'last_name', 'father_name', 'mother_name', 'place_of_birth', 'place_of_issue', 'dob', 'nationality', 'gender', 'passport_number', 'issue_number', 'issuing_date', 'national_number', 'mrz1', 'mrz2', 'mrz', 'issuing_country']
1411
+ keys = ['full_name', 'first_name', 'last_name', 'father_name', 'mother_name', 'place_of_birth', 'place_of_issue', 'dob', 'nationality', 'gender', 'passport_number', 'issue_number',
1412
+ 'issuing_date', 'national_number', 'mrz1', 'mrz2', 'mrz', 'issuing_country',
1413
+ 'passport_number_mrz','name_mrz', 'dob_mrz', 'expiry_date_mrz','gender_mrz',
1414
+ 'is_valid_id_duration','is_valid_id_duration_mrz','is_passport_number_match_mrz','is_dob_match_mrz','is_gender_mrz_match','is_name_match_mrz']
1753
1415
 
1754
1416
 
1755
1417
  if country == 'PSE':
1756
1418
  main_prop_data = {}
1757
1419
  keys_to_remove = ['name', 'issuing_place', 'occupation', 'employer', 'mrz_line3', 'family_sponsor']
1758
1420
  if data.get('doc_type') == 'passport':
1759
- keys = ['full_name', 'first_name', 'last_name', 'mother_name', 'place_of_birth', 'dob', 'issuing_date', 'nationality', 'gender', 'place_of_issue', 'passport_number', 'id_number', 'mrz1', 'mrz2', 'mrz', 'issuing_country']
1421
+ keys = ['full_name', 'first_name', 'last_name', 'mother_name', 'place_of_birth', 'dob', 'issuing_date', 'nationality', 'gender',
1422
+ 'place_of_issue', 'passport_number', 'id_number', 'mrz1', 'mrz2', 'mrz', 'issuing_country',
1423
+ 'passport_number_mrz','name_mrz', 'dob_mrz', 'expiry_date_mrz','gender_mrz',
1424
+ 'is_valid_id_duration','is_valid_id_duration_mrz','is_passport_number_match_mrz','is_dob_match_mrz','is_gender_mrz_match','is_name_match_mrz']
1760
1425
 
1761
1426
  for key in keys:
1762
1427
  main_prop_data[key] = data.get(key, '')
1763
1428
 
1429
+ logging.info(f"Main properties before removal: {main_prop_data.keys()}")
1764
1430
  if keys_to_remove:
1765
1431
  for key in keys_to_remove:
1766
1432
  if key in main_properties:
@@ -1771,7 +1437,6 @@ def main_details(data, country):
1771
1437
  if main_properties.get('issue_date', ''):
1772
1438
  main_properties['issue_date'] = onfido_date_format(get_dates_to_generic_format(main_properties['issue_date']))
1773
1439
 
1774
-
1775
1440
 
1776
1441
  if not data.get('card_number') and data.get('card_number_front'):
1777
1442
  card_data_t = {
@@ -1823,7 +1488,6 @@ def form_final_data_document_report(data, front_id_text, back_id_text, country,
1823
1488
  dob = data.get('dob', '')
1824
1489
 
1825
1490
  document_report = {
1826
- ## pending - to be filled by dev
1827
1491
  "_id": "",
1828
1492
  "breakdown": {
1829
1493
  "age_validation": age_validation(dob),
@@ -1847,20 +1511,16 @@ def form_final_data_document_report(data, front_id_text, back_id_text, country,
1847
1511
  "police_record": {},
1848
1512
  "visual_authenticity": visual_authenticity_check(data, front_id_text, back_id_text, selfie, facial_similarity, face_match_threshold, country)
1849
1513
  },
1850
- ## pending - to be filled by dev
1851
1514
  "check_id": "",
1852
1515
  "created_at": created_at(),
1853
1516
  "documents": [
1854
1517
  {
1855
- ## pending - id value in table stored in db for front id - to be filled by dev
1856
1518
  "id": ""
1857
1519
  },
1858
1520
  {
1859
- ## pending - id value in table stored in db for front id - to be filled by dev
1860
1521
  "id": ""
1861
1522
  }
1862
1523
  ],
1863
- # to be filled by dev
1864
1524
  "href": "",
1865
1525
  "name": "document",
1866
1526
  "properties": main_details(data, country),
@@ -1960,7 +1620,6 @@ def form_final_facial_similarity_report(data, selfie, facial_similarity, livenes
1960
1620
  facial_report['breakdown']['visual_authenticity']['breakdown']['spoofing_detection']['properties']['score'] = ''
1961
1621
  facial_report['breakdown']['visual_authenticity']['breakdown']['spoofing_detection']['result'] = ''
1962
1622
 
1963
- # if np.any(selfie) and liveness_result:
1964
1623
  visual_authenticity_final_result = create_final_result(facial_report['breakdown']['visual_authenticity'])
1965
1624
  facial_report['breakdown']['visual_authenticity']['result'] = visual_authenticity_final_result
1966
1625