contact-person-profile-csv-imp-local 0.0.28__py3-none-any.whl → 0.0.30__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.
@@ -1,3 +1,4 @@
1
+ # TODO Please rename the file based on our naming convention i.e. contact_person
1
2
  import csv
2
3
  import os
3
4
  from datetime import datetime
@@ -18,6 +19,7 @@ from importer_local.ImportersLocal import ImportersLocal
18
19
  from database_mysql_local.point import Point
19
20
  from database_mysql_local.generic_crud import GenericCRUD
20
21
  from contact_user_external_local.contact_user_external_local import ContactUserExternalLocal
22
+ from profile_local.profiles_local import ProfilesLocal
21
23
  from contact_profile_local.contact_profiles_local import ContactProfilesLocal
22
24
  from contact_phone_local.contact_phone_local import ContactPhoneLocal
23
25
  from phones_local.phones_local import PhonesLocal
@@ -103,13 +105,14 @@ DEFAULT_PROFILE_ID = 0
103
105
 
104
106
  class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
105
107
  object=CSVToContactPersonProfileConstants.CSV_LOCAL_PYTHON_PACKAGE_CODE_LOGGER_OBJECT):
106
- def __init__(self, is_test_data: bool = False) -> None:
108
+ def __init__(self, groups_str: str = None, is_test_data: bool = False) -> None:
107
109
  GenericCRUD.__init__(self, default_schema_name="field", default_column_name="field_id",
108
110
  default_table_name="field_table", default_view_table_name="field_view",
109
111
  is_test_data=is_test_data)
110
112
  self.contact_entity_type_id = self.select_one_value_by_column_and_value(
111
113
  schema_name="entity_type", view_table_name="entity_type_ml_en_view",
112
114
  select_clause_value="entity_type_id", column_name="title", column_value="Contact")
115
+ self.groups_list: list[str] = [group.strip() for group in groups_str.split(",")] if groups_str else []
113
116
  self.user_context = UserContext()
114
117
  self.organization_profiles = OrganizationProfilesLocal(is_test_data=is_test_data)
115
118
  self.contact_persons = ContactPersonsLocal(is_test_data=is_test_data)
@@ -155,8 +158,10 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
155
158
  # ans: it cannot be after directory_name and csv_path because it is a required parameter
156
159
 
157
160
  # TODO: break this function into smaller functions
161
+ # TODO Align the parameters between import-contact-csv with sync-google-contact
162
+ # TODO Can we please add groups_str parameter to both sync-google-contact and import-contact-csv where we add all contacts to those groups?
158
163
  def insert_update_contact_from_csv(
159
- self, *, data_source_type_id: int, file_name: str = None, user_external_username: str,
164
+ self, *, data_source_type_id: int, file_name: str = None, user_external_username: str, system_id: int = None,
160
165
  # TODO Add support to criteria_set_id
161
166
  directory_name: str = None, csv_path: str = None, start_index: int = 0, end_index: int = None) -> dict:
162
167
  """
@@ -170,7 +175,10 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
170
175
  :param end_index: The end index
171
176
  :return:
172
177
  """
173
-
178
+ profile_id = ProfilesLocal().select_one_value_by_column_and_value(
179
+ schema_name="profile", view_table_name="profile_view",
180
+ select_clause_value="profile_id", column_name="profile_main_email",
181
+ column_value=user_external_username)
174
182
  # TODO Please explain
175
183
  # if csv_path is provided then we will use the full path
176
184
  # if csv_path is not provided then we will use the directory_name and file_name to create the full path
@@ -183,15 +191,16 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
183
191
  if not os.path.exists(csv_file_path):
184
192
  raise FileNotFoundError(f"File {csv_file_path} not found")
185
193
 
194
+ # TODO Why do we need it? - Those fields will be added to the contact_dict
186
195
  contact_fields_to_keep = (
187
196
  'name_prefix', 'additional_name', 'name_suffix', 'nickname', 'full_name', 'title', 'department', 'notes',
188
197
  'first_name', 'last_name', 'phone1', 'phone2', 'phone3', 'birthday', 'email1', 'email2', 'email3',
189
- 'hashtag', 'url', 'groups',
198
+ 'hashtag', 'url', 'groups', 'added_timestamp',
190
199
  'website1', 'handle', 'address1_street', 'address1_city', 'address1_state', 'address1_postal_code',
191
200
  'address1_country', 'address2_street', 'address2_city', 'address2_state', 'address2_postal_code',
192
201
  'address2_country', 'job_title', 'organization', 'display_as')
