projectal.entities.booking

  1from projectal.entity import Entity
  2from projectal.linkers import *
  3import projectal
  4
  5
  6class Booking(Entity, NoteLinker, FileLinker, StageLinker, TagLinker):
  7    """
  8    Implementation of the [Booking](https://projectal.com/docs/latest/#tag/Booking) API.
  9    """
 10
 11    _path = "booking"
 12    _name = "booking"
 13    _links = [NoteLinker, FileLinker, StageLinker, TagLinker]
 14
 15    @classmethod
 16    def get(cls, entities, links=None, deleted_at=None):
 17        """
 18        Get one or more entities of the same type. The entity
 19        type is determined by the subclass calling this method.
 20
 21        `entities`: One of several formats containing the `uuId`s
 22        of the entities you want to get (see bottom for examples):
 23
 24        - `str` or list of `str`
 25        - `dict` or list of `dict` (with `uuId` key)
 26
 27        `links`: A case-insensitive list of entity names to fetch with
 28        this entity. For performance reasons, links are only returned
 29        on demand.
 30
 31        Links follow a common naming convention in the output with
 32        a *_List* suffix. E.g.:
 33        `links=['company', 'location']` will appear as `companyList` and
 34        `locationList` in the response.
 35        ```
 36        # Example usage:
 37        # str
 38        projectal.Project.get('1b21e445-f29a-4a9f-95ff-fe253a3e1b11')
 39
 40        # list of str
 41        ids = ['1b21e445-f29a...', '1b21e445-f29a...', '1b21e445-f29a...']
 42        projectal.Project.get(ids)
 43
 44        # dict
 45        project = project.Project.create({'name': 'MyProject'})
 46        # project = {'uuId': '1b21e445-f29a...', 'name': 'MyProject', ...}
 47        projectal.Project.get(project)
 48
 49        # list of dicts (e.g. from a query)
 50        # projects = [{'uuId': '1b21e445-f29a...'}, {'uuId': '1b21e445-f29a...'}, ...]
 51        project.Project.get(projects)
 52
 53        # str with links
 54        projectal.Project.get('1b21e445-f29a...', 'links=['company', 'location']')
 55        ```
 56
 57        `deleted_at`: Include this parameter to get a deleted entity.
 58        This value should be a UTC timestamp from a webhook delete event.
 59        """
 60        link_set = cls._get_linkset(links)
 61
 62        if isinstance(entities, str):
 63            # String input is a uuId
 64            payload = [{"uuId": entities}]
 65        elif isinstance(entities, dict):
 66            # Dict input needs to be a list
 67            payload = [entities]
 68        elif isinstance(entities, list):
 69            # List input can be a list of uuIds or list of dicts
 70            # If uuIds (strings), convert to list of dicts
 71            if len(entities) > 0 and isinstance(entities[0], str):
 72                payload = [{"uuId": uuId} for uuId in entities]
 73            else:
 74                # Already expected format
 75                payload = entities
 76        else:
 77            # We have a list of dicts already, the expected format
 78            payload = entities
 79
 80        if deleted_at:
 81            if not isinstance(deleted_at, int):
 82                raise projectal.UsageException("deleted_at must be a number")
 83
 84        url = "/api/{}/get".format(cls._path)
 85        params = []
 86        # project and staff links need to be included by default for methods that use get
 87        # they can't be included in the typical way since they aren't compatible with linking methods
 88        params.append(
 89            "links=PROJECT,STAFF,RESOURCE{}".format(
 90                "," + ",".join(links) if links else ""
 91            )
 92        )
 93        params.append("epoch={}".format(deleted_at - 1)) if deleted_at else None
 94        if len(params) > 0:
 95            url += "?" + "&".join(params)
 96
 97        # We only need to send over the uuIds
 98        payload = [{"uuId": e["uuId"]} for e in payload]
 99        if not payload:
