Mark a single leg as DNP and return the new bet shape (legs + multiplier
potential payout). Pure: caller persists the result.
Mirrors bet-service.ts:markLegDnp's transition logic so the Deno
settlement watcher's pre-game DNP path produces the same column writes
as the RN UI's manual DNP override. The actual void column values
(status='void', actual_payout=stake, etc.) are applied by the caller
when isVoided=true — see bet-service.ts:399-433.
MAINTAINED PAIR: applyLegDnp (this file, used by the Deno watcher) and
markLegDnp (bet-service.ts, used by the RN UI) implement the same
transition twice. Future cleanup: extract computeDnpTransition that
returns the full intended column-write object so both call sites
collapse to thin transport wrappers. The void-branch contract pin in
tests/unit/lib/dfs-pregame-dnp.test.ts catches drift between the two.
KNOWN LIMITATION: passing currentMultiplier (post-prior-DNP) instead
of the slip's original placed multiplier is mathematically equivalent
by chain rule — recalc results match across multi-DNP modulo 4-decimal
rounding. The semantic loss is the link back to slip-at-placement,
which becomes load-bearing for Wave 4 G.write (stat-correction reversal
needs to recompute from original) and dispute explainability. Fix:
persist slip_original_multiplier at create time, immutable; multiplier
remains current state. Deferred until reconciliation forces the issue.
Idempotency: if the target leg is already 'dnp', returns alreadyDnp=true
and the caller should skip writes.
Caller is responsible for:
Re-asserting bet status='pending' in the WHERE clause to guard
against manual-override races.
Mark a single leg as DNP and return the new bet shape (legs + multiplier
Mirrors bet-service.ts:markLegDnp's transition logic so the Deno settlement watcher's pre-game DNP path produces the same column writes as the RN UI's manual DNP override. The actual void column values (status='void', actual_payout=stake, etc.) are applied by the caller when isVoided=true — see bet-service.ts:399-433.
MAINTAINED PAIR: applyLegDnp (this file, used by the Deno watcher) and markLegDnp (bet-service.ts, used by the RN UI) implement the same transition twice. Future cleanup: extract computeDnpTransition that returns the full intended column-write object so both call sites collapse to thin transport wrappers. The void-branch contract pin in tests/unit/lib/dfs-pregame-dnp.test.ts catches drift between the two.
KNOWN LIMITATION: passing currentMultiplier (post-prior-DNP) instead of the slip's original placed multiplier is mathematically equivalent by chain rule — recalc results match across multi-DNP modulo 4-decimal rounding. The semantic loss is the link back to slip-at-placement, which becomes load-bearing for Wave 4 G.write (stat-correction reversal needs to recompute from original) and dispute explainability. Fix: persist slip_original_multiplier at create time, immutable; multiplier remains current state. Deferred until reconciliation forces the issue.
Idempotency: if the target leg is already 'dnp', returns alreadyDnp=true and the caller should skip writes.
Caller is responsible for: