cctally 1.6.3 → 1.7.1

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.
@@ -0,0 +1,110 @@
1
+ """`cctally sync-week` subcommand entry point.
2
+
3
+ Lazy I/O sibling: holds the single entry-point function `cmd_sync_week`,
4
+ which loads config + selects the target subscription week +
5
+ JSONL-aggregates the week's cost + inserts a `weekly_cost_snapshots`
6
+ row + emits the success line (or `--json` envelope).
7
+
8
+ Every helper this command calls — `load_config`, `get_week_start_name`,
9
+ `open_db`, `pick_week_selection`, `compute_week_cost`,
10
+ `format_local_iso`, `insert_cost_snapshot`, `make_week_ref`,
11
+ `get_latest_usage_for_week` — stays in `bin/cctally` (they're shared
12
+ with the rest of the subcommand surface), reached via the `_cctally()`
13
+ call-time accessor (spec §5.2 / §5.5 pattern).
14
+
15
+ bin/cctally re-exports `cmd_sync_week` so the two non-extracted internal
16
+ callers (`cmd_record_usage`'s milestone-cost-sync path and the
17
+ `cmd_report` lazy-sync path) resolve via bare name unchanged.
18
+
19
+ Spec: docs/superpowers/specs/2026-05-13-bin-cctally-split-design.md
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import json
25
+ import sys
26
+
27
+
28
+ def _cctally():
29
+ """Resolve the current `cctally` module at call-time (spec §5.5)."""
30
+ return sys.modules["cctally"]
31
+
32
+
33
+ def cmd_sync_week(args: argparse.Namespace) -> int:
34
+ c = _cctally()
35
+ config = c.load_config()
36
+ week_start_name = c.get_week_start_name(config, args.week_start_name)
37
+
38
+ conn = c.open_db()
39
+ try:
40
+ selection = c.pick_week_selection(
41
+ conn,
42
+ args.week_start,
43
+ args.week_end,
44
+ week_start_name,
45
+ )
46
+ week_start = selection.week_start
47
+ week_end = selection.week_end
48
+ result = c.compute_week_cost(
49
+ week_start=week_start,
50
+ week_end=week_end,
51
+ mode=args.mode,
52
+ offline=args.offline,
53
+ project=args.project,
54
+ start_iso_override=selection.start_iso_override,
55
+ end_iso_override=selection.end_iso_override,
56
+ )
57
+ week_start_at = selection.start_iso_override or c.format_local_iso(week_start, end_of_day=False)
58
+ week_end_at = selection.end_iso_override or c.format_local_iso(week_end, end_of_day=True)
59
+ insert_id = c.insert_cost_snapshot(
60
+ conn,
61
+ week_start=week_start,
62
+ week_end=week_end,
63
+ week_start_at=week_start_at,
64
+ week_end_at=week_end_at,
65
+ range_start_iso=result.start_iso,
66
+ range_end_iso=result.end_iso,
67
+ cost_usd=result.cost_usd,
68
+ mode=args.mode,
69
+ project=args.project,
70
+ )
71
+
72
+ week_ref = c.make_week_ref(
73
+ week_start_date=week_start.isoformat(),
74
+ week_end_date=week_end.isoformat(),
75
+ week_start_at=week_start_at,
76
+ week_end_at=week_end_at,
77
+ )
78
+ usage_row = c.get_latest_usage_for_week(conn, week_ref)
79
+ weekly_percent = float(usage_row["weekly_percent"]) if usage_row else None
80
+ dollars_per_percent = (
81
+ result.cost_usd / weekly_percent if weekly_percent and weekly_percent > 0 else None
82
+ )
83
+
84
+ payload = {
85
+ "id": insert_id,
86
+ "weekStartDate": week_start.isoformat(),
87
+ "weekEndDate": week_end.isoformat(),
88
+ "weekStartAt": week_start_at,
89
+ "weekEndAt": week_end_at,
90
+ "rangeStartIso": result.start_iso,
91
+ "rangeEndIso": result.end_iso,
92
+ "costUSD": round(result.cost_usd, 9),
93
+ "weeklyPercent": weekly_percent,
94
+ "dollarsPerPercent": round(dollars_per_percent, 9) if dollars_per_percent is not None else None,
95
+ }
96
+
97
+ if args.json:
98
+ print(json.dumps(payload, indent=2))
99
+ elif not args.quiet:
100
+ print(
101
+ f"Synced week {payload['weekStartDate']}..{payload['weekEndDate']} "
102
+ f"=> ${payload['costUSD']:.6f}"
103
+ )
104
+ if weekly_percent is not None:
105
+ print(f"Latest weekly usage: {weekly_percent:.2f}%")
106
+ if dollars_per_percent is not None:
107
+ print(f"$ per 1% usage: ${dollars_per_percent:.6f}")
108
+ return 0
109
+ finally:
110
+ conn.close()