Exemple #1
0
    def _add_single_record_type_entries(
        self, rt_element: MetadataElement, api_name: str, picklist: str, entry: Dict
    ):
        # Locate, or add, the root picklistValues element for this picklist.
        picklist_element = rt_element.find(
            "picklistValues", picklist=picklist
        ) or rt_element.append("picklistValues")
        if not picklist_element.find("picklist", text=picklist):
            picklist_element.append("picklist", text=picklist)

        # If this picklist value entry is not already present, add it.
        default = str(process_bool_arg(entry.get("default", False))).lower
        fullName = entry["fullName"]

        # The Metadata API's behavior with picklist values in record types
        # is to return partially URL-encoded values. Most punctuation appears
        # to be escaped, but spaces and high-bit characters are not.
        # To route around this, we compare the `unquote()`-ed
        # value of each element, since we don't know in 100% of cases
        # how to make our input look like what MDAPI returns.

        # Note that this behavior is different from picklist values in value sets.
        def find_matching_value(picklist, target):
            return next(
                filter(
                    lambda x: unquote(x.fullName.text) == target,
                    picklist.findall("values"),
                ),
                None,
            )

        values = find_matching_value(picklist_element, fullName)
        if not values:
            add_before = entry.get("add_before")
            if add_before:
                before_elem = find_matching_value(picklist_element, add_before)
                if before_elem:
                    values = picklist_element.insert_before(before_elem, "values")
                else:
                    values = picklist_element.append("values")
            else:
                values = picklist_element.append("values")

            # The Metadata API does _not_ require us to perform its partial URL-encoding to deploy.
            values.append("fullName", text=fullName)
            values.append("default", text=str(default).lower())

        # If this picklist value needs to be made default, remove any existing default.
        if default:
            # Find existing default and remove it, while setting our value as default
            for value in picklist_element.values:
                default = value.find("default")
                if default:
                    default.text = (
                        "false" if value.fullName.text != fullName else "true"
                    )
    def _add_record_type_entries(self, metadata: MetadataElement,
                                 api_name: str, picklist: str, entry: Dict):
        if "*" in self.options["record_types"]:
            rt_list = metadata.findall("recordTypes")
        else:
            rt_list = [
                metadata.find("recordTypes", fullName=record_type)
                for record_type in self.options["record_types"]
            ]

        for rt_element in rt_list:
            # Silently ignore record types that don't exist in the target org.
            if rt_element:
                self._add_single_record_type_entries(rt_element, api_name,
                                                     picklist, entry)
Exemple #3
0
    def _transform_entity(self, metadata: MetadataElement,
                          api_name: str) -> MetadataElement:
        """Finds metadata's first child with tag.  If no child is found, appends
        a new child with tag.  Then updates child's text as the value option."""
        tag = self.options["tag"]

        child = metadata.find(tag)
        if child is None:
            child = metadata.append(tag)

        child.text = self.options["value"]

        self.logger.info(f'Updating {self.entity} "{api_name}":')
        self.logger.info(f'    {tag} as "{child.text}"')

        return metadata
Exemple #4
0
    def _transform_entity(self, metadata: MetadataElement,
                          api_name: str) -> Optional[MetadataElement]:
        status = "true" if process_bool_arg(
            self.options["active"]) else "false"
        metadata.find("isActive").text = status

        return metadata
Exemple #5
0
    def _transform_entity(self, metadata: MetadataElement, api_name: str):
        for entry in self.options.get("entries", []):
            if "fullName" not in entry or "label" not in entry:
                raise TaskOptionsError(
                    "Standard value set entries must contain the 'fullName' and 'label' keys."
                )

            # Check for extra metadata on CaseStatus and OpportunityStage
            if api_name == "OpportunityStage":
                if not all([
                        "closed" in entry,
                        "forecastCategory" in entry,
                        "probability" in entry,
                        "won" in entry,
                ]):
                    raise TaskOptionsError(
                        "OpportunityStage standard value set entries require the keys "
                        "'closed', 'forecastCategory', 'probability', and 'won'"
                    )
            if api_name == "CaseStatus":
                if "closed" not in entry:
                    raise TaskOptionsError(
                        "CaseStatus standard value set entries require the key 'closed'"
                    )

            existing_entry = metadata.findall("standardValue",
                                              fullName=entry["fullName"])

            if not existing_entry:
                # Entry doesn't exist. Insert it.
                elem = metadata.append(tag="standardValue")
                elem.append("fullName", text=entry["fullName"])

                elem.append("label", text=entry["label"])

                elem.append("default", text="false")

                if api_name in ["OpportunityStage", "CaseStatus"]:
                    elem.append("closed", str(entry["closed"]).lower())

                if api_name == "OpportunityStage":
                    elem.append("won", str(entry["won"]).lower())
                    elem.append("probability", str(entry["probability"]))
                    elem.append("forecastCategory", entry["forecastCategory"])

        return metadata
