170 lines
4.2 KiB
Python
170 lines
4.2 KiB
Python
"""Favro Data Model.
|
|
|
|
Based on the descriptions on the [Favro API Specification
|
|
Page](https://favro.com/developer/), and observed behaviour.
|
|
"""
|
|
|
|
import dataclasses
|
|
import datetime
|
|
from typing import Any
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class SeqId:
|
|
raw_id: int
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CardId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CommonId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class UserId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class OrganizationId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CardAssignment:
|
|
user: UserId
|
|
completed: bool
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'CardAssignment':
|
|
return CardAssignment(
|
|
UserId(json['userId']),
|
|
json['completed'],
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class UserInfo:
|
|
user_id: UserId
|
|
name: str
|
|
email: str
|
|
organization_role: str
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'UserInfo':
|
|
return UserInfo(
|
|
UserId(json['userId']),
|
|
json['name'],
|
|
json['email'],
|
|
json['organizationRole'],
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class TagId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CustomFieldId:
|
|
raw_id: str
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class TagInfo:
|
|
tag_id: TagId
|
|
organization_id: OrganizationId
|
|
name: str
|
|
color: str | None
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'TagInfo':
|
|
return TagInfo(
|
|
TagId(json['tagId']),
|
|
OrganizationId(json['organizationId']),
|
|
json['name'],
|
|
json.get('color'),
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CustomField:
|
|
custom_field_id: CustomFieldId
|
|
value: list[str] # TODO
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'CustomField':
|
|
return CustomField(
|
|
CustomFieldId(json['customFieldId']),
|
|
json['value'], # TODO
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class CardDependency:
|
|
card_id: CardId
|
|
card_common_id: CommonId
|
|
is_before: bool
|
|
reverse_card_id: CardId
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'CardDependency':
|
|
return CardDependency(
|
|
CardId(json['cardId']),
|
|
CommonId(json['cardCommonId']),
|
|
json['isBefore'],
|
|
CardId(json['reverseCardId']),
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class Card:
|
|
card_id: CardId
|
|
seq_id: SeqId
|
|
common_id: CommonId
|
|
organization_id: OrganizationId
|
|
is_archived: bool
|
|
name: str
|
|
dependencies: list[CardDependency]
|
|
assignments: list[CardAssignment]
|
|
custom_fields: list[CustomField]
|
|
tags: list[TagId]
|
|
todo_list_user_id: UserId | None
|
|
todo_list_completed: bool | None
|
|
creator_user_id: UserId
|
|
creation_date: datetime.datetime
|
|
attachments: list[dict]
|
|
detailed_description: str | None
|
|
|
|
@staticmethod
|
|
def from_json(json: dict[str, Any]) -> 'Card':
|
|
todo_list_user_id = (
|
|
UserId(json['todoListUserId']) if 'todoListUserId' in json else None
|
|
)
|
|
return Card(
|
|
card_id=CardId(json['cardId']),
|
|
seq_id=SeqId(json['sequentialId']),
|
|
common_id=CommonId(json['cardCommonId']),
|
|
detailed_description=json.get('detailedDescription'),
|
|
is_archived=json['archived'],
|
|
organization_id=OrganizationId(json['organizationId']),
|
|
name=json['name'],
|
|
todo_list_user_id=todo_list_user_id,
|
|
todo_list_completed=json.get('todoListCompleted'),
|
|
dependencies=[
|
|
CardDependency.from_json(dep) for dep in json['dependencies']
|
|
],
|
|
tags=[TagId(tag) for tag in json['tags']],
|
|
creator_user_id=UserId(json['createdByUserId']),
|
|
creation_date=datetime.datetime.fromisoformat(json['createdAt']),
|
|
assignments=[CardAssignment.from_json(ass) for ass in json['assignments']],
|
|
custom_fields=[
|
|
CustomField.from_json(field) for field in json['customFields']
|
|
],
|
|
attachments=json['attachments'], # TODO
|
|
)
|