Verifies that an approver can open the drawer, tick/untick PIBI
measures, save the selection, and that the POST to pibi-measures route
(which pushes measures_for_pibi_ordered to HubSpot) is intercepted with
the correct payload. Uses cy.intercept stubs for both GET and POST.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds PibiMeasureSelector component (issue #254) inside the drawer's
PIBI section. Approvers see a checkbox multi-select listing proposed +
instructed measures; approved measures are pre-ticked. Non-approvers
retain the existing read-only chip list. Saves via POST
/api/portfolio/[portfolioId]/pibi-measures and invalidates the query
cache on success.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds POST /api/portfolio/[portfolioId]/pibi-measures (approver-gated)
that accepts { dealId, measureNames[] } and delegates to
selectPibiMeasures. Also adds a GET handler that returns the current
pibi_ordered selection, approved measures, and instructed measures for
a deal — used by the drawer's PIBI selector to pre-populate.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements selectPibiMeasures (issue #254): replaces all pibi_ordered
rows for a deal, then pushes the new list to HubSpot under
measures_for_pibi_ordered via syncMeasuresFieldToHubSpot. Mirrors the
instruct-measure service; no approval rows touched.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Approver opens the drawer at the Measures section, picks a measure from
the catalogue dropdown, submits, and the spec asserts the optimistic
chip, the POST payload + response shape, and that the approval log
surfaces the new approval row.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Approver-only catalogue dropdown + submit button at the bottom of the
Measures section with optimistic chip rendering, error surfacing, and
the out-of-order soft warning when technical-approved measures already
exist on the deal.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Approver-only flow that records an instructed measure in
user_defined_deal_measures, auto-creates a deal_measure_approvals row +
event in a single tx, then pushes the instructed list to HubSpot under
instructed_measures. When the deal has no proposed measures and no prior
approvals, also pushes the new measure as proposed_measures so the deal
has a coherent starting point. Soft-warning helper surfaces the
out-of-order case for the drawer (and later slices).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Generic push for multi-value HubSpot deal properties (semicolon-separated)
with the same ECONNRESET retry pattern as pushDealPropertiesToHubSpot.
Returns a discriminated ok result so callers can stamp pushed_at only on
success. Slice 4 (PIBI selections) will reuse the same helper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Track instructed and pibi-ordered measures locally with a source enum,
created-by user, and HubSpot sync timestamps so issue #253 can persist
approver instructions and slice 4 can reuse the table for PIBI selections.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>