Exemple #6
0
    def _transform_entity(
        self, metadata: MetadataElement, api_name: str
    ) -> MetadataElement:
        desired_internal_model = self.owds[api_name].get("internal_sharing_model")
        desired_external_model = self.owds[api_name].get("external_sharing_model")

        if desired_external_model:
            external_model = metadata.find("externalSharingModel")
            if not external_model:
                external_model = metadata.append("externalSharingModel")
            external_model.text = desired_external_model

        if desired_internal_model:
            internal_model = metadata.find("sharingModel")
            if not internal_model:
                internal_model = metadata.append("sharingModel")
            internal_model.text = desired_internal_model

        return metadata
Exemple #7
0
    def _transform_entity(self, metadata: MetadataElement,
                          api_name: str) -> Optional[MetadataElement]:
        related_list = self._inject_namespace(self.options["related_list"])
        existing_related_lists = metadata.findall("relatedLists",
                                                  relatedList=related_list)

        if existing_related_lists:
            return None

        self._create_new_related_list(metadata, api_name, related_list)

        return metadata
    def _add_picklist_field_entry(self, vsd: MetadataElement, api_name: str,
                                  picklist: str, entry: Dict):
        fullName = entry["fullName"]
        label = entry.get("label") or fullName
        default = entry.get("default", False)
        add_before = entry.get("add_before")

        if vsd.find("value", fullName=fullName):
            self.logger.warning(
                f"Picklist entry with fullName {fullName} already exists on picklist {picklist}."
            )
        else:
            if add_before and vsd.find("value", fullName=add_before):
                entry_element = vsd.insert_before(
                    vsd.find("value", fullName=add_before), "value")
            else:
                entry_element = vsd.append("value")
            entry_element.append("fullName", text=fullName)
            entry_element.append("label", text=label)
            entry_element.append("default", text=str(default).lower())

        # If we're setting this as the default, unset all of the other entries.
        if default:
            for value in vsd.findall("value"):
                default = value.find("default")
                if default:
                    default.text = ("false" if value.fullName.text != fullName
                                    else "true")
Exemple #9
0
    def _modify_picklist(self, metadata: MetadataElement, api_name: str, picklist: str):
        # Locate the <fields> entry for this picklist.
        field = metadata.find("fields", fullName=picklist)

        if not field:
            raise TaskOptionsError(f"The field {api_name}.{picklist} was not found.")

        vsd = field.valueSet.find("valueSetDefinition")
        if not vsd:
            raise TaskOptionsError(
                f"The picklist {api_name}.{picklist} uses a Global Value Set, which is not supported."
            )

        # Update each entry in this picklist, and also add to all record types.
        for entry in self.options["entries"]:
            self._add_picklist_field_entry(vsd, api_name, picklist, entry)

            if self.options["record_types"]:
                self._add_record_type_entries(metadata, api_name, picklist, entry)
Exemple #10
0
 def _modify_help_text(
     self,
     metadata: MetadataElement,
     api_name: str,
     custom_field: str,
     help_text: str,
 ):
     # Locate the <fields> entry for this field entry.
     field = metadata.find("fields", fullName=custom_field)
     if not field:
         raise TaskOptionsError(
             f"The field {api_name}.{custom_field} was not found.")
     try:
         if (field.inlineHelpText.text == ""
                 or field.inlineHelpText.text == help_text
                 or self.options["overwrite"]):
             field.inlineHelpText.text = help_text
         else:
             self.logger.warning(
                 f"Help text for field {api_name} has a different value. "
                 "Set the overwrite option to True to overwrite this field help text."
             )
     except AttributeError:
         field.append("inlineHelpText", text=help_text)