Example #1
0
    def test_accounting_datetimes_utc(self, model_name, field_name, value,
                                      expected):
        result = Result(model_name, {model_name: {field_name: value}})

        assert getattr(
            result, field_name
        ) == expected, f"{model_name}.{field_name} should equal {expected}"
Example #2
0
    def delete(self, account_id: str, resource_id: int) -> Result:
        """Delete a resource.

        Note: Most FreshBooks resources are soft-deleted,
        See [FreshBooks API - Active and Deleted Objects](https://www.freshbooks.com/api/active_deleted)

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to delete

        Returns:
            Result: An empty Result object.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("delete")
        if self.delete_via_update:
            response = self._request(
                self._get_url(account_id, resource_id),
                HttpVerbs.PUT,
                data={self.single_name: {
                    "vis_state": VisState.DELETED
                }})
        else:
            response = self._request(self._get_url(account_id, resource_id),
                                     HttpVerbs.DELETE)
        return Result(self.single_name, response)
Example #3
0
    def update(self,
               account_id: str,
               resource_id: int,
               data: dict,
               includes: Optional[IncludesBuilder] = None) -> Result:
        """Update a resource.

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to update
            data: Dictionary of data to update the resource to
            builders: (Optional) IncludesBuilder object for including additional data, sub-resources, etc.

        Returns:
            Result: Result object with the updated resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("update")
        resource_url = self._get_url(account_id, resource_id)
        query_string = ""
        if includes:
            query_string = self._build_query_string([includes])
        response = self._request(f"{resource_url}{query_string}",
                                 HttpVerbs.PUT,
                                 data={self.single_name: data})
        return Result(self.single_name, response)
