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}"
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)
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)
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)
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)
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)
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)
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)
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)
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)