100            return []
101        objects = []
102        for i in range(0, len(payload), projectal.chunk_size_read):
103            chunk = payload[i : i + projectal.chunk_size_read]
104            dicts = api.post(url, chunk)
105            for d in dicts:
106                obj = cls(d)
107                obj._with_links.update(link_set)
108                obj._is_new = False
109                # Create default fields for links we ask for. Workaround for backend
110                # sometimes omitting links if no links exist.
111                for link_name in link_set:
112                    link_def = obj._link_def_by_name[link_name]
113                    if link_def["link_key"] not in obj:
114                        if link_def["type"] == dict:
115                            obj.set_readonly(link_def["link_key"], None)
116                        else:
117                            obj.set_readonly(link_def["link_key"], link_def["type"]())
118                objects.append(obj)
119
120        if not isinstance(entities, list):
121            return objects[0]
122        return objects
  7class Booking(Entity, NoteLinker, FileLinker, StageLinker, TagLinker):
  8    """
  9    Implementation of the [Booking](https://projectal.com/docs/latest/#tag/Booking) API.
 10    """
 11
 12    _path = "booking"
 13    _name = "booking"
 14    _links = [NoteLinker, FileLinker, StageLinker, TagLinker]
 15
 16    @classmethod
 17    def get(cls, entities, links=None, deleted_at=None):
 18        """
 19        Get one or more entities of the same type. The entity
 20        type is determined by the subclass calling this method.
 21
 22        `entities`: One of several formats containing the `uuId`s
 23        of the entities you want to get (see bottom for examples):
 24
 25        - `str` or list of `str`
 26        - `dict` or list of `dict` (with `uuId` key)
 27
 28        `links`: A case-insensitive list of entity names to fetch with
 29        this entity. For performance reasons, links are only returned
 30        on demand.
 31
 32        Links follow a common naming convention in the output with
 33        a *_List* suffix. E.g.:
 34        `links=['company', 'location']` will appear as `companyList` and
 35        `locationList` in the response.
 36        ```
 37        # Example usage:
 38        # str
 39        projectal.Project.get('1b21e445-f29a-4a9f-95ff-fe253a3e1b11')
 40
 41        # list of str
 42        ids = ['1b21e445-f29a...', '1b21e445-f29a...', '1b21e445-f29a...']
 43        projectal.Project.get(ids)
 44
 45        # dict
 46        project = project.Project.create({'name': 'MyProject'})
 47        # project = {'uuId': '1b21e445-f29a...', 'name': 'MyProject', ...}
 48        projectal.Project.get(project)
 49
 50        # list of dicts (e.g. from a query)
 51        # projects = [{'uuId': '1b21e445-f29a...'}, {'uuId': '1b21e445-f29a...'}, ...]
 52        project.Project.get(projects)
 53
 54        # str with links
 55        projectal.Project.get('1b21e445-f29a...', 'links=['company', 'location']')
 56        ```
 57
 58        `deleted_at`: Include this parameter to get a deleted entity.
 59        This value should be a UTC timestamp from a webhook delete event.
 60        """
 61        link_set = cls._get_linkset(links)
 62
 63        if isinstance(entities, str):
 64            # String input is a uuId
 65            payload = [{"uuId": entities}]
 66        elif isinstance(entities, dict):
 67            # Dict input needs to be a list
 68            payload = [entities]
 69        elif isinstance(entities, list):
 70            # List input can be a list of uuIds or list of dicts
 71            # If uuIds (strings), convert to list of dicts
 72            if len(entities) > 0 and isinstance(entities[0], str):
 73                payload = [{"uuId": uuId} for uuId in entities]
 74            else:
 75                # Already expected format
 76                payload = entities
 77        else:
 78            # We have a list of dicts already, the expected format
 79            payload = entities
 80
 81        if deleted_at:
 82            if not isinstance(deleted_at, int):
 83                raise projectal.UsageException("deleted_at must be a number")
 84
 85        url = "/api/{}/get".format(cls._path)
 86        params = []
 87        # project and staff links need to be included by default for methods that use get
 88        # they can't be included in the typical way since they aren't compatible with linking methods
 89        params.append(
 90            "links=PROJECT,STAFF,RESOURCE{}".format(
 91                "," + ",".join(links) if links else ""
 92            )
 93        )
 94        params.append("epoch={}".format(deleted_at - 1)) if deleted_at else None
 95        if len(params) > 0:
 96            url += "?" + "&".join(params)
 97
 98        # We only need to send over the uuIds
 99        payload = [{"uuId": e["uuId"]} for e in payload]
100        if not payload:
101            return []
102        objects = []
103        for i in range(0, len(payload), projectal.chunk_size_read):
104            chunk = payload[i : i + projectal.chunk_size_read]
105            dicts = api.post(url, chunk)
106            for d in dicts:
107                obj = cls(d)
108                obj._with_links.update(link_set)
109                obj._is_new = False
110                # Create default fields for links we ask for. Workaround for backend
111                # sometimes omitting links if no links exist.
112                for link_name in link_set:
113                    link_def = obj._link_def_by_name[link_name]
114                    if link_def["link_key"] not in obj:
115                        if link_def["type"] == dict:
116                            obj.set_readonly(link_def["link_key"], None)
117                        else:
118                            obj.set_readonly(link_def["link_key"], link_def["type"]())
119                objects.append(obj)
120
121        if not isinstance(entities, list):
122            return objects[0]
123        return objects

Implementation of the Booking API.