Example #4
0
    def get(self, business_id: int, resource_id: int) -> Result:
        """Get a single resource with the corresponding id.

        Args:
            business_id: The business id
            resource_id: Id of the resource to return
        Returns:
            Result: Result object with the resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("get")
        data = self._request(self._get_url(business_id, resource_id), HttpVerbs.GET)
        return Result(self.single_name, data)
    def defaults(self, account_id: str) -> Result:
        """Get the default settings for an account resource.

        Args:
            account_id: The alpha-numeric account id
        Returns:
            Result: Result object with the default data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("defaults")
        resource_url = self._get_url(account_id)
        data = self._request(resource_url, HttpVerbs.GET)
        return Result(self.single_name, data)
    def get(self, account_id: str, resource_id: int) -> Result:
        """Get a single resource with the corresponding id.

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to return payment details for
        Returns:
            Result: Result object with the resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("get")
        resource_url = self._get_url(account_id, resource_id)
        data = self._request(resource_url, HttpVerbs.GET)
        return Result(self.single_name, data)
Example #7
0
    def create(self, business_id: int, data: dict) -> Result:
        """Create a resource.

        Args:
            business_id: The business id
            data: Dictionary of data to populate the resource

        Returns:
            Result: Result object with the new resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("create")
        response = self._request(self._get_url(business_id), HttpVerbs.POST, data={self.single_name: data})
        return Result(self.single_name, response)
    def create(self, account_id: str, resource_id: int, data: dict) -> Result:
        """Create a resource.

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to create payment details for
            data: Dictionary of data to populate the resource

        Returns:
            Result: Result object with the new resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("create")
        resource_url = self._get_url(account_id, resource_id)
        response = self._request(resource_url, HttpVerbs.POST, data=data)
        return Result(self.single_name, response)
Example #9
0
    def delete(self, business_id: int, resource_id: int) -> Result:  # pragma: no cover
        """Delete a resource.

        Note: Most FreshBooks resources are soft-deleted,
        See [FreshBooks API - Active and Deleted Objects](https://www.freshbooks.com/api/active_deleted)

        Args:
            business_id: The business id
            resource_id: Id of the resource to delete

        Returns:
            Result: An empty Result object.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("delete")
        response = self._request(self._get_url(business_id, resource_id), HttpVerbs.DELETE)
        return Result(self.single_name, response)
Example #10
0
    def update(self, business_id: int, resource_id: int, data: dict) -> Result:
        """Update a resource.

        Args:
            business_id: The business id
            resource_id: Id of the resource to update
            data: Dictionary of data to update the resource to

        Returns:
            Result: Result object with the updated resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("update")
        response = self._request(
            self._get_url(business_id, resource_id), HttpVerbs.PUT, data={self.single_name: data}
        )
        return Result(self.single_name, response)
Example #11
0
    def resend_verification(self, account_id: str, resource_id: int) -> Result:
        """Tell FreshBooks to resend the verification webhook for the callback

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to update

        Returns:
            Result: Result object with the resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        response = self._request(self._get_url(account_id, resource_id),
                                 HttpVerbs.PUT,
                                 data={self.single_name: {
                                     "resend": True
                                 }})
        return Result(self.single_name, response)
Example #12
0
    def verify(self, account_id: str, resource_id: int,
               verifier: str) -> Result:
        """Verify webhook callback by making a put request

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to update
            verifier: The string verifier received by the webhook callback URI

        Returns:
            Result: Result object with the resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        response = self._request(
            self._get_url(account_id, resource_id),
            HttpVerbs.PUT,
            data={self.single_name: {
                "verifier": verifier
            }})
        return Result(self.single_name, response)
Example #13
0
    def get(self,
            account_id: str,
            resource_id: int,
            includes: Optional[IncludesBuilder] = None) -> Result:
        """Get a single resource with the corresponding id.

        Args:
            account_id: The alpha-numeric account id
            resource_id: Id of the resource to return
            builders: (Optional) IncludesBuilder object for including additional data, sub-resources, etc.
        Returns:
            Result: Result object with the resource's response data.

        Raises:
            FreshBooksError: If the call is not successful.
        """
        self._reject_missing("get")
        resource_url = self._get_url(account_id, resource_id)
        query_string = ""
        if includes:
            query_string = self._build_query_string([includes])
        data = self._request(f"{resource_url}{query_string}", HttpVerbs.GET)
        return Result(self.single_name, data)
    def upload(self,
               account_id: str,
               file_stream: Optional[BufferedReader] = None,
               file_path: Optional[str] = None) -> Result:
        """Upload a file to FreshBooks' file storage. This returns a Result object with the JWT required to access the file,
        and in the case of an image, a link to the image itself.

        The file to upload can be either a byte stream, or a path to the file itself.

        Eg.

        ```python
        >>> uploaded = freshBooksClient.images.upload(account_id, file_path="/path/to/image.png")
        >>> uploaded = freshBooksClient.images.upload(account_id, file_stream=open("/path/to/image.png", "rb")

        >>> print(uploaded.jwt)
        <some jwt>

        >>> print(uploaded.link)
        https://my.freshbooks.com/service/uploads/images/<some jwt>
        ```

        Args:
            account_id: The alpha-numeric account id
            file_stream: (Optional) Byte stream of the file
            file_path: (Optional) Path to the file
        Returns:
            Result: Result object with the new resource's response data.
        Raises:
            FreshBooksError: If the call is not successful.
        """
        url = self._get_url(account_id=account_id)

        file_content = file_stream
        if file_path and not file_stream:  # pragma: no cover
            file_content = open(file_path, "rb")
        files = {'content': file_content}

        response = self._send_request(url, HttpVerbs.POST, files=files)

        status = response.status_code
        try:
            content = response.json()
        except ValueError:
            raise FreshBooksError(status,
                                  "Failed to parse response",
                                  raw_response=response.text)

        if status >= 400:
            raise FreshBooksError(status,
                                  content["error"],
                                  raw_response=response.text)

        if self.single_name not in content:  # pragma: no cover
            raise FreshBooksError(status,
                                  "Returned an unexpected response",
                                  raw_response=response.text)

        if content.get("link"):
            content[self.single_name]["link"] = content["link"]

        return Result(self.single_name, content)