wealthbox-cli 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. wealthbox_cli-1.0.0.dist-info/METADATA +230 -0
  2. wealthbox_cli-1.0.0.dist-info/RECORD +54 -0
  3. wealthbox_cli-1.0.0.dist-info/WHEEL +4 -0
  4. wealthbox_cli-1.0.0.dist-info/entry_points.txt +3 -0
  5. wealthbox_cli-1.0.0.dist-info/licenses/LICENSE +201 -0
  6. wealthbox_tools/__init__.py +51 -0
  7. wealthbox_tools/cli/__init__.py +3 -0
  8. wealthbox_tools/cli/_config.py +43 -0
  9. wealthbox_tools/cli/_util.py +315 -0
  10. wealthbox_tools/cli/activity.py +42 -0
  11. wealthbox_tools/cli/categories.py +41 -0
  12. wealthbox_tools/cli/comments.py +51 -0
  13. wealthbox_tools/cli/config.py +47 -0
  14. wealthbox_tools/cli/contacts.py +412 -0
  15. wealthbox_tools/cli/events.py +168 -0
  16. wealthbox_tools/cli/households.py +41 -0
  17. wealthbox_tools/cli/main.py +55 -0
  18. wealthbox_tools/cli/me.py +25 -0
  19. wealthbox_tools/cli/notes.py +97 -0
  20. wealthbox_tools/cli/opportunities.py +198 -0
  21. wealthbox_tools/cli/projects.py +102 -0
  22. wealthbox_tools/cli/tasks.py +180 -0
  23. wealthbox_tools/cli/users.py +24 -0
  24. wealthbox_tools/cli/workflows.py +172 -0
  25. wealthbox_tools/client/__init__.py +45 -0
  26. wealthbox_tools/client/activity.py +13 -0
  27. wealthbox_tools/client/base.py +216 -0
  28. wealthbox_tools/client/categories.py +14 -0
  29. wealthbox_tools/client/comments.py +14 -0
  30. wealthbox_tools/client/contacts.py +44 -0
  31. wealthbox_tools/client/events.py +31 -0
  32. wealthbox_tools/client/households.py +30 -0
  33. wealthbox_tools/client/me.py +11 -0
  34. wealthbox_tools/client/notes.py +28 -0
  35. wealthbox_tools/client/opportunities.py +31 -0
  36. wealthbox_tools/client/projects.py +28 -0
  37. wealthbox_tools/client/tasks.py +31 -0
  38. wealthbox_tools/client/users.py +14 -0
  39. wealthbox_tools/client/workflows.py +44 -0
  40. wealthbox_tools/models/__init__.py +134 -0
  41. wealthbox_tools/models/activity.py +13 -0
  42. wealthbox_tools/models/comments.py +13 -0
  43. wealthbox_tools/models/common.py +123 -0
  44. wealthbox_tools/models/contacts.py +131 -0
  45. wealthbox_tools/models/custom_fields.py +19 -0
  46. wealthbox_tools/models/enums.py +209 -0
  47. wealthbox_tools/models/events.py +63 -0
  48. wealthbox_tools/models/households.py +17 -0
  49. wealthbox_tools/models/notes.py +28 -0
  50. wealthbox_tools/models/opportunities.py +48 -0
  51. wealthbox_tools/models/projects.py +27 -0
  52. wealthbox_tools/models/tasks.py +76 -0
  53. wealthbox_tools/models/workflows.py +50 -0
  54. wealthbox_tools/py.typed +0 -0
