crowdtime-cli 0.22.0__tar.gz → 0.23.0__tar.gz
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.
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/PKG-INFO +1 -1
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/pyproject.toml +1 -1
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/__init__.py +1 -1
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/invoice_cmd.py +61 -11
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/skills/crowdtime/SKILL.md +3 -2
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/skills/crowdtime/references/commands.md +9 -5
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/skills/crowdtime/references/workflows.md +1 -1
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/.gitignore +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/LICENSE +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/README.md +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/auth.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/client.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/__init__.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/ai_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/auth_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/billing_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/calendar_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/clients_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/config_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/expense_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/favorites_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/insights_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/log_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/org_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/payroll_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/projects_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/pto_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/report_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/skill_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/tasks_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/team_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/timer_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/timesheet_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/commands/version_cmd.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/config.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/formatters.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/main.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/models.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/oauth.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/resolvers.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/skills/crowdtime/references/pto.md +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/utils.py +0 -0
- {crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/version_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crowdtime-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: AI-powered time tracking CLI — a modern, developer-friendly alternative to Harvest
|
|
5
5
|
Project-URL: Homepage, https://crowdtime.lat
|
|
6
6
|
Project-URL: Documentation, https://crowdtime.lat/docs
|
|
@@ -572,6 +572,41 @@ def show_invoice(
|
|
|
572
572
|
raise typer.Exit(1)
|
|
573
573
|
|
|
574
574
|
|
|
575
|
+
# How hours are shown on an invoice (CRO-94). "person" is accepted for "user".
|
|
576
|
+
HOURS_DISPLAYS = {
|
|
577
|
+
"project": "project", "task": "task", "user": "user", "person": "user",
|
|
578
|
+
"date": "date", "none": "none", "detailed": "detailed",
|
|
579
|
+
}
|
|
580
|
+
LINE_DETAILS = ["date", "person", "project", "task", "notes"]
|
|
581
|
+
GROUP_BY_HELP = (
|
|
582
|
+
"How to display hours: project, task, person (one line each, per project), "
|
|
583
|
+
"detailed (one line per time entry), date, or none (everything on one line)."
|
|
584
|
+
)
|
|
585
|
+
DETAILS_HELP = (
|
|
586
|
+
"What each detailed line shows (implies --group-by detailed), comma-separated "
|
|
587
|
+
"from date, person, project, task, notes. Default: person,date,notes."
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
def _display_payload(group_by: Optional[str], details: Optional[str]) -> dict:
|
|
592
|
+
"""Validate --group-by / --details into API fields, or raise ValueError."""
|
|
593
|
+
payload: dict = {}
|
|
594
|
+
if group_by is not None:
|
|
595
|
+
resolved = HOURS_DISPLAYS.get(group_by.strip().lower())
|
|
596
|
+
if resolved is None:
|
|
597
|
+
raise ValueError(f"Invalid --group-by. Choose from: {', '.join(HOURS_DISPLAYS)}.")
|
|
598
|
+
payload["group_by"] = resolved
|
|
599
|
+
if details is not None:
|
|
600
|
+
items = [d.strip().lower() for d in details.split(",") if d.strip()]
|
|
601
|
+
bad = [d for d in items if d not in LINE_DETAILS]
|
|
602
|
+
if bad or not items:
|
|
603
|
+
raise ValueError(f"Invalid --details. Choose from: {', '.join(LINE_DETAILS)}.")
|
|
604
|
+
if payload.setdefault("group_by", "detailed") != "detailed":
|
|
605
|
+
raise ValueError("--details only applies to --group-by detailed.")
|
|
606
|
+
payload["line_details"] = items
|
|
607
|
+
return payload
|
|
608
|
+
|
|
609
|
+
|
|
575
610
|
@app.command("create")
|
|
576
611
|
def create_invoice(
|
|
577
612
|
client_id: str = typer.Option(..., "--client", "-c", help="Client ID."),
|
|
@@ -597,9 +632,8 @@ def create_invoice(
|
|
|
597
632
|
"its next unbilled payment; each payment is billed only once."
|
|
598
633
|
),
|
|
599
634
|
),
|
|
600
|
-
group_by: Optional[str] = typer.Option(
|
|
601
|
-
|
|
602
|
-
),
|
|
635
|
+
group_by: Optional[str] = typer.Option(None, "--group-by", "-g", help=GROUP_BY_HELP),
|
|
636
|
+
details: Optional[str] = typer.Option(None, "--details", help=DETAILS_HELP),
|
|
603
637
|
tax_rate: Optional[float] = typer.Option(
|
|
604
638
|
None, "--tax-rate", help="Tax rate percentage (e.g. 21 for 21%)."
|
|
605
639
|
),
|
|
@@ -634,6 +668,8 @@ def create_invoice(
|
|
|
634
668
|
Examples:
|
|
635
669
|
ct invoice create --client <id> --from 2026-03-01 --to 2026-03-31
|
|
636
670
|
ct invoice create --client <id> --period last-month --group-by project
|
|
671
|
+
ct invoice create --client <id> --period last-month --group-by person
|
|
672
|
+
ct invoice create --client <id> --period last-month --group-by detailed --details date,person,notes
|
|
637
673
|
ct invoice create --client <id> --period last-2-weeks --payment-terms net30
|
|
638
674
|
ct invoice create --client <id> --from monday --to friday --payment-terms 15
|
|
639
675
|
ct invoice create --client <id> --period last-month --due-date 2026-09-15
|
|
@@ -704,8 +740,11 @@ def create_invoice(
|
|
|
704
740
|
format_error("--payment needs the fixed-fee project selected with --project.")
|
|
705
741
|
raise typer.Exit(1)
|
|
706
742
|
payload["milestone_ids"] = list(payments)
|
|
707
|
-
|
|
708
|
-
payload
|
|
743
|
+
try:
|
|
744
|
+
payload.update(_display_payload(group_by, details))
|
|
745
|
+
except ValueError as e:
|
|
746
|
+
format_error(str(e))
|
|
747
|
+
raise typer.Exit(1)
|
|
709
748
|
if tax_rate is not None:
|
|
710
749
|
payload["tax_rate"] = str(tax_rate)
|
|
711
750
|
if notes:
|
|
@@ -1384,6 +1423,9 @@ def show_recurring(
|
|
|
1384
1423
|
console.print(f" Auto-send: {'Yes' if data.get('auto_send') else 'No'}")
|
|
1385
1424
|
console.print(f" Pull Entries: {'Yes' if data.get('pull_time_entries') else 'No'}")
|
|
1386
1425
|
console.print(f" Group By: {data.get('group_by', 'project')}")
|
|
1426
|
+
if data.get("group_by") == "detailed":
|
|
1427
|
+
shown = ", ".join(data.get("line_details") or ["person", "date", "notes"])
|
|
1428
|
+
console.print(f" Line Details: {shown}")
|
|
1387
1429
|
|
|
1388
1430
|
line_items = data.get("line_items", [])
|
|
1389
1431
|
if line_items:
|
|
@@ -1416,7 +1458,8 @@ def create_recurring(
|
|
|
1416
1458
|
payment_terms: Optional[int] = typer.Option(None, "--payment-terms", help="Payment terms in days."),
|
|
1417
1459
|
auto_send: bool = typer.Option(False, "--auto-send", help="Automatically send generated invoices."),
|
|
1418
1460
|
pull_entries: bool = typer.Option(True, "--pull-entries/--no-pull-entries", help="Pull time entries into invoice."),
|
|
1419
|
-
group_by: Optional[str] = typer.Option(None, "--group-by", "-g", help=
|
|
1461
|
+
group_by: Optional[str] = typer.Option(None, "--group-by", "-g", help=GROUP_BY_HELP),
|
|
1462
|
+
details: Optional[str] = typer.Option(None, "--details", help=DETAILS_HELP),
|
|
1420
1463
|
notes: Optional[str] = typer.Option(None, "--notes", help="Invoice notes."),
|
|
1421
1464
|
terms: Optional[str] = typer.Option(None, "--terms", help="Payment terms text."),
|
|
1422
1465
|
output_json: bool = typer.Option(False, "--json", help="Output as JSON."),
|
|
@@ -1442,8 +1485,11 @@ def create_recurring(
|
|
|
1442
1485
|
payload["payment_terms_days"] = payment_terms
|
|
1443
1486
|
if auto_send:
|
|
1444
1487
|
payload["auto_send"] = True
|
|
1445
|
-
|
|
1446
|
-
payload
|
|
1488
|
+
try:
|
|
1489
|
+
payload.update(_display_payload(group_by, details))
|
|
1490
|
+
except ValueError as e:
|
|
1491
|
+
format_error(str(e))
|
|
1492
|
+
raise typer.Exit(1)
|
|
1447
1493
|
if notes:
|
|
1448
1494
|
payload["notes"] = notes
|
|
1449
1495
|
if terms:
|
|
@@ -1474,7 +1520,8 @@ def update_recurring(
|
|
|
1474
1520
|
active: Optional[bool] = typer.Option(None, "--active/--inactive", help="Activate or deactivate."),
|
|
1475
1521
|
auto_send: Optional[bool] = typer.Option(None, "--auto-send/--no-auto-send", help="Auto-send invoices."),
|
|
1476
1522
|
payment_terms: Optional[int] = typer.Option(None, "--payment-terms", help="Payment terms in days."),
|
|
1477
|
-
group_by: Optional[str] = typer.Option(None, "--group-by", "-g", help=
|
|
1523
|
+
group_by: Optional[str] = typer.Option(None, "--group-by", "-g", help=GROUP_BY_HELP),
|
|
1524
|
+
details: Optional[str] = typer.Option(None, "--details", help=DETAILS_HELP),
|
|
1478
1525
|
notes: Optional[str] = typer.Option(None, "--notes", help="Invoice notes."),
|
|
1479
1526
|
output_json: bool = typer.Option(False, "--json", help="Output as JSON."),
|
|
1480
1527
|
) -> None:
|
|
@@ -1500,8 +1547,11 @@ def update_recurring(
|
|
|
1500
1547
|
payload["auto_send"] = auto_send
|
|
1501
1548
|
if payment_terms is not None:
|
|
1502
1549
|
payload["payment_terms_days"] = payment_terms
|
|
1503
|
-
|
|
1504
|
-
payload
|
|
1550
|
+
try:
|
|
1551
|
+
payload.update(_display_payload(group_by, details))
|
|
1552
|
+
except ValueError as e:
|
|
1553
|
+
format_error(str(e))
|
|
1554
|
+
raise typer.Exit(1)
|
|
1505
1555
|
if notes is not None:
|
|
1506
1556
|
payload["notes"] = notes
|
|
1507
1557
|
|
|
@@ -343,7 +343,8 @@ ct invoice aging # Overdue aging report: buckets 1-30d, 3
|
|
|
343
343
|
ct invoice aging --client <id> # Aging for a specific client
|
|
344
344
|
ct invoice show <id> # Invoice details with line items
|
|
345
345
|
ct invoice create --client <id> --period last-month --payment-terms net30 # From time entries
|
|
346
|
-
ct invoice create --client <id> --period last-month --group-by
|
|
346
|
+
ct invoice create --client <id> --period last-month --group-by person # One line per person on each project
|
|
347
|
+
ct invoice create --client <id> --period last-month --group-by detailed --details date,person,notes # One line per entry
|
|
347
348
|
ct invoice create-blank --client <id> --issue-date today --payment-terms net30 # Empty draft
|
|
348
349
|
ct invoice update <id> --terms "Wire to IBAN XX" --notes "March" # Edit draft fields
|
|
349
350
|
ct invoice update <id> --subject "April Dev" --currency EUR --tax-rate <id> # More fields
|
|
@@ -601,7 +602,7 @@ Read `references/commands.md` for the full reference of every command, subcomman
|
|
|
601
602
|
12. **Output formats** — `ct report` supports `table`, `json`, `csv`, and `markdown` via `--format`; suggest `csv` for spreadsheet export, `markdown` for docs
|
|
602
603
|
13. **Ask for details when vague** — if the user's request is ambiguous (e.g. "log 2 hours" with no description or project), ask them for the missing context rather than guessing. It's better to ask one clarifying question than to log something wrong that needs to be edited or deleted
|
|
603
604
|
14. **Expenses** — when the user mentions expenses, receipts, or purchases, use the `ct expense` commands. Always suggest a category and ask if the expense is billable. If recording a billable expense for a client project, always set `--project` and `--billable` so it gets included automatically when the client is invoiced
|
|
604
|
-
15. **Invoices include expenses** — when creating invoices with `ct invoice create --period`, billable expenses from the same period are automatically included as line items. Mention this to users so they know their expenses will appear on the invoice.
|
|
605
|
+
15. **Invoices include expenses** — when creating invoices with `ct invoice create --period`, billable expenses from the same period are automatically included as line items. Mention this to users so they know their expenses will appear on the invoice. Hours are shown per `--group-by`: `project`, `task` or `person` (one line each, per project, labelled with the period), `detailed` (one line per time entry; `--details` picks what each line shows from date, person, project, task, notes), `date`, or `none` (all on one line). Recurring templates take the same options. Line items support discounts (`--discount-type fixed|percent|hours --discount-value N`)
|
|
605
606
|
16. **Client contacts** — use `ct clients contacts` and `ct clients add-contact` to manage multiple contacts per client. Set `--primary` for the main point of contact. Use `--receives-invoices` to flag contacts who should receive invoice emails
|
|
606
607
|
17. **Permission errors are answers, not glitches** — the CLI now prints the server's reason on `403` (not your entry, already invoiced, no approval authority, read-only token, role too low) and on `400` validation errors (not assigned to the project, task not on the project). Relay the reason and the suggested alternative; do not retry the same command or look for another route to the same data. What each role can see is summarised under Team → Visibility rule and Organizations → Role hierarchy
|
|
607
608
|
18. **Rate confidentiality** — rates, budgets, amounts, invoices and retainers are manager+ only (see Projects). If a member, viewer or project manager asks about rates or billed amounts, tell them it's restricted to account managers instead of trying workarounds
|
|
@@ -2029,7 +2029,7 @@ Shows invoice details including line items, payments, and totals. Endpoint: `GET
|
|
|
2029
2029
|
### ct invoice create
|
|
2030
2030
|
|
|
2031
2031
|
```
|
|
2032
|
-
ct invoice create --client CLIENT --from DATE --to DATE [--period PERIOD] [--group-by GROUP] [--tax-rate RATE] [--payment-terms TERMS] [--issue-date DATE] [--due-date DATE] [--notes NOTES] [--terms TEXT] [--json]
|
|
2032
|
+
ct invoice create --client CLIENT --from DATE --to DATE [--period PERIOD] [--group-by GROUP] [--details LIST] [--tax-rate RATE] [--payment-terms TERMS] [--issue-date DATE] [--due-date DATE] [--notes NOTES] [--terms TEXT] [--json]
|
|
2033
2033
|
```
|
|
2034
2034
|
|
|
2035
2035
|
Creates an invoice from tracked time entries. Requires either `--from`/`--to` or `--period`.
|
|
@@ -2042,7 +2042,8 @@ Creates an invoice from tracked time entries. Requires either `--from`/`--to` or
|
|
|
2042
2042
|
| `--period` | string | Preset: `last-week`, `last-2-weeks`, `last-month`, `this-month` |
|
|
2043
2043
|
| `--project`, `-p` | string (repeatable) | Limit to specific project ID(s). **Required to bill a fixed-fee project** — those are never included in a client-wide invoice |
|
|
2044
2044
|
| `--payment` | string (repeatable) | One-off fixed-fee payment ID(s) to bill (from `ct projects show`). Without it, each selected one-off project bills its next unbilled payment |
|
|
2045
|
-
| `--group-by` | string |
|
|
2045
|
+
| `--group-by` | string | How to display hours: `project`, `task`, `person` (alias `user`) — one line each, per project, e.g. "Website: Ana Pérez (Oct 1 – Oct 31, 2026)"; `detailed` — one line per time entry; `date`; `none` — all on one line. Omitted: by project, or the project's billing mode when one project is billed |
|
|
2046
|
+
| `--details` | string | With `detailed`: comma-separated `date`, `person`, `project`, `task`, `notes` (default `person,date,notes`), e.g. "10/23/2026 – Ana Pérez: Signup form". Implies `--group-by detailed` |
|
|
2046
2047
|
| `--tax-rate` | float | Tax rate percentage (e.g. 21 for 21%) |
|
|
2047
2048
|
| `--payment-terms` | string | Payment terms: `receipt` (0 days), `net7`, `net15`, `net30`, or number of days. **Omit** to resolve from the waterfall below |
|
|
2048
2049
|
| `--issue-date` | string | Invoice date. Default: today |
|
|
@@ -2062,7 +2063,8 @@ Billable time entries and expenses from the period are automatically imported as
|
|
|
2062
2063
|
ct invoice create --client <id> --period last-month --payment-terms net30
|
|
2063
2064
|
ct invoice create --client <id> --from 2026-03-01 --to 2026-03-31
|
|
2064
2065
|
ct invoice create --client <id> --period last-2-weeks --group-by project
|
|
2065
|
-
ct invoice create --client <id> --period last-month --group-by
|
|
2066
|
+
ct invoice create --client <id> --period last-month --group-by person # One line per person on each project
|
|
2067
|
+
ct invoice create --client <id> --period last-month --group-by detailed --details date,task,notes # One line per entry
|
|
2066
2068
|
ct invoice create --client <id> --period last-month # Uses the client's own terms
|
|
2067
2069
|
ct invoice create --client <id> --period last-month --due-date 2026-09-15
|
|
2068
2070
|
ct invoice create --client <id> --period last-month --project <fixed-project-id> # Bills the next payment / one period
|
|
@@ -2203,7 +2205,8 @@ ct invoice recurring create --name NAME --client CLIENT_ID --schedule SCHEDULE -
|
|
|
2203
2205
|
| `--payment-terms` | integer | Payment terms in days |
|
|
2204
2206
|
| `--auto-send` | flag | Auto-send generated invoices |
|
|
2205
2207
|
| `--pull-entries/--no-pull-entries` | flag | Pull time entries (default: yes) |
|
|
2206
|
-
| `--group-by`, `-g` | string |
|
|
2208
|
+
| `--group-by`, `-g` | string | How to display hours: `project`, `task`, `person`, `detailed`, `date`, `none` (see `ct invoice create`) |
|
|
2209
|
+
| `--details` | string | With `detailed`: what each line shows (`date,person,project,task,notes`) |
|
|
2207
2210
|
| `--notes` | string | Invoice notes |
|
|
2208
2211
|
| `--terms` | string | Payment terms text |
|
|
2209
2212
|
| `--json` | flag | JSON output |
|
|
@@ -2224,7 +2227,8 @@ ct invoice recurring update TEMPLATE_ID [options]
|
|
|
2224
2227
|
| `--active/--inactive` | flag | Activate or deactivate |
|
|
2225
2228
|
| `--auto-send/--no-auto-send` | flag | Auto-send setting |
|
|
2226
2229
|
| `--payment-terms` | integer | Payment terms in days |
|
|
2227
|
-
| `--group-by`, `-g` | string |
|
|
2230
|
+
| `--group-by`, `-g` | string | How to display hours (see `ct invoice create`) |
|
|
2231
|
+
| `--details` | string | With `detailed`: what each line shows |
|
|
2228
2232
|
| `--notes` | string | Invoice notes |
|
|
2229
2233
|
| `--json` | flag | JSON output |
|
|
2230
2234
|
|
|
@@ -330,7 +330,7 @@ When a project uses per-person billing, grouping the invoice by user gives clien
|
|
|
330
330
|
|
|
331
331
|
```bash
|
|
332
332
|
# Create invoice grouped by team member
|
|
333
|
-
ct invoice create --client "Acme Corp" --period last-month --group-by
|
|
333
|
+
ct invoice create --client "Acme Corp" --period last-month --group-by person --payment-terms net30
|
|
334
334
|
|
|
335
335
|
# Add a line item with a discount (e.g. 2 hours courtesy)
|
|
336
336
|
ct invoice add-item <invoice-id> --desc "Extra support" --qty 10 --rate 150 --discount-type hours --discount-value 2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{crowdtime_cli-0.22.0 → crowdtime_cli-0.23.0}/src/crowdtime_cli/skills/crowdtime/references/pto.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|