projectal.entities.staff API documentation

# projectal.entities.staff

View Source

      1from datetime import datetime
      2
      3import projectal
      4from projectal.entity import Entity
      5from projectal.linkers import *
      6from projectal.errors import UsageException
      7from projectal.enums import DateLimit
      8
      9
     10class Staff(
     11    Entity,
     12    LocationLinker,
     13    ResourceLinker,
     14    SkillLinker,
     15    FileLinker,
     16    CompanyLinker,
     17    DepartmentLinker,
     18    TaskLinker,
     19    TaskTemplateLinker,
     20    NoteLinker,
     21    CalendarLinker,
     22    TagLinker,
     23    ContractLinker,
     24):
     25    """
     26    Implementation of the [Staff](https://projectal.com/docs/latest/#tag/Staff) API.
     27    """
     28
     29    _path = "staff"
     30    _name = "staff"
     31    _links = [
     32        LocationLinker,
     33        ResourceLinker,
     34        SkillLinker,
     35        FileLinker,
     36        NoteLinker,
     37        CalendarLinker,
     38        TagLinker,
     39        ContractLinker,
     40    ]
     41    _links_reverse = [CompanyLinker, DepartmentLinker, TaskLinker, TaskTemplateLinker]
     42
     43    @classmethod
     44    def calendar(cls, uuId, begin=None, until=None):
     45        """
     46        Returns the calendar of the staff with `uuId`.
     47
     48        `begin`: Start date in `yyyy-MM-dd`.
     49
     50        `until`: End date in `yyyy-MM-dd`.
     51
     52
     53        Optionally specify a date range. If no range specified, the
     54        minimum and maximum dates are used (see projectal.enums.DateLimit).
     55        """
     56        if begin:
     57            begin = datetime.strptime(begin, "%Y-%m-%d").date()
     58        if until:
     59            until = datetime.strptime(until, "%Y-%m-%d").date()
     60
     61        url = "/api/staff/{}/calendar?".format(uuId)
     62        params = []
     63        params.append("begin={}".format(begin)) if begin else None
     64        params.append("until={}".format(until)) if until else None
     65        url += "&".join(params)
     66
     67        cals = api.get(url)
     68        cals = [projectal.Calendar(c) for c in cals]
     69        return cals
     70
     71    @classmethod
     72    def calendar_availability(cls, uuId, begin=None, until=None):
     73        """
     74        Returns the availability (in hours) of the staff in `uuId`
     75        for each day within the specified date range.
     76
     77        `begin`: Start date in `yyyy-MM-dd`.
     78
     79        `until`: End date in `yyyy-MM-dd`.
     80
     81        If no range specified, the minimum and maximum dates are
     82        used (see projectal.enums.DateLimit).
     83        """
     84        if begin:
     85            begin = datetime.strptime(begin, "%Y-%m-%d").date()
     86        if until:
     87            until = datetime.strptime(until, "%Y-%m-%d").date()
     88
     89        url = "/api/staff/{}/calendar/availability?".format(uuId)
     90        params = []
     91        params.append("begin={}".format(begin)) if begin else None
     92        params.append("until={}".format(until)) if until else None
     93        url += "&".join(params)
     94
     95        return api.get(url)
     96
     97    @classmethod
     98    def usage(
     99        cls,
    100        begin,
    101        until,
    102        holder=None,
    103        start=None,
    104        limit=None,
    105        span=None,
    106        ksort=None,
    107        order=None,
    108        staff=None,
    109    ):
    110        """
    111        Returns the staff-to-task allocations for all staff within the `holder`.
    112
    113        See [Usage API](https://projectal.com/docs/latest/#tag/Staff/paths/~1api~1staff~1usage/post)
    114        for full details.
    115        """
    116        url = "/api/staff/usage?begin={}&until={}".format(begin, until)
    117        params = []
    118        params.append("holder={}".format(holder)) if holder else None
    119        params.append("start={}".format(start)) if start else None
    120        params.append("limit={}".format(limit)) if limit else None
    121        params.append("span={}".format(span)) if span else None
    122        params.append("ksort={}".format(ksort)) if ksort else None
    123        params.append("order={}".format(order)) if order else None
    124        if len(params) > 0:
    125            url += "&" + "&".join(params)
    126        payload = staff if staff and not holder else None
    127        response = api.post(url, payload)
    128        # Do some extra checks for empty list case
    129        if "status" in response:
    130            # We didn't have a 'jobCase' key and returned the outer dict.
    131            return []
    132        return response
    133
    134    @classmethod
    135    def auto_assign(
    136        cls,
    137        type="Recommend",
    138        over_allocate_staff=False,
    139        include_assigned_task=False,
    140        include_started_task=False,
    141        skills=None,
    142        tasks=None,
    143        staffs=None,
    144    ):
    145        """
    146        Automatically assign a set of staff (real or generic) to a set of tasks
    147        using various skill and allocation criteria.
    148
    149        See [Staff Assign API](https://projectal.com/docs/latest/#tag/Staff-Assign/paths/~1api~1allocation~1staff/post)
    150        for full details.
    151        """
    152        url = "/api/allocation/staff"
    153        payload = {
    154            "type": type,
    155            "overAllocateStaff": over_allocate_staff,
    156            "includeAssignedTask": include_assigned_task,
    157            "includeStartedTask": include_started_task,
    158            "skillMatchList": skills if skills else [],
    159            "staffList": staffs if staffs else [],
    160            "taskList": tasks if tasks else [],
    161        }
    162        return api.post(url, payload)
    163
    164    @classmethod
    165    def create_contract(
    166        cls,
    167        UUID,
    168        payload={},
    169        end_current_contract=False,
    170        start_new_contract=False,
    171    ):
    172        """
    173        Creates a new Contract for a staff, with updated fields from the payload
    174
    175        end_current: Sets the end date of the current contract to today's date
    176        start_new_date: Sets the start date of the new contract to today's date
    177
    178        See [Staff Clone API](https://projectal.com/docs/latest#tag/Staff/paths/~1api~1staff~1clone/post)
    179        for full details.
    180        """
    181
    182        url = "/api/staff/clone?reference={}&as_contract=true".format(UUID)
    183        date_today = datetime.today().strftime("%Y-%m-%d")
    184
    185        current_staff = None
    186        if end_current_contract:
    187            # Check if setting end date to today is
    188            # invalid for current Staff Contract
    189            current_staff = cls.get(UUID)
    190            if projectal.timestamp_from_date(
    191                current_staff.get("startDate")
    192            ) > projectal.timestamp_from_date(date_today):
    193                raise UsageException(
    194                    f"Cannot set endDate before startDate for current contract: {date_today}"
    195                )
    196
    197        if start_new_contract:
    198            payload["startDate"] = date_today
    199            payload["endDate"] = DateLimit.Max
    200
    201        response = api.post(url, payload)
    202
    203        if end_current_contract and current_staff:
    204            current_staff["endDate"] = date_today
    205            current_staff.save()
    206
    207        return response["jobClue"]["uuId"]

