ajera 0.1.3__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.
- ajera/__init__.py +5 -0
- ajera/cli/__init__.py +95 -0
- ajera/cli/__main__.py +4 -0
- ajera/cli/commands/__init__.py +0 -0
- ajera/cli/commands/activities.py +31 -0
- ajera/cli/commands/bank_accounts.py +18 -0
- ajera/cli/commands/clients.py +153 -0
- ajera/cli/commands/companies.py +18 -0
- ajera/cli/commands/contacts.py +153 -0
- ajera/cli/commands/departments.py +18 -0
- ajera/cli/commands/employees.py +212 -0
- ajera/cli/commands/invoice_formats.py +18 -0
- ajera/cli/commands/ledger.py +101 -0
- ajera/cli/commands/projects.py +350 -0
- ajera/cli/commands/rate_tables.py +18 -0
- ajera/cli/commands/vendors.py +407 -0
- ajera/cli/context.py +37 -0
- ajera/cli/group.py +72 -0
- ajera/cli/options.py +27 -0
- ajera/cli/output.py +30 -0
- ajera/client.py +2049 -0
- ajera/schemas/client.py +614 -0
- ajera/schemas/contact.py +568 -0
- ajera/schemas/deduction.py +92 -0
- ajera/schemas/employee.py +858 -0
- ajera/schemas/fringe.py +92 -0
- ajera/schemas/generic.py +82 -0
- ajera/schemas/ledger.py +322 -0
- ajera/schemas/project.py +1416 -0
- ajera/schemas/project_summary.py +825 -0
- ajera/schemas/project_v2.py +1171 -0
- ajera/schemas/reference.py +704 -0
- ajera/schemas/session.py +96 -0
- ajera/schemas/vendor.py +691 -0
- ajera/schemas/vendor_invoice.py +624 -0
- ajera-0.1.3.dist-info/METADATA +203 -0
- ajera-0.1.3.dist-info/RECORD +39 -0
- ajera-0.1.3.dist-info/WHEEL +4 -0
- ajera-0.1.3.dist-info/entry_points.txt +3 -0
ajera/__init__.py
ADDED
ajera/cli/__init__.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from ajera.cli.commands import (
|
|
8
|
+
activities,
|
|
9
|
+
bank_accounts,
|
|
10
|
+
clients,
|
|
11
|
+
companies,
|
|
12
|
+
contacts,
|
|
13
|
+
departments,
|
|
14
|
+
employees,
|
|
15
|
+
invoice_formats,
|
|
16
|
+
ledger,
|
|
17
|
+
projects,
|
|
18
|
+
rate_tables,
|
|
19
|
+
vendors,
|
|
20
|
+
)
|
|
21
|
+
from ajera.cli.context import ClientContext
|
|
22
|
+
from ajera.cli.group import CommonClickGroup
|
|
23
|
+
|
|
24
|
+
CLI_DOCS = """
|
|
25
|
+
Deltek Ajera API command-line interface.
|
|
26
|
+
|
|
27
|
+
Connection settings are read from environment variables:
|
|
28
|
+
|
|
29
|
+
\b
|
|
30
|
+
- AJERA_API_URL to define the API endpoint.
|
|
31
|
+
- AJERA_API_USERNAME / AJERA_API_PASSWORD for authentication.
|
|
32
|
+
- AJERA_API_HEADERS as a JSON object of extra request headers.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@click.group(
|
|
37
|
+
cls=CommonClickGroup,
|
|
38
|
+
context_settings={"help_option_names": ["-h", "--help"]},
|
|
39
|
+
help=CLI_DOCS,
|
|
40
|
+
)
|
|
41
|
+
@click.option(
|
|
42
|
+
"--log",
|
|
43
|
+
is_flag=True,
|
|
44
|
+
default=False,
|
|
45
|
+
help="Enable request logging at INFO level.",
|
|
46
|
+
)
|
|
47
|
+
@click.version_option(package_name="ajera", prog_name="ajera")
|
|
48
|
+
@click.pass_context
|
|
49
|
+
def cli(ctx: click.Context, log: bool) -> None:
|
|
50
|
+
ctx.obj = ClientContext(log=log)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Register all domain-specific command groups.
|
|
54
|
+
# Runtime gating is handled by AJERA_CLI_DISABLE.
|
|
55
|
+
for module in (
|
|
56
|
+
employees,
|
|
57
|
+
clients,
|
|
58
|
+
contacts,
|
|
59
|
+
vendors,
|
|
60
|
+
projects,
|
|
61
|
+
ledger,
|
|
62
|
+
activities,
|
|
63
|
+
companies,
|
|
64
|
+
departments,
|
|
65
|
+
rate_tables,
|
|
66
|
+
bank_accounts,
|
|
67
|
+
invoice_formats,
|
|
68
|
+
):
|
|
69
|
+
cli.add_command(module.group)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main() -> None:
|
|
73
|
+
"""
|
|
74
|
+
Console-script entry point.
|
|
75
|
+
|
|
76
|
+
Translates expected errors into a non-zero exit with a readable message
|
|
77
|
+
instead of a traceback.
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
cli(standalone_mode=False)
|
|
81
|
+
except click.ClickException as exc:
|
|
82
|
+
exc.show()
|
|
83
|
+
sys.exit(exc.exit_code)
|
|
84
|
+
except click.exceptions.Abort:
|
|
85
|
+
sys.exit(1)
|
|
86
|
+
except requests.HTTPError as exc:
|
|
87
|
+
click.echo(f"Error: {exc}", err=True)
|
|
88
|
+
sys.exit(1)
|
|
89
|
+
except Exception as exc: # noqa: BLE001
|
|
90
|
+
logging.getLogger("ajera").debug("CLI error", exc_info=True)
|
|
91
|
+
click.echo(f"Error: {exc}", err=True)
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
__all__ = ["cli", "main"]
|
ajera/cli/__main__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.options import status_option
|
|
5
|
+
from ajera.cli.output import render
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command(name="activities")
|
|
9
|
+
@status_option
|
|
10
|
+
@click.option(
|
|
11
|
+
"--description-like",
|
|
12
|
+
"filter_by_description_like",
|
|
13
|
+
type=str,
|
|
14
|
+
default=None,
|
|
15
|
+
help="Filter where the description contains this substring.",
|
|
16
|
+
)
|
|
17
|
+
@click.pass_obj
|
|
18
|
+
def group(
|
|
19
|
+
ctx: ClientContext,
|
|
20
|
+
filter_by_status: tuple[str, ...],
|
|
21
|
+
filter_by_description_like: str | None,
|
|
22
|
+
) -> None:
|
|
23
|
+
"""
|
|
24
|
+
List activities (active only by default).
|
|
25
|
+
"""
|
|
26
|
+
render(
|
|
27
|
+
ctx.client.list_activities(
|
|
28
|
+
filter_by_status=list(filter_by_status),
|
|
29
|
+
filter_by_description_like=filter_by_description_like,
|
|
30
|
+
)
|
|
31
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.options import status_option
|
|
5
|
+
from ajera.cli.output import render
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command(name="bank-accounts")
|
|
9
|
+
@status_option
|
|
10
|
+
@click.pass_obj
|
|
11
|
+
def group(
|
|
12
|
+
ctx: ClientContext,
|
|
13
|
+
filter_by_status: tuple[str, ...],
|
|
14
|
+
) -> None:
|
|
15
|
+
"""
|
|
16
|
+
List bank accounts (active only by default).
|
|
17
|
+
"""
|
|
18
|
+
render(ctx.client.list_bank_accounts(filter_by_status=list(filter_by_status)))
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.group import CommonClickGroup
|
|
5
|
+
from ajera.cli.options import status_option
|
|
6
|
+
from ajera.cli.output import render
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group(name="clients", cls=CommonClickGroup)
|
|
10
|
+
def group() -> None:
|
|
11
|
+
"""
|
|
12
|
+
List and inspect clients.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@group.command(name="list")
|
|
17
|
+
@click.option(
|
|
18
|
+
"--company",
|
|
19
|
+
"filter_by_company",
|
|
20
|
+
type=int,
|
|
21
|
+
multiple=True,
|
|
22
|
+
help="Filter by company ID (repeatable).",
|
|
23
|
+
)
|
|
24
|
+
@status_option
|
|
25
|
+
@click.option(
|
|
26
|
+
"--name-like",
|
|
27
|
+
"filter_by_name_like",
|
|
28
|
+
type=str,
|
|
29
|
+
default=None,
|
|
30
|
+
help="Filter where the client name contains this substring.",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--name-equals",
|
|
34
|
+
"filter_by_name_equals",
|
|
35
|
+
type=str,
|
|
36
|
+
default=None,
|
|
37
|
+
help="Filter where the client name equals this value.",
|
|
38
|
+
)
|
|
39
|
+
@click.option(
|
|
40
|
+
"--client-type",
|
|
41
|
+
"filter_by_client_type",
|
|
42
|
+
type=int,
|
|
43
|
+
multiple=True,
|
|
44
|
+
help="Filter by client type ID (repeatable).",
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--modified-after",
|
|
48
|
+
"filter_by_earliest_modified_date",
|
|
49
|
+
type=str,
|
|
50
|
+
default=None,
|
|
51
|
+
help="Earliest modified date (YYYY-MM-DD or ISO 8601).",
|
|
52
|
+
)
|
|
53
|
+
@click.option(
|
|
54
|
+
"--modified-before",
|
|
55
|
+
"filter_by_latest_modified_date",
|
|
56
|
+
type=str,
|
|
57
|
+
default=None,
|
|
58
|
+
help="Latest modified date (YYYY-MM-DD or ISO 8601).",
|
|
59
|
+
)
|
|
60
|
+
@click.pass_obj
|
|
61
|
+
def list_(
|
|
62
|
+
ctx: ClientContext,
|
|
63
|
+
filter_by_company: tuple[int, ...],
|
|
64
|
+
filter_by_status: tuple[str, ...],
|
|
65
|
+
filter_by_name_like: str | None,
|
|
66
|
+
filter_by_name_equals: str | None,
|
|
67
|
+
filter_by_client_type: tuple[int, ...],
|
|
68
|
+
filter_by_earliest_modified_date: str | None,
|
|
69
|
+
filter_by_latest_modified_date: str | None,
|
|
70
|
+
) -> None:
|
|
71
|
+
"""
|
|
72
|
+
List clients (active only by default).
|
|
73
|
+
"""
|
|
74
|
+
render(
|
|
75
|
+
ctx.client.list_clients(
|
|
76
|
+
filter_by_company=list(filter_by_company) or None,
|
|
77
|
+
filter_by_status=list(filter_by_status),
|
|
78
|
+
filter_by_name_like=filter_by_name_like,
|
|
79
|
+
filter_by_name_equals=filter_by_name_equals,
|
|
80
|
+
filter_by_client_type=list(filter_by_client_type) or None,
|
|
81
|
+
filter_by_earliest_modified_date=filter_by_earliest_modified_date,
|
|
82
|
+
filter_by_latest_modified_date=filter_by_latest_modified_date,
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@group.command(name="get")
|
|
88
|
+
@click.argument("client_ids", nargs=-1, required=True, type=int)
|
|
89
|
+
@click.pass_obj
|
|
90
|
+
def get(ctx: ClientContext, client_ids: tuple[int, ...]) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Get one or more clients by ID.
|
|
93
|
+
"""
|
|
94
|
+
render(ctx.client.get_clients(list(client_ids)))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@group.command(name="update")
|
|
98
|
+
@click.argument("client_key", type=int)
|
|
99
|
+
@click.option("--description", default=None, help="New client description (name).")
|
|
100
|
+
@click.option("--account-id", default=None, help="New account ID.")
|
|
101
|
+
@click.option("--email", default=None, help="New email address.")
|
|
102
|
+
@click.option("--website", default=None, help="New website URL.")
|
|
103
|
+
@click.option("--primary-phone", default=None, help="New primary phone number.")
|
|
104
|
+
@click.option("--secondary-phone", default=None, help="New secondary phone number.")
|
|
105
|
+
@click.option("--tertiary-phone", default=None, help="New tertiary phone number.")
|
|
106
|
+
@click.option("--fax", default=None, help="New fax number.")
|
|
107
|
+
@click.option("--notes", default=None, help="New notes.")
|
|
108
|
+
@click.pass_obj
|
|
109
|
+
def update(
|
|
110
|
+
ctx: ClientContext,
|
|
111
|
+
client_key: int,
|
|
112
|
+
description: str | None,
|
|
113
|
+
account_id: str | None,
|
|
114
|
+
email: str | None,
|
|
115
|
+
website: str | None,
|
|
116
|
+
primary_phone: str | None,
|
|
117
|
+
secondary_phone: str | None,
|
|
118
|
+
tertiary_phone: str | None,
|
|
119
|
+
fax: str | None,
|
|
120
|
+
notes: str | None,
|
|
121
|
+
) -> None:
|
|
122
|
+
"""
|
|
123
|
+
Update simple fields on one client.
|
|
124
|
+
|
|
125
|
+
Only the options you pass are changed; everything else is left as-is.
|
|
126
|
+
"""
|
|
127
|
+
render(
|
|
128
|
+
ctx.client.update_client(
|
|
129
|
+
client_key,
|
|
130
|
+
description=description,
|
|
131
|
+
account_id=account_id,
|
|
132
|
+
email=email,
|
|
133
|
+
website=website,
|
|
134
|
+
primary_phone_number=primary_phone,
|
|
135
|
+
secondary_phone_number=secondary_phone,
|
|
136
|
+
tertiary_phone_number=tertiary_phone,
|
|
137
|
+
fax_number=fax,
|
|
138
|
+
notes=notes,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@group.command(name="types")
|
|
144
|
+
@status_option
|
|
145
|
+
@click.pass_obj
|
|
146
|
+
def types(
|
|
147
|
+
ctx: ClientContext,
|
|
148
|
+
filter_by_status: tuple[str, ...],
|
|
149
|
+
) -> None:
|
|
150
|
+
"""
|
|
151
|
+
List client types (active only by default).
|
|
152
|
+
"""
|
|
153
|
+
render(ctx.client.list_client_types(filter_by_status=list(filter_by_status)))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.options import status_option
|
|
5
|
+
from ajera.cli.output import render
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command(name="companies")
|
|
9
|
+
@status_option
|
|
10
|
+
@click.pass_obj
|
|
11
|
+
def group(
|
|
12
|
+
ctx: ClientContext,
|
|
13
|
+
filter_by_status: tuple[str, ...],
|
|
14
|
+
) -> None:
|
|
15
|
+
"""
|
|
16
|
+
List companies (active only by default).
|
|
17
|
+
"""
|
|
18
|
+
render(ctx.client.list_companies(filter_by_status=list(filter_by_status)))
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.group import CommonClickGroup
|
|
5
|
+
from ajera.cli.options import status_option
|
|
6
|
+
from ajera.cli.output import render
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group(name="contacts", cls=CommonClickGroup)
|
|
10
|
+
def group() -> None:
|
|
11
|
+
"""
|
|
12
|
+
List and inspect contacts.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@group.command(name="list")
|
|
17
|
+
@click.option(
|
|
18
|
+
"--company",
|
|
19
|
+
"filter_by_company",
|
|
20
|
+
type=int,
|
|
21
|
+
multiple=True,
|
|
22
|
+
help="Filter by company ID (repeatable).",
|
|
23
|
+
)
|
|
24
|
+
@status_option
|
|
25
|
+
@click.option(
|
|
26
|
+
"--text",
|
|
27
|
+
"filter_by_text",
|
|
28
|
+
type=str,
|
|
29
|
+
default=None,
|
|
30
|
+
help="Filter where the contact text contains this substring.",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--contact-type",
|
|
34
|
+
"filter_by_contact_type",
|
|
35
|
+
type=int,
|
|
36
|
+
multiple=True,
|
|
37
|
+
help="Filter by contact type ID (repeatable).",
|
|
38
|
+
)
|
|
39
|
+
@click.option(
|
|
40
|
+
"--modified-after",
|
|
41
|
+
"filter_by_earliest_modified_date",
|
|
42
|
+
type=str,
|
|
43
|
+
default=None,
|
|
44
|
+
help="Earliest modified date (YYYY-MM-DD or ISO 8601).",
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--modified-before",
|
|
48
|
+
"filter_by_latest_modified_date",
|
|
49
|
+
type=str,
|
|
50
|
+
default=None,
|
|
51
|
+
help="Latest modified date (YYYY-MM-DD or ISO 8601).",
|
|
52
|
+
)
|
|
53
|
+
@click.pass_obj
|
|
54
|
+
def list_(
|
|
55
|
+
ctx: ClientContext,
|
|
56
|
+
filter_by_company: tuple[int, ...],
|
|
57
|
+
filter_by_status: tuple[str, ...],
|
|
58
|
+
filter_by_text: str | None,
|
|
59
|
+
filter_by_contact_type: tuple[int, ...],
|
|
60
|
+
filter_by_earliest_modified_date: str | None,
|
|
61
|
+
filter_by_latest_modified_date: str | None,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""
|
|
64
|
+
List contacts (active only by default).
|
|
65
|
+
"""
|
|
66
|
+
render(
|
|
67
|
+
ctx.client.list_contacts(
|
|
68
|
+
filter_by_company=list(filter_by_company) or None,
|
|
69
|
+
filter_by_status=list(filter_by_status),
|
|
70
|
+
filter_by_text=filter_by_text,
|
|
71
|
+
filter_by_contact_type=list(filter_by_contact_type) or None,
|
|
72
|
+
filter_by_earliest_modified_date=filter_by_earliest_modified_date,
|
|
73
|
+
filter_by_latest_modified_date=filter_by_latest_modified_date,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@group.command(name="get")
|
|
79
|
+
@click.argument("contact_ids", nargs=-1, required=True, type=int)
|
|
80
|
+
@click.pass_obj
|
|
81
|
+
def get(ctx: ClientContext, contact_ids: tuple[int, ...]) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Get one or more contacts by ID.
|
|
84
|
+
"""
|
|
85
|
+
render(ctx.client.get_contacts(list(contact_ids)))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@group.command(name="update")
|
|
89
|
+
@click.argument("contact_key", type=int)
|
|
90
|
+
@click.option("--first-name", default=None, help="New first name.")
|
|
91
|
+
@click.option("--middle-name", default=None, help="New middle name.")
|
|
92
|
+
@click.option("--last-name", default=None, help="New last name.")
|
|
93
|
+
@click.option("--title", default=None, help="New title.")
|
|
94
|
+
@click.option("--company", default=None, help="New company.")
|
|
95
|
+
@click.option("--email", default=None, help="New email address.")
|
|
96
|
+
@click.option("--website", default=None, help="New website URL.")
|
|
97
|
+
@click.option("--primary-phone", default=None, help="New primary phone number.")
|
|
98
|
+
@click.option("--secondary-phone", default=None, help="New secondary phone number.")
|
|
99
|
+
@click.option("--tertiary-phone", default=None, help="New tertiary phone number.")
|
|
100
|
+
@click.option("--fax", default=None, help="New fax number.")
|
|
101
|
+
@click.option("--notes", default=None, help="New notes.")
|
|
102
|
+
@click.pass_obj
|
|
103
|
+
def update(
|
|
104
|
+
ctx: ClientContext,
|
|
105
|
+
contact_key: int,
|
|
106
|
+
first_name: str | None,
|
|
107
|
+
middle_name: str | None,
|
|
108
|
+
last_name: str | None,
|
|
109
|
+
title: str | None,
|
|
110
|
+
company: str | None,
|
|
111
|
+
email: str | None,
|
|
112
|
+
website: str | None,
|
|
113
|
+
primary_phone: str | None,
|
|
114
|
+
secondary_phone: str | None,
|
|
115
|
+
tertiary_phone: str | None,
|
|
116
|
+
fax: str | None,
|
|
117
|
+
notes: str | None,
|
|
118
|
+
) -> None:
|
|
119
|
+
"""
|
|
120
|
+
Update simple fields on one contact.
|
|
121
|
+
|
|
122
|
+
Only the options you pass are changed; everything else is left as-is.
|
|
123
|
+
"""
|
|
124
|
+
render(
|
|
125
|
+
ctx.client.update_contact(
|
|
126
|
+
contact_key,
|
|
127
|
+
first_name=first_name,
|
|
128
|
+
middle_name=middle_name,
|
|
129
|
+
last_name=last_name,
|
|
130
|
+
title=title,
|
|
131
|
+
company=company,
|
|
132
|
+
email=email,
|
|
133
|
+
website=website,
|
|
134
|
+
primary_phone_number=primary_phone,
|
|
135
|
+
secondary_phone_number=secondary_phone,
|
|
136
|
+
tertiary_phone_number=tertiary_phone,
|
|
137
|
+
fax_number=fax,
|
|
138
|
+
notes=notes,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@group.command(name="types")
|
|
144
|
+
@status_option
|
|
145
|
+
@click.pass_obj
|
|
146
|
+
def types(
|
|
147
|
+
ctx: ClientContext,
|
|
148
|
+
filter_by_status: tuple[str, ...],
|
|
149
|
+
) -> None:
|
|
150
|
+
"""
|
|
151
|
+
List contact types (active only by default).
|
|
152
|
+
"""
|
|
153
|
+
render(ctx.client.list_contact_types(filter_by_status=list(filter_by_status)))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from ajera.cli.context import ClientContext
|
|
4
|
+
from ajera.cli.options import status_option
|
|
5
|
+
from ajera.cli.output import render
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@click.command(name="departments")
|
|
9
|
+
@status_option
|
|
10
|
+
@click.pass_obj
|
|
11
|
+
def group(
|
|
12
|
+
ctx: ClientContext,
|
|
13
|
+
filter_by_status: tuple[str, ...],
|
|
14
|
+
) -> None:
|
|
15
|
+
"""
|
|
16
|
+
List departments (active only by default).
|
|
17
|
+
"""
|
|
18
|
+
render(ctx.client.list_departments(filter_by_status=list(filter_by_status)))
|