contact-person-profile-csv-imp-local 0.0.51__py3-none-any.whl → 0.0.52__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.
@@ -6,7 +6,7 @@ import sys
6
6
  from zoneinfo import ZoneInfo
7
7
  import chardet
8
8
 
9
- from .contact_person_profile_csv_imp_local_constants import CSVToContactPersonProfileConstants
9
+ from src.contact_person_profile_csv_imp_local_constants import CSVToContactPersonProfileConstants
10
10
  from data_source_local.data_source import DataSources
11
11
  # from user_external_local.user_externals_local import UserExternalsLocal
12
12
  # from user_context_remote.user_context import UserContext
@@ -50,32 +50,13 @@ DEFAULT_PROFILE_ID = 0
50
50
 
51
51
  # Those methods should be called from the common method for this repo (contact-person-profile-csv-imp-local-python-package and google-contact-sync ...)
52
52
 
53
- # TODO def process_first_name( original_first_name: str) -> str: (move to people-local-python-package)
54
- # normalized_first_name = the first word in original_first_name
55
- # GroupsLocal.add_update_group_and_link_to_contact( normalized_first_name, is_group=true, contact_id) # When checking if exists, ignore the upper-case lower-case
56
- # return normalized_first_name
57
-
58
- # TODO def process_last_name( original_last_name : str) -> str: (move to people-local-python-package)
59
- # normalized_last_name = Remove all the digits from the last name
60
- # GroupsLocal.add_update_group_and_link_to_contact( normilized_last_name, is_group=true, contact_id) # When checking if exists, ignore the upper-case lower-case
61
-
62
- # TODO def process_phone( original_phone_number: str) -> str: (move to phone-local-python-package)
63
- # phone_id, normalized_phone = PhonesLocal.link_phone_to_contact( normilized_phone, contact_id) # Please use method written by @akiva and return normalized_phone_number
64
-
65
- # TODO def process_job_title( job_title: str) -> str: (move to people-local-python-package)
66
- # normalized_job_title = GroupsLocal.add_update_group_and_link_to_contact( job_title, is_group=true, contact_id) # When checking if exists, ignore the upper-case lower-case, return the value with is_main == true
67
-
68
- # TODO def process_email_address( email_address: str)
69
- # """ Returned email_address_id, domain_name, organization_name """
70
- # DomainsLocal.link_contact_to_domain( contact_id, domain_name )
71
-
72
53
  # TODO def process_organization( organization_name: str, email_address: str) -> str: (move to people-local-python-package
73
54
  # if organization_name == None or empty
74
55
  # organization_name = extract_organization_from_email_address( email_address)
75
56
  # normalized_organization_name = GroupsLocal.add_update_group_and_link_to_contact( organization_name, is_organization=true) # When checking if the organization exists, remove suffix such as Ltd, Inc, בעמ... when searching ignore the uppper-case lower-case
76
57
 
77
58
  # TODO def process_department( department_name: str) -> str: (move to people-local-python-package
78
- # normalized_department_name = GroupsLocal.add_update_group_and_link_to_contact( department_name, is_department=true) # When searching, ignore the upper-case lower-case, return the value with is_main == true
59
+ # normalized_department_name = GroupsLocal.add_update_group_and_link_to_contact( department_name, is_department=true) # When searching ignore the upper-case lower-case, return the value with is_main == true
79
60
 
80
61
  # TODO def process_continent( continent_name: str) -> str: (move to location-local-python-package)
81
62
  # continent_id, normalized_continent_name = GroupsLocal.add_update_group_and_link_to_contact( continent_name, is_continent=true) # When checking if exists, ignore the upper-case lower-case, return the value with is_main == true
@@ -124,8 +105,10 @@ class CSVToContactPersonProfile(
124
105
  'contact_location', 'user_externals_local',
125
106
  'organizations_local', 'domain_local',
126
107
  'importers_local']