class Staff(projectal.entity.Entity, projectal.linkers.LocationLinker, projectal.linkers.ResourceLinker, projectal.linkers.SkillLinker, projectal.linkers.FileLinker, projectal.linkers.CompanyLinker, projectal.linkers.DepartmentLinker, projectal.linkers.TaskLinker, projectal.linkers.TaskTemplateLinker, projectal.linkers.NoteLinker, projectal.linkers.CalendarLinker, projectal.linkers.TagLinker, projectal.linkers.ContractLinker): View Source

     11class Staff(
     12    Entity,
     13    LocationLinker,
     14    ResourceLinker,
     15    SkillLinker,
     16    FileLinker,
     17    CompanyLinker,
     18    DepartmentLinker,
     19    TaskLinker,
     20    TaskTemplateLinker,
     21    NoteLinker,
     22    CalendarLinker,
     23    TagLinker,
     24    ContractLinker,
     25):
     26    """
     27    Implementation of the [Staff](https://projectal.com/docs/latest/#tag/Staff) API.
     28    """
     29
     30    _path = "staff"
     31    _name = "staff"
     32    _links = [
     33        LocationLinker,
     34        ResourceLinker,
     35        SkillLinker,
     36        FileLinker,
     37        NoteLinker,
     38        CalendarLinker,
     39        TagLinker,
     40        ContractLinker,
     41    ]
     42    _links_reverse = [CompanyLinker, DepartmentLinker, TaskLinker, TaskTemplateLinker]
     43
     44    @classmethod
     45    def calendar(cls, uuId, begin=None, until=None):
     46        """
     47        Returns the calendar of the staff with `uuId`.
     48
     49        `begin`: Start date in `yyyy-MM-dd`.
     50
     51        `until`: End date in `yyyy-MM-dd`.
     52
     53
     54        Optionally specify a date range. If no range specified, the
     55        minimum and maximum dates are used (see projectal.enums.DateLimit).
     56        """
     57        if begin:
     58            begin = datetime.strptime(begin, "%Y-%m-%d").date()
     59        if until:
     60            until = datetime.strptime(until, "%Y-%m-%d").date()
     61
     62        url = "/api/staff/{}/calendar?".format(uuId)
     63        params = []
     64        params.append("begin={}".format(begin)) if begin else None
     65        params.append("until={}".format(until)) if until else None
     66        url += "&".join(params)
     67
     68        cals = api.get(url)
     69        cals = [projectal.Calendar(c) for c in cals]
     70        return cals
     71
     72    @classmethod
     73    def calendar_availability(cls, uuId, begin=None, until=None):
     74        """
     75        Returns the availability (in hours) of the staff in `uuId`
     76        for each day within the specified date range.
     77
     78        `begin`: Start date in `yyyy-MM-dd`.
     79
     80        `until`: End date in `yyyy-MM-dd`.
     81
     82        If no range specified, the minimum and maximum dates are
     83        used (see projectal.enums.DateLimit).
     84        """
     85        if begin:
     86            begin = datetime.strptime(begin, "%Y-%m-%d").date()
     87        if until:
     88            until = datetime.strptime(until, "%Y-%m-%d").date()
     89
     90        url = "/api/staff/{}/calendar/availability?".format(uuId)
     91        params = []
     92        params.append("begin={}".format(begin)) if begin else None
     93        params.append("until={}".format(until)) if until else None
     94        url += "&".join(params)
     95
     96        return api.get(url)
     97
     98    @classmethod
     99    def usage(
    100        cls,
    101        begin,
    102        until,
    103        holder=None,
    104        start=None,
    105        limit=None,
    106        span=None,
    107        ksort=None,
    108        order=None,
    109        staff=None,
    110    ):
    111        """
    112        Returns the staff-to-task allocations for all staff within the `holder`.
    113
    114        See [Usage API](https://projectal.com/docs/latest/#tag/Staff/paths/~1api~1staff~1usage/post)
    115        for full details.
    116        """
    117        url = "/api/staff/usage?begin={}&until={}".format(begin, until)
    118        params = []
    119        params.append("holder={}".format(holder)) if holder else None
    120        params.append("start={}".format(start)) if start else None
    121        params.append("limit={}".format(limit)) if limit else None
    122        params.append("span={}".format(span)) if span else None
    123        params.append("ksort={}".format(ksort)) if ksort else None
    124        params.append("order={}".format(order)) if order else None
    125        if len(params) > 0:
    126            url += "&" + "&".join(params)
    127        payload = staff if staff and not holder else None
    128        response = api.post(url, payload)
    129        # Do some extra checks for empty list case
    130        if "status" in response:
    131            # We didn't have a 'jobCase' key and returned the outer dict.
    132            return []
    133        return response
    134
    135    @classmethod
    136    def auto_assign(
    137        cls,
    138        type="Recommend",
    139        over_allocate_staff=False,
    140        include_assigned_task=False,
    141        include_started_task=False,
    142        skills=None,
    143        tasks=None,
    144        staffs=None,
    145    ):
    146        """
    147        Automatically assign a set of staff (real or generic) to a set of tasks
    148        using various skill and allocation criteria.
    149
    150        See [Staff Assign API](https://projectal.com/docs/latest/#tag/Staff-Assign/paths/~1api~1allocation~1staff/post)
    151        for full details.
    152        """
    153        url = "/api/allocation/staff"
    154        payload = {
    155            "type": type,
    156            "overAllocateStaff": over_allocate_staff,
    157            "includeAssignedTask": include_assigned_task,
    158            "includeStartedTask": include_started_task,
    159            "skillMatchList": skills if skills else [],
    160            "staffList": staffs if staffs else [],
    161            "taskList": tasks if tasks else [],
    162        }
    163        return api.post(url, payload)
    164
    165    @classmethod
    166    def create_contract(
    167        cls,
    168        UUID,
    169        payload={},
    170        end_current_contract=False,
    171        start_new_contract=False,
    172    ):
    173        """
    174        Creates a new Contract for a staff, with updated fields from the payload
    175
    176        end_current: Sets the end date of the current contract to today's date
    177        start_new_date: Sets the start date of the new contract to today's date
    178
    179        See [Staff Clone API](https://projectal.com/docs/latest#tag/Staff/paths/~1api~1staff~1clone/post)
    180        for full details.
    181        """
    182
    183        url = "/api/staff/clone?reference={}&as_contract=true".format(UUID)
    184        date_today = datetime.today().strftime("%Y-%m-%d")
    185
    186        current_staff = None
    187        if end_current_contract:
    188            # Check if setting end date to today is
    189            # invalid for current Staff Contract
    190            current_staff = cls.get(UUID)
    191            if projectal.timestamp_from_date(
    192                current_staff.get("startDate")
    193            ) > projectal.timestamp_from_date(date_today):
    194                raise UsageException(
    195                    f"Cannot set endDate before startDate for current contract: {date_today}"
    196                )
    197
    198        if start_new_contract:
    199            payload["startDate"] = date_today
    200            payload["endDate"] = DateLimit.Max
    201
    202        response = api.post(url, payload)
    203
    204        if end_current_contract and current_staff:
    205            current_staff["endDate"] = date_today
    206            current_staff.save()
    207
    208        return response["jobClue"]["uuId"]

