2026-07-17 — XP-142 clone-academic-year drops COUNT wave
What shipped
Section titled “What shipped”packages/service/src/academic-years/clone-academic-year.tsrefactored: the 5count(*)selects (old step 2) plus a conditional re-fetch of the 4 amount tables (old step 4) and a secondsubject_tingkat_applicabilityfetch (old step 10) collapse into a single 5-tablePromise.all. Counts now come from.length. Net code deletion, one round-trip instead of three inside the money transaction.
Key decisions
Section titled “Key decisions”- Always fetch all 5 tables (empty tables return
[]) rather than the old count-then-maybe-fetch branching — simpler and one fewer round-trip;rowsCopiedderived from.lengthis byte-identical to the old COUNT-derived values (source row counts, pre-bump). - Wrapped the rewritten reads in
withQueryName(...)perservice-conventions.md(they had been unwrapped); tx mutations left as-is (apply-when-touching, not a sweep).
Gotchas / lessons
Section titled “Gotchas / lessons”- The 0-row guard UNIT test in
pricing/__tests__/pricing-guards.test.tswas implementation-coupled to the COUNT wave (its faketxqueued[{count:0}]per count select). The mock had to switch to returning row arrays (Array.from({length:n})) — same behavioural assertion, new fetch shape. - Empty-year guard reordered to run BEFORE the new-year INSERT (fetch → guard → create) so “reject empty before any write” is preserved.
Reference changes
Section titled “Reference changes”None. Clone semantics per domain-academic-year.md unchanged (5 tables, +1yr shift, UPCOMING, level axis carried) — only round-trip count dropped. No new academic-year fixture (integration-test-shared-fixtures trap #2 respected).