@@ -0,0 +1,209 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import StrEnum
4
+
5
+
6
+ # Contacts
7
+ class RecordType(StrEnum):
8
+ PERSON = "Person"
9
+ HOUSEHOLD = "Household"
10
+ ORGANIZATION = "Organization"
11
+ TRUST = "Trust"
12
+
13
+
14
+ class Gender(StrEnum):
15
+ FEMALE = "Female"
16
+ MALE = "Male"
17
+ NON_BINARY = "Non-binary"
18
+ UNKNOWN = "Unknown"
19
+
20
+
21
+ class MaritalStatus(StrEnum):
22
+ MARRIED = "Married"
23
+ SINGLE = "Single"
24
+ DIVORCED = "Divorced"
25
+ WIDOWED = "Widowed"
26
+ LIFE_PARTNER = "Life partner"
27
+ SEPARATED = "Separated"
28
+ UNKNOWN = "Unknown"
29
+
30
+ class ContactsOrder(StrEnum):
31
+ ASC = "asc"
32
+ DESC = "desc"
33
+ RECENT = "recent"
34
+ CREATED = "created"
35
+ UPDATED = "updated"
36
+
37
+
38
+ # Households
39
+ class HouseholdTitle(StrEnum):
40
+ HEAD = "Head"
41
+ SPOUSE = "Spouse"
42
+ CHILD = "Child"
43
+ OTHER_DEPENDENT = "Other Dependent"
44
+ PARTNER = "Partner"
45
+ PARENT = "Parent"
46
+ SIBLING = "Sibling"
47
+ GRANDPARENT = "Grandparent"
48
+ GRANDCHILD = "Grandchild"
49
+
50
+
51
+ # Activity
52
+ class ActivityType(StrEnum):
53
+ CONTACT = "Contact"
54
+ STATUS_UPDATE = "StatusUpdate"
55
+ DROPBOX_EMAIL = "DropboxEmail"
56
+ PHONE_CALL = "PhoneCall"
57
+ TASK = "Task"
58
+ EVENT = "Event"
59
+ WORKFLOW = "Workflow"
60
+ WORKFLOW_STEP = "WorkflowStep"
61
+ OPPORTUNITY = "Opportunity"
62
+ DATA_FILE = "DataFile"
63
+ MAIL_MERGE = "MailMerge"
64
+ PROJECT = "Project"
65
+ USER = "User"
66
+ MEETING = "Meeting"
67
+ CUSTOM_OBJECT = "CustomObject"
68
+
69
+
70
+ # Categories
71
+ class CategoryType(StrEnum):
72
+ TAGS = "tags"
73
+ CUSTOM_FIELDS = "custom_fields"
74
+ OPPORTUNITY_STAGES = "opportunity_stages"
75
+ OPPORTUNITY_PIPELINES = "opportunity_pipelines"
76
+ CONTACT_TYPES = "contact_types"
77
+ CONTACT_SOURCES = "contact_sources"
78
+ TASK_CATEGORIES = "task_categories"
79
+ EVENT_CATEGORIES = "event_categories"
80
+ FILE_CATEGORIES = "file_categories"
81
+ INVESTMENT_OBJECTIVES = "investment_objectives"
82
+ FINANCIAL_ACCOUNT_TYPES = "financial_account_types"
83
+ EMAIL_TYPES = "email_types"
84
+ PHONE_TYPES = "phone_types"
85
+ ADDRESS_TYPES = "address_types"
86
+ WEBSITE_TYPES = "website_types"
87
+ CONTACT_ROLES = "contact_roles"
88
+
89
+
90
+ class DocumentType(StrEnum):
91
+ CONTACT = "Contact"
92
+ OPPORTUNITY = "Opportunity"
93
+ PROJECT = "Project"
94
+ TASK = "Task"
95
+ EVENT = "Event"
96
+ MANUAL_INVESTMENT_ACCOUNT = "ManualInvestmentAccount"
97
+ DATA_FILE = "DataFile"
98
+
99
+
100
+ # Events
101
+ class EventsState(StrEnum):
102
+ UNCONFIRMED = "unconfirmed"
103
+ CONFIRMED = "confirmed"
104
+ TENTATIVE = "tentative"
105
+ COMPLETED = "completed"
106
+ CANCELLED = "cancelled"
107
+
108
+
109
+ class EventsOrder(StrEnum):
110
+ ASC = "asc"
111
+ DESC = "desc"
112
+ RECENT = "recent"
113
+ CREATED = "created"
114
+
115
+
116
+
117
+
118
+ class EmailInviteeType(StrEnum):
119
+ USER = "User"
120
+ CONTACT = "Contact"
121
+
122
+
123
+ # Notes
124
+ class NotesOrder(StrEnum):
125
+ ASC = "asc"
126
+ CREATED = "created"
127
+ UPDATED = "updated"
128
+
129
+
130
+ # Tasks
131
+ class TaskFrame(StrEnum):
132
+ TODAY = "today"
133
+ TOMORROW = "tomorrow"
134
+ THIS_WEEK = "this_week"
135
+ NEXT_WEEK = "next_week"
136
+ FUTURE = "future"
137
+ SPECIFIC = "specific"
138
+
139
+
140
+ class TaskResourceType(StrEnum):
141
+ CONTACT = "Contact"
142
+ PROJECT = "Project"
143
+ OPPORTUNITY = "Opportunity"
144
+
145
+
146
+ class NoteResourceType(StrEnum):
147
+ CONTACT = "Contact"
148
+
149
+
150
+ class CommentResourceType(StrEnum):
151
+ CONTACT = "Contact"
152
+ TASK = "Task"
153
+ EVENT = "Event"
154
+
155
+
156
+ class OpportunityResourceType(StrEnum):
157
+ CONTACT = "Contact"
158
+ PROJECT = "Project"
159
+
160
+
161
+ class WorkflowResourceType(StrEnum):
162
+ CONTACT = "Contact"
163
+ PROJECT = "Project"
164
+
165
+
166
+ class TaskType(StrEnum):
167
+ ALL = "all"
168
+ PARENTS = "parents"
169
+ SUBTASKS = "subtasks"
170
+
171
+
172
+ class TaskPriority(StrEnum):
173
+ LOW = "Low"
174
+ MEDIUM = "Medium"
175
+ HIGH = "High"
176
+
177
+
178
+ class InvestmentRiskTolerance(StrEnum):
179
+ LOW = "Low"
180
+ MODERATE = "Moderate"
181
+ HIGH = "High Risk"
182
+
183
+
184
+ class InvestmentTimeHorizon(StrEnum):
185
+ SHORT_TERM = "Short Term"
186
+ INTERMEDIATE = "Intermediate"
187
+ LONG_TERM = "Long Term"
188
+
189
+
190
+ # Opportunities
191
+ class OpportunityOrder(StrEnum):
192
+ ASC = "asc"
193
+ DESC = "desc"
194
+ RECENT = "recent"
195
+ CREATED = "created"
196
+
197
+
198
+ class OpportunityAmountKind(StrEnum):
199
+ FEE = "Fee"
200
+ COMMISSION = "Commission"
201
+ AUM = "AUM"
202
+ OTHER = "Other"
203
+
204
+
205
+ # Workflows
206
+ class WorkflowStatus(StrEnum):
207
+ ACTIVE = "active"
208
+ COMPLETED = "completed"
209
+ SCHEDULED = "scheduled"
@@ -0,0 +1,63 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from .common import (
6
+ DateField,
7
+ DateTimeField,
8
+ LinkedToRef,
9
+ NonNullDateTimeField,
10
+ PaginationQuery,
11
+ RequireAnyFieldModel,
12
+ WealthboxModel,
13
+ )
14
+ from .enums import EmailInviteeType, EventsOrder, EventsState, TaskResourceType
15
+
16
+
17
+ class EmailInvitees(WealthboxModel):
18
+ id: int | None = Field(default=None, ge=1)
19
+ type: EmailInviteeType | None = None
20
+
21
+
22
+ class EventListQuery(PaginationQuery):
23
+ resource_id: int | None = Field(default=None, ge=1)
24
+ resource_type: TaskResourceType | None = None
25
+ start_date_min: DateField = None
26
+ start_date_max: DateField = None
27
+ order: EventsOrder | None = None
28
+ updated_since: DateTimeField = None
29
+ updated_before: DateTimeField = None
30
+
31
+
32
+ class EventCreateInput(WealthboxModel):
33
+ title: str = Field(min_length=1)
34
+ starts_at: NonNullDateTimeField
35
+ ends_at: NonNullDateTimeField
36
+ repeats: bool | None = None
37
+ event_category: int | None = Field(default=None, ge=1)
38
+ all_day: bool | None = None
39
+ location: str | None = None
40
+ description: str | None = None
41
+ state: EventsState | None = None
42
+ # visible_to: str | None = None
43
+ email_invitees: bool | None = None
44
+ linked_to: list[LinkedToRef] | None = None
45
+ invitees: list[EmailInvitees] | None = None
46
+ # custom_fields: str | None = None
47
+
48
+
49
+ class EventUpdateInput(RequireAnyFieldModel):
50
+ title: str | None = None
51
+ starts_at: DateTimeField = None
52
+ ends_at: DateTimeField = None
53
+ repeats: bool | None = None
54
+ event_category: int | None = Field(default=None, ge=1)
55
+ all_day: bool | None = None
56
+ location: str | None = None
57
+ description: str | None = None
58
+ state: EventsState | None = None
59
+ # visible_to: str | None = None
60
+ email_invitees: bool | None = None
61
+ linked_to: list[LinkedToRef] | None = None
62
+ invitees: list[EmailInvitees] | None = None
63
+ # custom_fields: str | None = None
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field, model_validator
4
+
5
+ from .common import WealthboxModel
6
+ from .enums import HouseholdTitle
7
+
8
+
9
+ class HouseholdMemberInput(WealthboxModel):
10
+ id: int | None = Field(default=None, ge=1)
11
+ title: HouseholdTitle | None = Field(default=None, min_length=1)
12
+
13
+ @model_validator(mode="after")
14
+ def ensure_member_target(self) -> "HouseholdMemberInput":
15
+ if self.id is None and self.title is None:
16
+ raise ValueError("Either id or title must be provided.")
17
+ return self
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from .common import DateTimeField, LinkedToRef, PaginationQuery, RequireAnyFieldModel, WealthboxModel
6
+ from .enums import NoteResourceType, NotesOrder
7
+
8
+
9
+ class NoteListQuery(PaginationQuery):
10
+ resource_id: int | None = Field(default=None, ge=1)
11
+ resource_type: NoteResourceType | None = None
12
+ order: NotesOrder | None = None
13
+ updated_since: DateTimeField = None
14
+ updated_before: DateTimeField = None
15
+
16
+
17
+ class NoteCreateInput(WealthboxModel):
18
+ content: str = Field(min_length=1)
19
+ linked_to: list[LinkedToRef] | None = None
20
+ # visable_to: str | None = None
21
+ # tags: list[str] | None = None
22
+
23
+
24
+ class NoteUpdateInput(RequireAnyFieldModel):
25
+ content: str | None = Field(default=None, min_length=1)
26
+ linked_to: list[LinkedToRef] | None = None
27
+ # visable_to: str | None = None
28
+ # tags: list[str] | None = None
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from .common import DateTimeField, LinkedToRef, PaginationQuery, RequireAnyFieldModel, WealthboxModel
6
+ from .custom_fields import CustomFieldValue
7
+ from .enums import OpportunityAmountKind, OpportunityOrder, OpportunityResourceType
8
+
9
+
10
+ class OpportunityAmount(WealthboxModel):
11
+ amount: float
12
+ currency: str = Field(min_length=1)
13
+ kind: OpportunityAmountKind
14
+
15
+
16
+ class OpportunityListQuery(PaginationQuery):
17
+ resource_id: int | None = Field(default=None, ge=1)
18
+ resource_type: OpportunityResourceType | None = None
19
+ order: OpportunityOrder | None = None
20
+ include_closed: bool | None = None
21
+ updated_since: DateTimeField = None
22
+ updated_before: DateTimeField = None
23
+
24
+
25
+ class OpportunityCreateInput(WealthboxModel):
26
+ name: str = Field(min_length=1)
27
+ description: str | None = None
28
+ target_close: str = Field(min_length=1)
29
+ probability: int = Field(ge=0, le=100)
30
+ stage: int = Field(ge=1)
31
+ manager: int | None = None
32
+ amounts: list[OpportunityAmount] | None = None
33
+ linked_to: list[LinkedToRef] | None = None
34
+ visible_to: str | None = None
35
+ custom_fields: list[CustomFieldValue] | None = None
36
+
37
+
38
+ class OpportunityUpdateInput(RequireAnyFieldModel):
39
+ name: str | None = None
40
+ description: str | None = None
41
+ target_close: str | None = None
42
+ probability: int | None = Field(default=None, ge=0, le=100)
43
+ stage: int | None = Field(default=None, ge=1)
44
+ manager: int | None = None
45
+ amounts: list[OpportunityAmount] | None = None
46
+ linked_to: list[LinkedToRef] | None = None
47
+ visible_to: str | None = None
48
+ custom_fields: list[CustomFieldValue] | None = None
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from .common import DateTimeField, PaginationQuery, RequireAnyFieldModel, WealthboxModel
6
+ from .custom_fields import CustomFieldValue
7
+
8
+
9
+ class ProjectListQuery(PaginationQuery):
10
+ updated_since: DateTimeField = None
11
+ updated_before: DateTimeField = None
12
+
13
+
14
+ class ProjectCreateInput(WealthboxModel):
15
+ name: str = Field(min_length=1)
16
+ description: str = Field(min_length=1)
17
+ organizer: int | None = None
18
+ visible_to: str | None = None
19
+ custom_fields: list[CustomFieldValue] | None = None
20
+
21
+
22
+ class ProjectUpdateInput(RequireAnyFieldModel):
23
+ name: str | None = None
24
+ description: str | None = None
25
+ organizer: int | None = None
26
+ visible_to: str | None = None
27
+ custom_fields: list[CustomFieldValue] | None = None
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field, model_validator
4
+
5
+ from .common import DateTimeField, LinkedToRef, PaginationQuery, RequireAnyFieldModel, WealthboxModel
6
+ from .enums import TaskFrame, TaskPriority, TaskResourceType, TaskType
7
+
8
+
9
+ def _validate_assignment_target(assigned_to: int | None, assigned_to_team: int | None) -> None:
10
+ if assigned_to is not None and assigned_to_team is not None:
11
+ raise ValueError("Provide only one of assigned_to or assigned_to_team.")
12
+
13
+
14
+
15
+ class TaskListQuery(PaginationQuery):
16
+ resource_id: int | None = Field(default=None, ge=1)
17
+ resource_type: TaskResourceType | None = None
18
+ assigned_to: int | None = Field(default=None, ge=1)
19
+ assigned_to_team: int | None = Field(default=None, ge=1)
20
+ created_by: int | None = Field(default=None, ge=1)
21
+ completed: bool | None = None
22
+ task_type: TaskType | None = None
23
+ updated_since: DateTimeField = None
24
+ updated_before: DateTimeField = None
25
+
26
+
27
+ class TaskCreateInput(WealthboxModel):
28
+ name: str = Field(min_length=1)
29
+ due_date: DateTimeField = None
30
+ frame: TaskFrame | None = None
31
+ complete: bool | None = None
32
+ category: int | None = Field(default=None, ge=1)
33
+ linked_to: list[LinkedToRef] | None = None
34
+ priority: TaskPriority | None = None
35
+ # visible_to: str | None = None
36
+ # due_later: str | None = None
37
+ # subtasks: SubTaskInput | None = None
38
+ # custom_fields: TaskCustomFieldInput | None = None
39
+ assigned_to: int | None = Field(default=None, ge=1)
40
+ assigned_to_team: int | None = Field(default=None, ge=1)
41
+ description: str | None = None
42
+
43
+ @model_validator(mode="after")
44
+ def validate_assignment_target(self) -> "TaskCreateInput":
45
+ _validate_assignment_target(self.assigned_to, self.assigned_to_team)
46
+ return self
47
+
48
+ @model_validator(mode="after")
49
+ def validate_due_date_xor_frame(self) -> "TaskCreateInput":
50
+ if (self.due_date is None) == (self.frame is None):
51
+ # both None OR both set
52
+ raise ValueError("Provide exactly one of due_date or frame (not both).")
53
+ return self
54
+
55
+
56
+
57
+ class TaskUpdateInput(RequireAnyFieldModel):
58
+ name: str | None = Field(default=None, min_length=1)
59
+ due_date: DateTimeField = None
60
+ frame: TaskFrame | None = None
61
+ complete: bool | None = None
62
+ category: int | None = Field(default=None, ge=1)
63
+ linked_to: list[LinkedToRef] | None = None
64
+ priority: TaskPriority | None = None
65
+ # visible_to: str | None = None
66
+ # due_later: str | None = None
67
+ # subtasks: SubTaskInput | None = None
68
+ # custom_fields: TaskCustomFieldInput | None = None
69
+ assigned_to: int | None = Field(default=None, ge=1)
70
+ assigned_to_team: int | None = Field(default=None, ge=1)
71
+ description: str | None = None
72
+
73
+ @model_validator(mode="after")
74
+ def validate_assignment_target(self) -> "TaskUpdateInput":
75
+ _validate_assignment_target(self.assigned_to, self.assigned_to_team)
76
+ return self
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import Field
4
+
5
+ from .common import DateTimeField, LinkedToRef, PaginationQuery, WealthboxModel
6
+ from .enums import WorkflowResourceType, WorkflowStatus
7
+
8
+
9
+ class WorkflowMilestone(WealthboxModel):
10
+ id: int = Field(ge=1)
11
+ name: str = Field(min_length=1)
12
+ milestone_date: str = Field(min_length=1)
13
+
14
+
15
+ class WorkflowListQuery(PaginationQuery):
16
+ resource_id: int | None = Field(default=None, ge=1)
17
+ resource_type: WorkflowResourceType | None = None
18
+ status: WorkflowStatus | None = None
19
+ updated_since: DateTimeField = None
20
+ updated_before: DateTimeField = None
21
+
22
+
23
+ class WorkflowCreateInput(WealthboxModel):
24
+ label: str | None = None
25
+ linked_to: list[LinkedToRef] | None = None
26
+ visible_to: str | None = None
27
+ workflow_template: int = Field(ge=1)
28
+ starts_at: str | None = None
29
+ workflow_milestones: list[WorkflowMilestone] | None = None
30
+
31
+
32
+ class WorkflowTemplateListQuery(PaginationQuery):
33
+ resource_id: int | None = Field(default=None, ge=1)
34
+ resource_type: WorkflowResourceType | None = None
35
+ status: WorkflowStatus | None = None
36
+ updated_since: DateTimeField = None
37
+ updated_before: DateTimeField = None
38
+
39
+
40
+ class WorkflowStepCompleteInput(WealthboxModel):
41
+ complete: bool = Field(default=True)
42
+ workflow_outcome_id: int | None = None
43
+ # When selecting an outcome with the “Restart Step” action, this indicates
44
+ # whether the restarted step will have a due date.
45
+ due_date_set: bool = Field(default=False)
46
+ due_date: str | None = None
47
+
48
+
49
+ class WorkflowStepRevertInput(WealthboxModel):
50
+ revert: bool = Field(default=True)
File without changes