Source code for pypipedrive.models.person_fields

from typing import Dict, List
from typing_extensions import Self
from pypipedrive.api import V1, V2
from pypipedrive.utils import warn_endpoint_legacy
from pypipedrive.orm.model import Model
from pypipedrive.orm import fields as F


[docs]class PersonFields(Model): """ Person fields represent the near-complete schema for a person in the context of the company of the authorized user. Each company can have a different schema for their persons, with various custom fields. In the context of using person fields as a schema for defining the data fields of a person, it must be kept in mind that some types of custom fields can have additional data fields which are not separate person fields per se. Such is the case with monetary, daterange and timerange fields - each of these fields will have one additional data field in addition to the one presented in the context of person fields. For example, if there is a monetary field with the key ``ffk9s9`` stored on the account, ``ffk9s9`` would hold the numeric value of the field, and ``ffk9s9_currency`` would hold the ISO currency code that goes along with the numeric value. To find out which data fields are available, fetch one person and list its keys. See `PersonFields API reference <https://developers.pipedrive.com/docs/api/v1/PersonFields>`_. Get all person fields. * GET[Cost:20] ``v1/personFields`` **DEPRECATED** * GET[Cost:10] ``v2/personFields`` Get one person field. * GET[Cost:2] ``v1/personFields/{id}`` **DEPRECATED** * GET[Cost:1] ``v2/personFields/{field_code}`` Add a new person field. * POST[Cost:10] ``v1/personFields`` **DEPRECATED** * POST[Cost:5] ``v2/personFields`` Add person field options in bulk. * POST[Cost:5] ``v2/personFields/{field_code}/options`` Update a person field. * PUT[Cost:10] ``v1/personFields/{id}`` **DEPRECATED** * PATCH[Cost:5] ``v2/personFields/{field_code}`` Update person field options in bulk. * PATCH[Cost:5] ``v2/personFields/{field_code}/options`` Delete multiple person fields in bulk. * DELETE[Cost:10] ``v1/personFields`` Delete a person field. * DELETE[Cost:6] ``v1/personFields/{id}`` **DEPRECATED** * DELETE[Cost:3] ``v2/personFields/{field_code}`` Delete person field options in bulk. * DELETE[Cost:3] ``v2/personFields/{field_code}/options`` """ id = F.TextField("id") # Used for compatibility (=None) field_name = F.TextField("field_name") field_code = F.TextField("field_code") field_type = F.TextField("field_type") options = F.OptionsField("options") subfields = F.SubfieldField("subfields") is_custom_field = F.BooleanField("is_custom_field") is_optional_response_field = F.BooleanField("is_optional_response_field") class Meta: entity_name = "personFields" version = V2 field_id = "field_code" # Indicates field used as the object id.
[docs] @classmethod def get(cls, id: str, params: Dict = {}) -> Self: """ Returns metadata about a specific person field. Allowed query params: - ``include_fields`` (str): Optional comma separated string array of additional data namespaces to include in response. Values: `ui_visibility`, `important_fields`, `required_fields`. Args: id: The code of the person field to retrieve. params: Additional query parameters. Returns: An instance of PersonFields representing the person field. """ assert isinstance(id, str), "`id` must be a string" return super().get(id=id, params=params)
[docs] def add_options(self, option_labels: List[Dict[str, str]]) -> Dict: """ Adds new options to a person custom field that supports options (enum or set field types). This operation is atomic - all options are added or none are added. Returns only the newly added options. Args: option_labels: A list of option dictionaries to add. Each item must contain a label. At least one option is required. Returns: A dictionary containing the newly added options. """ if self.field_type not in ["enum", "set"]: raise ValueError( "`PersonFields.add_options()` is only supported for " "'enum' and 'set' field types." ) assert isinstance(self.field_code, str), "`field_code` must be a string" assert isinstance(option_labels, list), "`option_labels` must be a list" for option in option_labels: assert isinstance(option, dict), "each `option` must be a dict" assert list(option.keys()) == ["label"], \ "each `option` must contain only the `label` key" assert isinstance(option.get("label"), str), \ "`label` value must be a string" uri = f"{self._get_meta('entity_name')}/{self.field_code}/options" response = self.get_api(version=V2).post(uri=uri, json=option_labels) self.fetch() # Refresh the model data after adding options return response.to_dict()
[docs] def update_options(self, options: List[Dict]) -> Dict: """ Updates existing options for a person custom field. This operation is atomic and fails if any of the specified option IDs do not exist. Returns only the updated options. Args: options: A list of option dictionaries to update. Each item must contain an id and label. Returns: A dictionary containing the updated options. """ if self.field_type not in ["enum", "set"]: raise ValueError( "`PersonFields.update_options()` is only supported for " "'enum' and 'set' field types." ) assert isinstance(self.field_code, str), "`field_code` must be a string" assert isinstance(options, list), "`options` must be a list" for option in options: assert isinstance(option, dict), "each `option` must be a dict" assert set(option.keys()) == {"id", "label"}, \ "each `option` must contain only the `id` and `label` keys" assert isinstance(option.get("id"), int), "`id` value must be an integer" assert isinstance(option.get("label"), str), "`label` value must be a string" uri = f"{self._get_meta('entity_name')}/{self.field_code}/options" response = self.get_api(version=V2).patch(uri=uri, json=options) self.fetch() # Refresh the model data after updating options return response.to_dict()
[docs] def delete_options(self, option_ids: List[str]) -> Dict: """ Removes existing options from a person custom field. This operation is atomic and fails if any of the specified option IDs do not exist. Returns only the deleted options. Args: option_ids: A list of option IDs to delete. Returns: A dictionary containing the deleted options. """ if self.field_type not in ["enum", "set"]: raise ValueError( "`PersonFields.add_options()` is only supported for " "'enum' and 'set' field types." ) assert isinstance(self.field_code, str), "`field_code` must be a string" assert isinstance(option_ids, list), "`option_ids` must be a list" for option in option_ids: assert isinstance(option, dict), "each `option` must be a dict" assert list(option.keys()) == ["id"], \ "each `option` must contain only the `id` key" assert isinstance(option.get("id"), int), \ "`id` value must be an integer" uri = f"{self._get_meta('entity_name')}/{self.field_code}/options" response = self.get_api(version=V2).delete(uri=uri, json=option_ids) self.fetch() # Refresh the model data after deleting options return response.to_dict()
[docs] @warn_endpoint_legacy @classmethod def batch_delete(cls, ids: List[str]) -> Dict: """ Marks multiple fields as deleted. Args: ids: A list of field codes to delete. Returns: A dictionary containing the result of the batch delete operation. """ return super().batch_delete(ids=ids, version=V1).to_dict()