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

Implementation of the Booking API.

@classmethod
def get(cls, entities, links=None, deleted_at=None):
 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('links=PROJECT,STAFF,RESOURCE{}'.format(',' + ','.join(links) if links else ''))
 89        params.append('epoch={}'.format(deleted_at - 1)) if deleted_at else None
 90        if len(params) > 0:
 91            url += '?' + '&'.join(params)
 92
 93        # We only need to send over the uuIds
 94        payload = [{'uuId': e['uuId']} for e in payload]
 95        if not payload:
 96            return []
 97        objects = []
 98        for i in range(0, len(payload), projectal.chunk_size_read):
 99            chunk = payload[i:i + projectal.chunk_size_read]
100            dicts = api.post(url, chunk)
101            for d in dicts:
102                obj = cls(d)
103                obj._with_links.update(link_set)
104                obj._is_new = False
105                # Create default fields for links we ask for. Workaround for backend
106                # sometimes omitting links if no links exist.
107                for link_name in link_set:
108                    link_def = obj._link_def_by_name[link_name]
109                    if link_def['link_key'] not in obj:
110                        if link_def['type'] == dict:
111                            obj.set_readonly(link_def['link_key'], None)
112                        else:
113                            obj.set_readonly(link_def['link_key'], link_def['type']())
114                objects.append(obj)
115
116        if not isinstance(entities, list):
117            return objects[0]
118        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.