feat(advisor-branding P1): wire trip-order invoices to resolveBrand (letterhead brand, pinned TICO footer)#1476
Conversation
Advisor self-branding P1 — the invoice LETTERHEAD renders the acting advisor's brand (headline + logo); the FOOTER / TICO §38 fine-print ALWAYS renders the agency registrant (Phoenix + TICO#), non-overridable, regardless of tier. Ships LIVE but inert until an advisor has an active brand row (default tier='none' → agency headline = today's output). No migration; money boundary untouched. Wiring - getBusinessConfiguration(agencyId, advisorId?) resolves the brand via resolveBrand and bakes brand_headline/brand_logo_url/brand_color/brand_tier + advisor_user_id into BusinessConfiguration (frozen into the snapshot at finalize, so a reissue re-resolves the same brand + per-advisor template). Registrant fields (company_name/tico/address/phone/email) are LEFT UNTOUCHED. - Both context builders expose a `brand` key (letterhead) alongside the unchanged `agency` key (registrant); templates read brand.headline/logoUrl in the letterhead only. embedLogoAsBase64 now embeds the brand logo. - Live PDF + email + group-trip-order pass the advisor (trip.ownerId / bookingTrip.ownerId); manifest/rooming/checklist stay agency-only. Per-advisor template cascade (dormant → activated) - renderTripOrderPdf / renderTripOrderEmail / renderGroupPdf and DocumentTemplatesService.renderEmail now pass the acting advisor as the resolvePublishedTemplate userId, so a per-advisor published override wins the 3-tier cascade (user → agency → system). §38 validator - validateTICOCompliance now asserts the registrant (agency) legal name is present REGARDLESS of any brand headline (a DBA/personal invoice must still carry the agency legal name + TICO#). Existing checks unchanged. Tests (foreground) - trip-order.branding.render.spec.ts: unbranded → identical to today; personal → "X by Phoenix Voyages" + advisor logo, footer still Phoenix+TICO; DBA → bare DBA name + advisor logo, footer still Phoenix+TICO#50028032; registrant pinned across all tiers; group template branded/unbranded. - trip-order-tico-compliance.spec.ts: §38(6) registrant present for unbranded/personal/dba; flags a missing registrant name. - resolve-published-template.cascade.spec.ts: 3-tier precedence with userId. - Updated 6 group specs for the new brandingService constructor arg. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…odex r1) Codex gpt-5.5 xhigh r1 BLOCK — the newly activated per-advisor template cascade was not agency-scoped, so passing the advisor userId into a TICO §38 invoice render could let a cross-agency or stale user template override another agency's legal document. resolvePublishedTemplate Tier 1 (user-level) matched slug + userId + status only. Added eq(documentTemplates.agencyId, agencyId) so it FAILS CLOSED — a user template row always carries its agencyId (forkTemplate sets both), so this excludes any foreign-agency advisor template. Protects both the trip-order render path and the renderEmail agentId path. +2 regression specs: cross-agency user template is ignored (falls through to the agency template); structural guard that Tier 1's WHERE references agency_id. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Advisor Self-Branding P1 — invoices. Codex gpt-5.5 xhigh: APPROVE on 8b84281 (r1 BLOCK → r2 APPROVE). Builds on P0 (#1475, merged).
The invoice letterhead now renders the acting advisor's brand (headline + logo); the footer / TICO §38 fine-print ALWAYS renders the agency registrant (Phoenix + TICO#), non-overridable, regardless of tier. Ships LIVE but is effectively inert until an advisor has an active brand row — default
tier='none'→ agency headline = today's output (proven byte-identical by test).getBusinessConfiguration(agencyId, advisorId?)→resolveBrandbakesbrand_headline/logo/color/tier+advisor_user_idintoBusinessConfiguration(frozen into the snapshot at finalize; legacy snapshots fall back to the agency). Registrant fields left untouched. Both context builders expose abrandkey (letterhead) alongside the unchangedagencykey (registrant). Live PDF + email + group-trip-order brand by the trip/booking-trip owner; manifest/rooming/checklist stay agency-only.renderEmailpass the advisor as theresolvePublishedTemplateuserId, so a per-advisor published override wins the 3-tier cascade. Tier 1 is agency-scoped (Codex r1 fix) — a cross-agency/stale advisor template can never override another agency's legal invoice (fails closed).No migration. Money boundary untouched (no pricing/commission/totals/payment logic changed — Codex-confirmed). P2 (email header/from-name) consumes
resolveBrandnext.