127
- GenericCRUD.__init__(self, default_schema_name="profile",
128
- default_view_table_name="profile_view",
108
+ GenericCRUD.__init__(self, default_schema_name="field",
109
+ default_column_name="field_id",
110
+ default_table_name="field_table",
111
+ default_view_table_name="field_view",
129
112
  is_test_data=is_test_data)
130
113
  self.contact_entity_type_id = \
131
114
  self.select_one_value_by_column_and_value(
@@ -171,11 +154,32 @@ class CSVToContactPersonProfile(
171
154
  # Otherwise, return the value
172
155
  return value
173
156
 
174
-
175
- # What are the diff between csv_path and directory_name?
157
+ # # TODO Does this function should be here on in https://github.com/circles-zone/variable-local-python-package/tree/dev/variable_local_python_package/variable_local/src "field/field.py"?
158
+ # def __get_field_name(self, field_id: int, data_source_type_id: int) -> str:
159
+ # """
160
+ # Get the field name from the database
161
+ # :param field_id: The field ID
162
+ # :param data_source_type_id: The data source ID
163
+ # :return: The field name
164
+ # """
165
+ #
166
+ # 'data_source_type_id': data_source_type_id})
167
+
168
+ # self.set_schema(schema_name="data_source_field")
169
+ # data_source_field_tuples = self.select_multi_tuple_by_where(view_table_name="data_source_field_view",
170
+ # select_clause_value="external_field_name",
171
+ # where="data_source_type_id = %s AND field_id = %s",
172
+ # params=(data_source_type_id, field_id))
173
+
174
+ # if data_source_field_tuples:
175
+ #
176
+ # return data_source_field_tuples[0][0]
177
+ # return
178
+
179
+ # TODO what are the diff between csv_path and directory_name?
176
180
  # ans: csv_path is the full path to the csv file, directory_name is the directory where the csv file is located
177
181
 
178
- # I think file name should be after directory_name and csv_path
182
+ # TODO I think file name should be after directory_name and csv_path
179
183
  # ans: it cannot be after directory_name and csv_path because it is a required parameter
180
184
 
181
185
  # TODO: break this function into smaller functions
@@ -204,7 +208,7 @@ class CSVToContactPersonProfile(
204
208
  :return:
205
209
  """
206
210
  data_source_type_name = DataSources().get_data_source_name_by_id(data_source_type_id)
207
- # There can be multiple profiles with the same email, why not to query `user_external_table`.`main_profile_id`?
211
+ # TODO There can be multiple profiles with the same email, why not to query `user_external_table`.`main_profile_id`?
208
212
  # Answer: first, We can't query tables with GenericCRUD, second, we may not find profile_id in user_external table
209
213
  # and may have to insert a new record to user_external_table, in this case we need profile_id from profile_view
210
214
  profile_id = self.select_one_value_by_column_and_value(
@@ -220,6 +224,7 @@ class CSVToContactPersonProfile(
220
224
  self.logger.error("Couldn't find profile_id in profile_view by email_address.")
221
225
  raise Exception("Couldn't find profile_id in user_external or profile_view.")
222
226
  system_id = system_id or CONTACT_PERSON_PROFILE_CSV_SYSTEM_ID
227
+ self.set_schema(schema_name="field")
223
228
  self.list_of_group_dicts = list_of_group_dicts if list_of_group_dicts else []
224
229
  '''
225
230
  profile_id = ProfilesLocal().select_one_value_by_column_and_value(
@@ -228,9 +233,10 @@ class CSVToContactPersonProfile(
228
233
  column_value=user_external_username)
229
234
  '''
230
235
  self.logger.info(f"profile_id: {profile_id}")
236
+ # TODO Please explain
231
237
  # if csv_path is provided then we will use the full path
232
238
  # if csv_path is not provided then we will use the directory_name and file_name to create the full path
233
- # If directory_name is not provided, the assumption is that the file is in the same directory as the script and not in a folder
239
+ # if directory_name is not provided the assumption is that the file is in the same directory as the script and not in a folder
234
240
  if csv_path is not None:
235
241
  csv_file_path = csv_path
236
242
  else:
@@ -249,7 +255,7 @@ class CSVToContactPersonProfile(
249
255
 
250
256
  user_external_id = self.__get_user_external_id(user_external_username=user_external_username,
251
257
  profile_id=profile_id, system_id=system_id)
252
- # We create a new data_source_instance_id every time we import a new csv file
258
+ # We create a new data_source_instance_id everytime we import a new csv file
253
259
  data_source_instance_id = self.__get_data_source_instance_id(
254
260
  data_source_type_id=data_source_type_id, csv_file_path=csv_file_path,
255
261
  user_external_id=user_external_id, file_name=file_name,
@@ -321,7 +327,6 @@ class CSVToContactPersonProfile(
321
327
  # contact_dict['last_name'] = process_last_name(
322
328
  # original_last_name=contact_dict['last_name'])
323
329
 
324
-
325
330
  # TODO This should be executed also by Google Contact Sync (please make sure it is in
326
331
  # people-local-python-package i.e. get_display_name(first_name, last_name, organization) -> str
327
332
  if contact_dict.get('display_as') is None:
@@ -332,6 +337,7 @@ class CSVToContactPersonProfile(
332
337
  contact_dict['display_as'] += " " + contact_dict['last_name']
333
338
  if not contact_dict['display_as'] and contact_dict.get('organization'):
334
339
  contact_dict['display_as'] += " " + contact_dict['organization']
340
+
335
341
  # TODO if contact_dict['display_as'] still empty raise?
336
342
 
337
343
  # TODO process_notes( contact_dict[notes] )
@@ -354,6 +360,8 @@ class CSVToContactPersonProfile(
354
360
  data_source_type_id=data_source_type_id)
355
361
  contact_data_by_contact_id_dict[contact_id] = contact_dict
356
362
  # groups_linked_by_job_title = process_job_title(contact_id=contact_id, job_title=contact_dict['job_title'])
363
+ # if groups_linked_by_job_title is None:
364
+ # logger.info("No groups linked by job title to contact " + str(contact_id))
357
365
 
358
366
  return contact_data_by_contact_id_dict
359
367
 
@@ -591,9 +599,7 @@ class CSVToContactPersonProfile(
591
599
  return linked_groups_results_list
592
600
 
593
601
  def __insert_link_contact_persons(self, contact_dict: dict) -> dict:
594
- # TODO create and use mandatory_fields_to_link_contact_to_person_array
595
602
  if not contact_dict.get("first_name") and not contact_dict.get("last_name"):
596
- # TODO logger.warning("Can't connect contact_id= contact.display_as= contact.organization to a person as we don't have first and last name
597
603
  return {}
598
604
  phones_local = PhonesLocal(is_test_data=self.is_test_data)
599
605
  contact_phone_number = contact_dict.get("phone1")
@@ -612,7 +618,7 @@ class CSVToContactPersonProfile(
612
618
 
613
619
  return contact_person_results_dict
614
620
 
615
- # TODO This method is confusing me, as based on the name, I was expecting to have two parameters
621
+ # TODO This method is confusing me as based on the name I was expected to to have two parameters
616
622
  # contact_dict and email_addresses but we are sending profile_id, please explain or fix
617
623
  def __insert_link_contact_email_addresses(self, contact_dict: dict) -> list[int]:
618
624
  email_addresses = self.contacts_local.get_contact_email_addresses_from_contact_dict(
@@ -651,6 +657,24 @@ class CSVToContactPersonProfile(
651
657
 
652
658
  return contact_phone_ids
653
659
 
660
+ # old, TODO, do we need it?
661
+ def __insert_link_contact_user_external(self, contact_dict: dict) -> int:
662
+ contact_id = contact_dict.get("contact_id")
663
+ print("Before " + __name__, file=sys.stderr, flush=True)
664
+ contact_user_external_id = \
665
+ self.contact_user_external.insert_contact_and_link_to_existing_or_new_user_external(
666
+ contact_dict=contact_dict,
667
+ contact_email_address_str=contact_dict["email1"],
668
+ contact_id=contact_id,
669
+ system_id=contact_dict.get("system_id"),
670
+ # TODO What happends if contact do not have email?
671
+ # TODO I'm not sure we should use contact_dict["email1"] for user_external_dict["username"] probably bug
672
+ user_external_dict={"username": contact_dict["email1"]}
673
+ )
674
+ print("After " + __name__, file=sys.stderr, flush=True)
675
+ return contact_user_external_id
676
+
677
+ # new
654
678
  def __insert_link_contact_user_external_by_contact_dict_and_user_external_dict(
655
679
  self,
656
680
  contact_dict: dict,
@@ -677,34 +701,48 @@ class CSVToContactPersonProfile(
677
701
  def __insert_link_contact_domains(self, contact_dict: dict) -> list[dict]:
678
702
  contact_id = contact_dict.get("contact_id")
679
703
  profiles_ids_list = contact_dict.get("profiles_ids_list")
704
+ organization_name = contact_dict.get("organization")
705
+ if organization_name:
706
+ organization_id = self.select_one_value_by_column_and_value(
707
+ schema_name="organization",
708
+ view_table_name="organization_view",
709
+ select_clause_value="organization_id",
710
+ column_name="name",
711
+ column_value=organization_name)
712
+ else:
713
+ organization_id = None
714
+
680
715
  website_count = 1
681
716
  website_url = contact_dict.get("website" + str(website_count))
682
717
  url_insert_information_list = []
683
718
  while website_url:
684
719
  if DomainLocal.is_domain(website_url):
685
720
  domain_insert_information_dict = self.domain_local.link_contact_to_domain(
686
- contact_id=contact_id, url=website_url)
721
+ contact_id=contact_id, url=website_url, organization_id=organization_id)
687
722
  url_insert_information_list.append(domain_insert_information_dict)
688
723
  elif DomainLocal.is_url(website_url):
689
724
  url_insert_information_dict = self.domain_local.link_contact_to_url(
690
725
  contact_id=contact_id, url=website_url, profiles_ids=profiles_ids_list)
691
726
  url_insert_information_list.append(url_insert_information_dict)
727
+ domain_insert_information_dict = self.domain_local.link_contact_to_domain(
728
+ contact_id=contact_id, url=website_url, organization_id=organization_id)
729
+ url_insert_information_list.append(domain_insert_information_dict)
692
730
  else:
693
- self.logger.warining(f"__insert_link_contact_domains: website_url: {website_url} is not a valid domain or url")
731
+ self.logger.warining(f"insert_link_contact_domains: website_url: {website_url} is not a valid domain or url")
694
732
  website_count += 1
695
733
  website_url = contact_dict.get("website" + str(website_count))
696
734
  url = contact_dict.get("url")
697
735
  if url:
698
736
  if DomainLocal.is_domain(url):
699
737
  domain_insert_information_dict = self.domain_local.link_contact_to_domain(
700
- contact_id=contact_id, url=url)
738
+ contact_id=contact_id, url=url, organization_id=organization_id)
701
739
  url_insert_information_list.append(domain_insert_information_dict)
702
740
  elif DomainLocal.is_url(url):
703
741
  url_insert_information_dict = self.domain_local.link_contact_to_url(
704
742
  contact_id=contact_id, url=url, profiles_ids=profiles_ids_list)
705
743
  url_insert_information_list.append(url_insert_information_dict)
706
744
  else:
707
- self.logger.warining(f"__insert_link_contact_domains: url: {url} is not a valid domain or url")
745
+ self.logger.warining(f"insert_link_contact_domains: url: {url} is not a valid domain or url")
708
746
 
709
747
  return url_insert_information_list
710
748
 
@@ -724,7 +762,7 @@ class CSVToContactPersonProfile(
724
762
  # TODO merge this method with the method in google-contact-sync
725
763
  def __insert_importer(self, contact_id: int, location_id: int, user_external_id: int,
726
764
  data_source_type_id: int, data_source_instance_id: int) -> int:
727
- # TODO: Shall we consider the url of CSVs as the following? Use Sql2Code. Use const enum
765
+ # TODO: Shall we consider the url of csv's as the following? Use Sql2Code. Use const enum
728
766
  if data_source_type_id == CSVToContactPersonProfileConstants.GOOGLE_CSV_DATA_SOURCE_TYPE_ID:
729
767
  url = "www.google.com"
730
768
  elif data_source_type_id == CSVToContactPersonProfileConstants.OUTLOOK_CSV_DATA_SOURCE_TYPE_ID:
@@ -749,10 +787,10 @@ class CSVToContactPersonProfile(
749
787
 
750
788
  return importer_id
751
789
 
752
- # TODO Move this method to ContactsLocal if not already exist
790
+ # TODO Move this method to ContactsLocal if not exists already
753
791
  def __procces_location_of_contact(self, contact_dict: dict) -> dict or None:
754
792
  """
755
- Process the location of the Google contact
793
+ Process location of Google contact
756
794
  :param contact_dict: location_dict
757
795
  :return: location_dict
758
796
  """
@@ -781,7 +819,6 @@ class CSVToContactPersonProfile(
781
819
  and not email_addresses_list):
782
820
  return
783
821
  # TODO: How can we add location type?
784
- # TODO Rename to processed_location_dicts
785
822
  proccessed_location_dicts = []
786
823
  if is_contact_location1:
787
824
  location_dict = self.__create_location_dict(
@@ -947,7 +984,6 @@ class CSVToContactPersonProfile(
947
984
  @staticmethod
948
985
  # TODO Move this function to python-sdk
949
986
  def detect_encoding(file_path: str, data_source_type_id: int = None):
950
- # TODO Do not use hard-coded values, get it from the data_source_type repo/package
951
987
  if data_source_type_id in [16, 17, 18]:
952
988
  detect_encodinfg_result = "utf-8"
953
989
  else:
@@ -965,3 +1001,54 @@ class CSVToContactPersonProfile(
965
1001
  cellphone_number = '+972 ' + cellphone_number
966
1002
  contact_dict['phone1'] = cellphone_number
967
1003
  return contact_dict
1004
+
1005
+ def process_email_address(self, email_address: str) -> dict:
1006
+ """
1007
+ Process email address and extract domain information
1008
+ :param email_address: Email adress to process
1009
+ :return: Dict with email_address_id, internet_domain_name, internet_domain_name_id, organization_name, organization_id
1010
+ """
1011
+ # Example email address could be: circles@circlez.ai
1012
+ if '@' not in email_address:
1013
+ return None #Invalid email address
1014
+
1015
+ # Get domain name
1016
+ internet_domain_name = email_address.split('@')[1]
1017
+
1018
+ # Get internet_domain_name_id based on internet_domain_name
1019
+ internet_domain_name_id = self.select_one_value_by_column_and_value(
1020
+ schema_name="internet_domain",
1021
+ view_table_name="internet_domain_view",
1022
+ select_clause_value="internet_domain_id",
1023
+ column_name="domain",
1024
+ column_value=internet_domain_name)
1025
+
1026
+ # Get organization_id name based on internet_domain_name
1027
+ organization_id = self.select_one_value_by_column_and_value(
1028
+ schema_name="internet_domain",
1029
+ view_table_name="internet_domain_view",
1030
+ select_clause_value="organization_id",
1031
+ column_name="domain",
1032
+ column_value=internet_domain_name)
1033
+
1034
+ # Get organization_name based on organization_id
1035
+ organization_name = self.select_one_value_by_column_and_value(
1036
+ schema_name="organization",
1037
+ view_table_name="organization_view",
1038
+ select_clause_value="name",
1039
+ column_name="organization_id",
1040
+ column_value=organization_id)
1041
+
1042
+ # Get email_address_id based on email_address
1043
+ email_address_id = self.select_one_value_by_column_and_value(
1044
+ schema_name="email_address",
1045
+ view_table_name="email_address_view",
1046
+ select_clause_value="email_address_id",
1047
+ column_name="email_address",
1048
+ column_value=email_address)
1049
+
1050
+ return {"email_address_id": email_address_id,
1051
+ "internet_domain_name": internet_domain_name,
1052
+ "internet_domain_name_id": internet_domain_name_id,
1053
+ "organization_name": organization_name,
1054
+ "organization_id": organization_id}
@@ -20,7 +20,6 @@ class CSVToContactPersonProfileConstants:
20
20
  'developer_email': DEVELOPER_EMAIL
21
21
  }
22
22
 
23
- # TODO search for the source_type_id in the database and remove those constants
24
23
  GOOGLE_CSV_DATA_SOURCE_TYPE_ID = 16
25
24
  LINKEDIN_CSV_DATA_SOURCE_TYPE_ID = 18
26
25
  OUTLOOK_CSV_DATA_SOURCE_TYPE_ID = 17
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: contact-person-profile-csv-imp-local
3
- Version: 0.0.51
3
+ Version: 0.0.52
4
4
  Summary: PyPI Package for Circles CSVToContactPersonProfile-local Local/Remote Python
5
5
  Home-page: https://github.com/circles-zone/contact-person-profile-csv-imp-local-python-package
6
6
  Author: Circles
@@ -12,7 +12,7 @@ Requires-Dist: contact-local>=0.0.48
12
12
  Requires-Dist: logger-local>=0.0.135
13
13
  Requires-Dist: database-mysql-local>=0.1.1
14
14
  Requires-Dist: user-context-remote>=0.0.77
15
- Requires-Dist: contact-email-address-local>=0.0.40.1234
15
+ Requires-Dist: contact-email-address-local>=0.0.8
16
16
  Requires-Dist: contact-group-local>=0.0.68
17
17
  Requires-Dist: contact-location-local>=0.0.14
18
18
  Requires-Dist: contact-notes-local>=0.0.33
@@ -0,0 +1,7 @@
1
+ contact_person_profile_csv_imp_local/CSVToContactPersonProfile.py,sha256=hNtIOLz7hMRxytWnsTV1y-rJC6RH6GVGw3sfX9fkpiI,57091
2
+ contact_person_profile_csv_imp_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ contact_person_profile_csv_imp_local/contact_person_profile_csv_imp_local_constants.py,sha256=SsMFKnI7y3P_kQxH21rxKnX7H4MZlemBy5vuv_Ns_a4,1180
4
+ contact_person_profile_csv_imp_local-0.0.52.dist-info/METADATA,sha256=lJQvtyEbZ1mqnP8ns3_OsNm_q8Z1Z4wEqu_t6YHYudY,1583
5
+ contact_person_profile_csv_imp_local-0.0.52.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ contact_person_profile_csv_imp_local-0.0.52.dist-info/top_level.txt,sha256=at6BnVzULDB109KZx9Cl9ClCHU4c0ykfV38WX-QR71U,37
7
+ contact_person_profile_csv_imp_local-0.0.52.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- contact_person_profile_csv_imp_local/CSVToContactPersonProfile.py,sha256=86cINZLvSqFNFYD7Z_q-WqNoIXNX3BFkDfHJZgUYg1U,53428
2
- contact_person_profile_csv_imp_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- contact_person_profile_csv_imp_local/contact_person_profile_csv_imp_local_constants.py,sha256=Wj_mBaolIK-h6To7YGeUGmgop5U95_Pfl7NXrob-6Ws,1264
4
- contact_person_profile_csv_imp_local-0.0.51.dist-info/METADATA,sha256=ZADrJdCdI_Ou9ORHltO9d8cQep0g8tHKcYaN1uYIM3I,1589
5
- contact_person_profile_csv_imp_local-0.0.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
- contact_person_profile_csv_imp_local-0.0.51.dist-info/top_level.txt,sha256=at6BnVzULDB109KZx9Cl9ClCHU4c0ykfV38WX-QR71U,37
7
- contact_person_profile_csv_imp_local-0.0.51.dist-info/RECORD,,