Implementation of the Staff API.

@classmethod
def calendar(cls, uuId, begin=None, until=None): View Source

    44    @classmethod
    45    def calendar(cls, uuId, begin=None, until=None):
    46        """
    47        Returns the calendar of the staff with `uuId`.
    48
    49        `begin`: Start date in `yyyy-MM-dd`.
    50
    51        `until`: End date in `yyyy-MM-dd`.
    52
    53
    54        Optionally specify a date range. If no range specified, the
    55        minimum and maximum dates are used (see projectal.enums.DateLimit).
    56        """
    57        if begin:
    58            begin = datetime.strptime(begin, "%Y-%m-%d").date()
    59        if until:
    60            until = datetime.strptime(until, "%Y-%m-%d").date()
    61
    62        url = "/api/staff/{}/calendar?".format(uuId)
    63        params = []
    64        params.append("begin={}".format(begin)) if begin else None
    65        params.append("until={}".format(until)) if until else None
    66        url += "&".join(params)
    67
    68        cals = api.get(url)
    69        cals = [projectal.Calendar(c) for c in cals]
    70        return cals

Returns the calendar of the staff with `uuId`.

`begin`: Start date in `yyyy-MM-dd`.

`until`: End date in `yyyy-MM-dd`.

Optionally specify a date range. If no range specified, the minimum and maximum dates are used (see projectal.enums.DateLimit).