@classmethod
def get(cls, entities, links=None, deleted_at=None):
 16    @classmethod
 17    def get(cls, entities, links=None, deleted_at=None):
 18        """
 19        Get one or more entities of the same type. The entity
 20        type is determined by the subclass calling this method.
 21
 22        `entities`: One of several formats containing the `uuId`s
 23        of the entities you want to get (see bottom for examples):
 24
 25        - `str` or list of `str`
 26        - `dict` or list of `dict` (with `uuId` key)
 27
 28        `links`: A case-insensitive list of entity names to fetch with
 29        this entity. For performance reasons, links are only returned
 30        on demand.
 31
 32        Links follow a common naming convention in the output with
 33        a *_List* suffix. E.g.:
 34        `links=['company', 'location']` will appear as `companyList` and
 35        `locationList` in the response.
 36        ```
 37        # Example usage:
 38        # str
 39        projectal.Project.get('1b21e445-f29a-4a9f-95ff-fe253a3e1b11')
 40
 41        # list of str
 42        ids = ['1b21e445-f29a...', '1b21e445-f29a...', '1b21e445-f29a...']
 43        projectal.Project.get(ids)
 44
 45        # dict
 46        project = project.Project.create({'name': 'MyProject'})
 47        # project = {'uuId': '1b21e445-f29a...', 'name': 'MyProject', ...}
 48        projectal.Project.get(project)
 49
 50        # list of dicts (e.g. from a query)
 51        # projects = [{'uuId': '1b21e445-f29a...'}, {'uuId': '1b21e445-f29a...'}, ...]
 52        project.Project.get(projects)
 53
 54        # str with links
 55        projectal.Project.get('1b21e445-f29a...', 'links=['company', 'location']')
 56        ```
 57
 58        `deleted_at`: Include this parameter to get a deleted entity.
 59        This value should be a UTC timestamp from a webhook delete event.
 60        """
 61        link_set = cls._get_linkset(links)
 62
 63        if isinstance(entities, str):
 64            # String input is a uuId
 65            payload = [{"uuId": entities}]
 66        elif isinstance(entities, dict):
 67            # Dict input needs to be a list
 68            payload = [entities]
 69        elif isinstance(entities, list):
 70            # List input can be a list of uuIds or list of dicts
 71            # If uuIds (strings), convert to list of dicts
 72            if len(entities) > 0 and isinstance(entities[0], str):
 73                payload = [{"uuId": uuId} for uuId in entities]
 74            else:
 75                # Already expected format
 76                payload = entities
 77        else:
 78            # We have a list of dicts already, the expected format
 79            payload = entities
 80
 81        if deleted_at:
 82            if not isinstance(deleted_at, int):
 83                raise projectal.UsageException("deleted_at must be a number")
 84
 85        url = "/api/{}/get".format(cls._path)
 86        params = []
 87        # project and staff links need to be included by default for methods that use get
 88        # they can't be included in the typical way since they aren't compatible with linking methods
 89        params.append(
 90            "links=PROJECT,STAFF,RESOURCE{}".format(
 91                "," + ",".join(links) if links else ""
 92            )
 93        )
 94        params.append("epoch={}".format(deleted_at - 1)) if deleted_at else None
 95        if len(params) > 0:
 96            url += "?" + "&".join(params)
 97
 98        # We only need to send over the uuIds
 99        payload = [{"uuId": e["uuId"]} for e in payload]
100        if not payload:
101            return []
102        objects = []
103        for i in range(0, len(payload), projectal.chunk_size_read):
104            chunk = payload[i : i + projectal.chunk_size_read]
105            dicts = api.post(url, chunk)
106            for d in dicts:
107                obj = cls(d)
108                obj._with_links.update(link_set)
109                obj._is_new = False
110                # Create default fields for links we ask for. Workaround for backend
111                # sometimes omitting links if no links exist.
112                for link_name in link_set:
113                    link_def = obj._link_def_by_name[link_name]
114                    if link_def["link_key"] not in obj:
115                        if link_def["type"] == dict:
116                            obj.set_readonly(link_def["link_key"], None)
117                        else:
118                            obj.set_readonly(link_def["link_key"], link_def["type"]())
119                objects.append(obj)
120
121        if not isinstance(entities, list):
122            return objects[0]
123        return objects

Get one or more entities of the same type. The entity type is determined by the subclass calling this method.

entities: One of several formats containing the uuIds of the entities you want to get (see bottom for examples):

  • str or list of str
  • dict or list of dict (with uuId key)

links: A case-insensitive list of entity names to fetch with this entity. For performance reasons, links are only returned on demand.

Links follow a common naming convention in the output with a _List suffix. E.g.: links=['company', 'location'] will appear as companyList and locationList in the response.

# Example usage:
# str
projectal.Project.get('1b21e445-f29a-4a9f-95ff-fe253a3e1b11')

# list of str
ids = ['1b21e445-f29a...', '1b21e445-f29a...', '1b21e445-f29a...']
projectal.Project.get(ids)

# dict
project = project.Project.create({'name': 'MyProject'})
# project = {'uuId': '1b21e445-f29a...', 'name': 'MyProject', ...}
projectal.Project.get(project)

# list of dicts (e.g. from a query)
# projects = [{'uuId': '1b21e445-f29a...'}, {'uuId': '1b21e445-f29a...'}, ...]
project.Project.get(projects)

# str with links
projectal.Project.get('1b21e445-f29a...', 'links=['company', 'location']')

deleted_at: Include this parameter to get a deleted entity. This value should be a UTC timestamp from a webhook delete event.