feat(uat-b1): ship Wave A-E of Bucket 1 audit findings
Wave A (Interest+EOI form quick wins): - Auto-select yacht after inline-create from interest form - EOI generate dialog: "View EOI" action toast - Interest form berth picker: formatBerthRange compact label - Remove "Generate EOI" button from Documents tab (clean removal) - Interest auto-assign: only sales_agent/sales_manager auto-claim ownership on create (explicit role check via user_port_roles join) - LinkedBerthRowItem dims: drop "D" suffix + "L × W" format - ExternalEoiUploadDialog: prefillSignatories prop threaded from active EOI signers - EOI signature progress on Overview milestone card footer Wave B (a11y + i18n sweeps): - aria-live on supplemental-info error state - text-[10px] -> text-xs in client-pipeline-summary - Currency formatter: locale default removed (Intl uses runtime) - en-US/en-GB hardcoded toLocaleString swept across 13 components Wave C (Primary berth always in EOI bundle): - Service guard strengthened on update path - Migration 0083 backfills historical primary rows Wave D (Onboarding super_admin discoverability): - /api/v1/admin/onboarding/status endpoint + shared service - Topbar OnboardingBanner (super_admin, session-dismissible) - OnboardingTile dashboard widget (rail group, self-hides at 100%) - Celebration toast + invalidate of shared status on last tick Wave E (Branded post-completion email idempotency): - Verified handleDocumentCompleted already owns the email fan-out - Added regression test for the polling path + idempotency Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -293,12 +293,23 @@ export async function upsertInterestBerthTx(
|
||||
if (opts.isInEoiBundle !== undefined) setForUpdate.isInEoiBundle = opts.isInEoiBundle;
|
||||
// Invariant: primary berth is ALWAYS in the EOI bundle. The primary IS
|
||||
// the canonical "berth for this deal" - excluding it from the signed
|
||||
// envelope is semantically nonsense. If the caller is setting the row
|
||||
// to primary OR opting to take out of the EOI bundle, force the bundle
|
||||
// flag back on whenever the row is also (about to be) primary.
|
||||
// envelope is semantically nonsense.
|
||||
// • If the caller is setting the row to primary + opting out of bundle,
|
||||
// force the bundle flag back on.
|
||||
// • If the existing row is already primary and the caller is toggling
|
||||
// the bundle off without changing primary, also force it back on.
|
||||
const willBePrimary = opts.isPrimary === true;
|
||||
if (willBePrimary && opts.isInEoiBundle === false) {
|
||||
setForUpdate.isInEoiBundle = true;
|
||||
} else if (opts.isInEoiBundle === false && opts.isPrimary !== false) {
|
||||
const existing = await tx
|
||||
.select({ isPrimary: interestBerths.isPrimary })
|
||||
.from(interestBerths)
|
||||
.where(and(eq(interestBerths.interestId, interestId), eq(interestBerths.berthId, berthId)))
|
||||
.limit(1);
|
||||
if (existing[0]?.isPrimary) {
|
||||
setForUpdate.isInEoiBundle = true;
|
||||
}
|
||||
}
|
||||
if (opts.addedBy !== undefined) setForUpdate.addedBy = opts.addedBy;
|
||||
if (opts.notes !== undefined) setForUpdate.notes = opts.notes;
|
||||
|
||||
Reference in New Issue
Block a user