@classmethod
def calendar_availability(cls, uuId, begin=None, until=None): View Source

    72    @classmethod
    73    def calendar_availability(cls, uuId, begin=None, until=None):
    74        """
    75        Returns the availability (in hours) of the staff in `uuId`
    76        for each day within the specified date range.
    77
    78        `begin`: Start date in `yyyy-MM-dd`.
    79
    80        `until`: End date in `yyyy-MM-dd`.
    81
    82        If no range specified, the minimum and maximum dates are
    83        used (see projectal.enums.DateLimit).
    84        """
    85        if begin:
    86            begin = datetime.strptime(begin, "%Y-%m-%d").date()
    87        if until:
    88            until = datetime.strptime(until, "%Y-%m-%d").date()
    89
    90        url = "/api/staff/{}/calendar/availability?".format(uuId)
    91        params = []
    92        params.append("begin={}".format(begin)) if begin else None
    93        params.append("until={}".format(until)) if until else None
    94        url += "&".join(params)
    95
    96        return api.get(url)

Returns the availability (in hours) of the staff in `uuId` for each day within the specified date range.

`begin`: Start date in `yyyy-MM-dd`.

`until`: End date in `yyyy-MM-dd`.

If no range specified, the minimum and maximum dates are used (see projectal.enums.DateLimit).

@classmethod
def usage( cls, begin, until, holder=None, start=None, limit=None, span=None, ksort=None, order=None, staff=None): View Source

     98    @classmethod
     99    def usage(
    100        cls,
    101        begin,
    102        until,
    103        holder=None,
    104        start=None,
    105        limit=None,
    106        span=None,
    107        ksort=None,
    108        order=None,
    109        staff=None,
    110    ):
    111        """
    112        Returns the staff-to-task allocations for all staff within the `holder`.
    113
    114        See [Usage API](https://projectal.com/docs/latest/#tag/Staff/paths/~1api~1staff~1usage/post)
    115        for full details.
    116        """
    117        url = "/api/staff/usage?begin={}&until={}".format(begin, until)
    118        params = []
    119        params.append("holder={}".format(holder)) if holder else None
    120        params.append("start={}".format(start)) if start else None
    121        params.append("limit={}".format(limit)) if limit else None
    122        params.append("span={}".format(span)) if span else None
    123        params.append("ksort={}".format(ksort)) if ksort else None
    124        params.append("order={}".format(order)) if order else None
    125        if len(params) > 0:
    126            url += "&" + "&".join(params)
    127        payload = staff if staff and not holder else None
    128        response = api.post(url, payload)
    129        # Do some extra checks for empty list case
    130        if "status" in response:
    131            # We didn't have a 'jobCase' key and returned the outer dict.
    132            return []
    133        return response