193
202
 
194
- user_external_id = self.__get_user_external_id(user_external_username)
203
+ user_external_id = self.__get_user_external_id(user_external_username=user_external_username, profile_id=profile_id)
195
204
  # We create a new data_source_instance_id everytime we import a new csv file
196
205
  data_source_instance_id = self.__get_data_source_instance_id(
197
206
  data_source_type_id=data_source_type_id, csv_file_path=csv_file_path,
@@ -200,6 +209,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
200
209
  start_index=start_index, end_index=end_index
201
210
  )
202
211
  fields_dictonary = self.data_sources.get_fields_name_from_csv(data_source_type_id)
212
+ self.logger.info(f"fields_dictonary: {fields_dictonary}")
203
213
  keys = list(fields_dictonary.keys())
204
214
  contact_data_by_contact_id_dict = {}
205
215
  encoding = CSVToContactPersonProfile.detect_encoding(file_path=csv_file_path, data_source_type_id=data_source_type_id)
@@ -240,6 +250,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
240
250
 
241
251
  contact_dict = {key: contact_dict.get(
242
252
  key) or None for key in contact_fields_to_keep}
253
+ self.logger.info(f"contact_dict: {contact_dict}")
243
254
  if (not contact_dict.get('first_name')
244
255
  and not contact_dict.get('last_name')
245
256
  and not contact_dict.get('organization')):
@@ -279,8 +290,10 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
279
290
 
280
291
  # TODO We should take care of situation which the contact already exists and we need to update it
281
292
  contact_dict["data_source_instance_id"] = data_source_instance_id
293
+ contact_dict["data_source_type_id"] = data_source_type_id
282
294
  contact_dict["source"] = "Import"
283
- contact_dict["owner_profile_id"] = self.user_context.get_effective_profile_id()
295
+ contact_dict["owner_profile_id"] = profile_id
296
+ contact_dict["system_id"] = system_id
284
297
  contact_id = self.contacts_local.upsert_contact_dict(contact_dict=contact_dict)
285
298
  contact_dict["contact_id"] = contact_id
286
299
  if contact_id:
@@ -302,6 +315,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
302
315
  # TODO Use regex to extract the data from the URL
303
316
  # TODO add to user_external using user-external-python-package
304
317
 
318
+ # TODO This looks like a generic method, please move it to url-remote-python-package
305
319
  @staticmethod
306
320
  def process_url(original_url: str) -> str:
307
321
  prefixes = ['http://', 'https://'] # noqa
@@ -316,6 +330,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
316
330
 
317
331
  # TODO: add a method to add notes to text_block process them to retrieve the groups and create and link the groups to the user
318
332
 
333
+ # TODO Please change ALL methods which are not public to become private
319
334
  def process_notes(self, contact_note: str) -> None:
320
335
  # TODO number_of_system_recommednded_groups_identified_in_contact_notes = get_system_recommended_groups_from_contact_notes( contact_notes: str)
321
336
 
@@ -333,6 +348,10 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
333
348
 
334
349
  pass
335
350
 
351
+
352
+ # TODO Please move this method if not exists to LocationsLocal
353
+ # TODO get_location_type_id_by_location_name(
354
+ # This method is being used by import-csv-contact
336
355
  def get_location_type_id_by_name(self, location_type_name: str) -> int or None:
337
356
  """
338
357
  Get the location type ID by its name
@@ -344,6 +363,8 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
344
363
  select_clause_value="location_type_id", column_name="title", column_value=location_type_name)
345
364
  return location_type_id
346
365
 
366
+ # TODO Move this method to ContactsLocal class in contact-local
367
+ # This method is being used by import-csv-contact
347
368
  def __insert_contact_details_to_db(self, *, contact_dict: dict, user_external_id: int,
348
369
  data_source_instance_id: int, data_source_type_id: int) -> int:
349
370
 
@@ -352,7 +373,10 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
352
373
 
353
374
  # insert link contact_location
354
375
  # The location is in contact_dict
376
+ # TODO Can we have a better name for locations_results? Maybe contact_locations?
355
377
  location_results = self.__insert_link_contact_location(contact_dict=contact_dict) or [{}]
378
+ # TODO Why do we process only [0]? What if there are multiple locations?
379
+ # TODO If we don't suppose multiple locations, maybe we should change it to contact_dict["main_location_id"] as we do in other places
356
380
  contact_dict["location_id"] = location_results[0].get("location_id")
357
381
  contact_dict["country_id"] = location_results[0].get("country_id")
358
382
 
@@ -396,6 +420,8 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
396
420
  )
397
421
  return importer_id
398
422
 
423
+ # TODO Move this method to LocationsLocal
424
+ # This method is being used by import-csv-contact
399
425
  def __insert_organization(self, contact_dict: dict) -> int or None:
400
426
 
401
427
  if not contact_dict.get("organization"):
@@ -440,6 +466,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
440
466
 
441
467
  return organization_dict
442
468
 
469
+ # TODO When do we use it? Multiple profiles to one organization?
443
470
  def __insert_organization_profile(self, organization_id: int, profiles_ids_list: list[int]) -> list[int] or None:
444
471
 
445
472
  if not organization_id or not profiles_ids_list:
@@ -462,6 +489,8 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
462
489
  _groups = contact_dict.get("groups").split(", ")
463
490
  for group in _groups:
464
491
  groups.append(group)
492
+ for group in self.groups_list:
493
+ groups.append(group)
465
494
  if len(groups) > 0:
466
495
  groups_linked = self.contact_groups.insert_link_contact_group_with_group_local(
467
496
  contact_id=contact_id, groups_names=groups)
@@ -568,12 +597,15 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
568
597
  location_dicts = self.__procces_location_of_contact(contact_dict)
569
598
  if not location_dicts:
570
599
  return
571
- location_results = [self.contact_location.insert_contact_and_link_to_location(
572
- location_dict=location_dict, contact_id=contact_id)
573
- for location_dict in location_dicts]
574
-
575
- return location_results
576
-
600
+ locations_results = []
601
+ for location_dict in location_dicts:
602
+ location_results = self.contact_location.insert_contact_and_link_to_location(
603
+ location_dict=location_dict, contact_id=contact_id)
604
+ if location_results:
605
+ locations_results.append(location_results)
606
+ return locations_results
607
+
608
+ # TODO merge this method with the method in google-contact-sync
577
609
  def __insert_importer(self, contact_id: int, location_id: int, user_external_id: int,
578
610
  data_source_type_id: int, data_source_instance_id: int) -> int:
579
611
  # TODO: Shall we consider the url of csv's as the following? Use Sql2Code. Use const enum
@@ -583,7 +615,8 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
583
615
  url = "www.outlook.com"
584
616
  elif data_source_type_id == 18:
585
617
  url = "www.linkedin.com"
586
- elif data_source_type_id == 57:
618
+ # TODO Please change all Magic Numbers to data generated by Sql2Code
619
+ elif data_source_type_id == 57: # BGU Course csv
587
620
  url = None
588
621
  else:
589
622
  raise ValueError("data_source_type_id is not valid")
@@ -598,6 +631,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
598
631
 
599
632
  return importer_id
600
633
 
634
+ # TODO Move this method to ContactsLocal if not exists already
601
635
  def __procces_location_of_contact(self, contact_dict: dict) -> dict or None:
602
636
  """
603
637
  Process location of Google contact
@@ -689,6 +723,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
689
723
  return proccessed_location_dicts
690
724
 
691
725
  @staticmethod
726
+ # TODO Move this method to LocationsLocal if not exists already
692
727
  def __create_location_dict(*, address_street: str, address_city: str, address_postal_code: str,
693
728
  address_country: str, address_state: str) -> dict:
694
729
  location_dict = {
@@ -706,19 +741,21 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
706
741
  return location_dict
707
742
 
708
743
  @staticmethod
744
+ # Move this method to ContactsLocal if not exists already
709
745
  def __get_phone_numbers_list(contact_dict: dict) -> list:
710
746
  phones_list = [contact_dict.get(f"phone{i}")
711
747
  for i in range(1, 4) if contact_dict.get(f"phone{i}")]
712
748
  return phones_list
713
749
 
714
750
  @staticmethod
751
+ # Move this method to ContactsLocal if not exists already
715
752
  def __get_email_addresses_list(contact_dict: dict) -> list:
716
753
  emails_list = [contact_dict.get(f"email{i}")
717
754
  for i in range(1, 4) if contact_dict.get(f"email{i}")]
718
755
  # TODO use enum const for "email1" ....
719
756
  return emails_list
720
757
 
721
- def __get_user_external_id(self, user_external_username: str) -> int or None:
758
+ def __get_user_external_id(self, user_external_username: str, profile_id: int) -> int or None:
722
759
 
723
760
  user_external_id = self.user_externals_local.select_one_value_by_column_and_value(
724
761
  select_clause_value="user_external_id", column_name="username",
@@ -726,7 +763,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
726
763
  if user_external_id is None:
727
764
  self.user_externals_local.insert_or_update_user_external_access_token(
728
765
  username=user_external_username,
729
- profile_id=self.user_context.get_effective_profile_id(),
766
+ profile_id=profile_id,
730
767
  system_id=CONTACT_PERSON_PROFILE_CSV_SYSTEM_ID,
731
768
  access_token=""
732
769
  )
@@ -736,6 +773,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
736
773
 
737
774
  return user_external_id
738
775
 
776
+ # Move this method to DataSourceInstancesLocal in data-source-instance-local-python-package
739
777
  def __get_data_source_instance_id(self, data_source_type_id: int, csv_file_path: str, user_external_id: int,
740
778
  file_name: str,
741
779
  user_external_username: str, start_index: int, end_index: int) -> int:
@@ -760,6 +798,7 @@ class CSVToContactPersonProfile(GenericCRUD, metaclass=MetaLogger,
760
798
  return data_source_instance_id
761
799
 
762
800
  @staticmethod
801
+ # TODO Move this function to python-sdk
763
802
  def detect_encoding(file_path: str, data_source_type_id: int = None):
764
803
  if data_source_type_id == 16 or data_source_type_id == 17 or data_source_type_id == 18:
765
804
  return "utf-8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: contact-person-profile-csv-imp-local
3
- Version: 0.0.28
3
+ Version: 0.0.30
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
@@ -1,7 +1,7 @@
1
- contact_person_profile_csv_imp_local/CSVToContactPersonProfile.py,sha256=KlaCY4YDlMu77bZLF7sIXHiYLfiDu7scds_CyS4ugMc,41462
1
+ contact_person_profile_csv_imp_local/CSVToContactPersonProfile.py,sha256=PyxEVut4mNat6KEkWs7N8p8cnvSZR4plprBUi-hws_c,44312
2
2
  contact_person_profile_csv_imp_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  contact_person_profile_csv_imp_local/contact_person_profile_csv_imp_local_constants.py,sha256=eE0Bg2dCPrmG72K20k0_KOckc61C9cGSgH0Zgae_lbk,957
4
- contact_person_profile_csv_imp_local-0.0.28.dist-info/METADATA,sha256=ZpO8eNNPmyDib3wNYdxIMAcK5faKxhghbPHKYQC3cK8,1481
5
- contact_person_profile_csv_imp_local-0.0.28.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
- contact_person_profile_csv_imp_local-0.0.28.dist-info/top_level.txt,sha256=at6BnVzULDB109KZx9Cl9ClCHU4c0ykfV38WX-QR71U,37
7
- contact_person_profile_csv_imp_local-0.0.28.dist-info/RECORD,,
4
+ contact_person_profile_csv_imp_local-0.0.30.dist-info/METADATA,sha256=EEJl_VnhaKYKRdo4v7_Y_tkZYzEVrdcZhIzxaDW47-o,1481
5
+ contact_person_profile_csv_imp_local-0.0.30.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
6
+ contact_person_profile_csv_imp_local-0.0.30.dist-info/top_level.txt,sha256=at6BnVzULDB109KZx9Cl9ClCHU4c0ykfV38WX-QR71U,37
7
+ contact_person_profile_csv_imp_local-0.0.30.dist-info/RECORD,,