Returns the staff-to-task allocations for all staff within the `holder`.

See Usage API for full details.

@classmethod
def auto_assign( cls, type='Recommend', over_allocate_staff=False, include_assigned_task=False, include_started_task=False, skills=None, tasks=None, staffs=None): View Source

    135    @classmethod
    136    def auto_assign(
    137        cls,
    138        type="Recommend",
    139        over_allocate_staff=False,
    140        include_assigned_task=False,
    141        include_started_task=False,
    142        skills=None,
    143        tasks=None,
    144        staffs=None,
    145    ):
    146        """
    147        Automatically assign a set of staff (real or generic) to a set of tasks
    148        using various skill and allocation criteria.
    149
    150        See [Staff Assign API](https://projectal.com/docs/latest/#tag/Staff-Assign/paths/~1api~1allocation~1staff/post)
    151        for full details.
    152        """
    153        url = "/api/allocation/staff"
    154        payload = {
    155            "type": type,
    156            "overAllocateStaff": over_allocate_staff,
    157            "includeAssignedTask": include_assigned_task,
    158            "includeStartedTask": include_started_task,
    159            "skillMatchList": skills if skills else [],
    160            "staffList": staffs if staffs else [],
    161            "taskList": tasks if tasks else [],
    162        }
    163        return api.post(url, payload)

Automatically assign a set of staff (real or generic) to a set of tasks using various skill and allocation criteria.

See Staff Assign API for full details.

@classmethod
def create_contract( cls, UUID, payload={}, end_current_contract=False, start_new_contract=False): View Source

    165    @classmethod
    166    def create_contract(
    167        cls,
    168        UUID,
    169        payload={},
    170        end_current_contract=False,
    171        start_new_contract=False,
    172    ):
    173        """
    174        Creates a new Contract for a staff, with updated fields from the payload
    175
    176        end_current: Sets the end date of the current contract to today's date
    177        start_new_date: Sets the start date of the new contract to today's date
    178
    179        See [Staff Clone API](https://projectal.com/docs/latest#tag/Staff/paths/~1api~1staff~1clone/post)
    180        for full details.
    181        """
    182
    183        url = "/api/staff/clone?reference={}&as_contract=true".format(UUID)
    184        date_today = datetime.today().strftime("%Y-%m-%d")
    185
    186        current_staff = None
    187        if end_current_contract:
    188            # Check if setting end date to today is
    189            # invalid for current Staff Contract
    190            current_staff = cls.get(UUID)
    191            if projectal.timestamp_from_date(
    192                current_staff.get("startDate")
    193            ) > projectal.timestamp_from_date(date_today):
    194                raise UsageException(
    195                    f"Cannot set endDate before startDate for current contract: {date_today}"
    196                )
    197
    198        if start_new_contract:
    199            payload["startDate"] = date_today
    200            payload["endDate"] = DateLimit.Max
    201
    202        response = api.post(url, payload)
    203
    204        if end_current_contract and current_staff:
    205            current_staff["endDate"] = date_today
    206            current_staff.save()
    207
    208        return response["jobClue"]["uuId"]

Creates a new Contract for a staff, with updated fields from the payload

end_current: Sets the end date of the current contract to today's date start_new_date: Sets the start date of the new contract to today's date

See Staff Clone API for full details.

##### Inherited Members

projectal.entity.Entity
  get
  update
  delete
  history
  create
  save
  clone
  list
  match
  match_startswith
  match_endswith
  match_one
  match_startswith_one
  match_endswith_one
  search
  query
  profile_get
  profile_set
  changes
  set_readonly
  get_link_definitions
  entity_name
projectal.linkers.LocationLinker
  link_location
  unlink_location
projectal.linkers.ResourceLinker
  link_resource
  relink_resource
  unlink_resource
projectal.linkers.SkillLinker
  link_skill
  relink_skill
  unlink_skill
projectal.linkers.FileLinker
  link_file
  unlink_file
projectal.linkers.CompanyLinker
  link_company
  unlink_company
projectal.linkers.DepartmentLinker
  link_department
  unlink_department
projectal.linkers.TaskLinker
  link_task
  unlink_task
projectal.linkers.TaskTemplateLinker
  link_task_template
  unlink_task_template
projectal.linkers.TagLinker
  link_tag
  unlink_tag