Add referral/discount code to FCC carrier page + REF-JAYK05 agent

Frontend (order/fcc-carrier-registration):
- Add a referral/discount code box on the review step that validates
  against /api/v1/discount/:code and shows the discount line + adjusted
  total. Discount applies to service fee + add-ons, never state filing fees.
- Prefill + auto-apply from ?code= / ?ref= query param (referral links).

Backend (fcc-carrier-registration route):
- Accept discount_code, validate it, store discount_code/discount_cents,
  and subtract from the total. Checkout already reads discount_cents to
  apply the Stripe coupon.
- Create a pending commission when the code belongs to an active sales agent.

Commission fix (agents.createCommission):
- Percent-type agents now earn commission_pct on ALL order types. Previously
  canada_crtc/formation/bundle used flat defaults and ignored percent agents.

Agent: created sales agent Jay Kordic (The Horizon Group) with custom code
REF-JAYK05 -> client gets 5% off discountable services, agent earns 15%.
Idempotent setup script in scripts/create_agent_jaykordic.cjs.
This commit is contained in:
justin 2026-06-02 14:31:22 -05:00
parent 1584a6692b
commit 53857574d3
4 changed files with 293 additions and 8 deletions

View file

@ -37,19 +37,23 @@ export async function createCommission(params: {
// Calculate commission amount
let commissionCents = agent.commission_default_cents || 30000; // $300 default
const overrides = agent.commission_overrides || {};
// Check for service-specific override
// Precedence:
// 1. Explicit per-service override (always wins, flat cents)
// 2. Percent-based agents earn commission_pct of the order on EVERY order type
// 3. Otherwise fall back to per-type flat defaults
if (params.serviceSlug && overrides[params.serviceSlug]) {
commissionCents = overrides[params.serviceSlug];
} else if (agent.commission_type === "percent") {
// Percent agents (e.g. referral partners on a flat % deal) get the same
// percentage regardless of order type. order_amount_cents is the total paid.
commissionCents = Math.round((params.orderAmountCents * (agent.commission_pct || 10)) / 100);
} else if (params.orderType === "canada_crtc") {
commissionCents = overrides["canada-crtc"] || 30000;
} else if (params.orderType === "formation") {
commissionCents = overrides["formation"] || 5000;
} else if (params.orderType === "bundle") {
commissionCents = overrides["bundle"] || 10000;
} else if (agent.commission_type === "percent") {
// For compliance services, use percentage
commissionCents = Math.round((params.orderAmountCents * (agent.commission_pct || 10)) / 100);
}
await pool.query(

View file

@ -51,6 +51,7 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
address_street, address_city, address_state, address_zip,
service_wizard, services,
engagement_accepted,
discount_code,
} = req.body ?? {};
// Validate required fields
@ -104,6 +105,53 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
if (includeOcn) addonFeeCents += OCN_FEE_CENTS;
const pucFeeCents = statePucStates.length * STATE_PUC_FEE_CENTS;
// ── Discount / referral code ──────────────────────────────────────────────
// Discounts apply to the Performance West service fee only. State filing fees
// (passed through at cost) are never discountable, matching the CRTC flow.
let discountCents = 0;
let normalizedDiscountCode: string | null = null;
if (discount_code && typeof discount_code === "string" && discount_code.trim().length >= 2) {
const code = discount_code.toUpperCase().trim();
try {
const dcResult = await pool.query(
"SELECT * FROM discount_codes WHERE code = $1",
[code],
);
if (dcResult.rows.length > 0) {
const dc = dcResult.rows[0];
const now = new Date();
const active = dc.active === true;
const notExpired = !dc.expires_at || new Date(dc.expires_at) >= now;
const started = !dc.starts_at || new Date(dc.starts_at) <= now;
const underGlobalLimit = dc.max_uses === null || dc.current_uses < dc.max_uses;
// Scope check: allow codes scoped to this service (or unscoped)
let inScope = true;
if (dc.applies_to) {
const allowed = String(dc.applies_to).split(",").map((s: string) => s.trim().toLowerCase());
inScope = allowed.includes("fcc_carrier_registration") || allowed.includes("all");
}
// Email allowlist check
let emailOk = true;
if (dc.allowed_emails && dc.allowed_emails.length > 0) {
const allowed = dc.allowed_emails.map((e: string) => e.toLowerCase());
emailOk = allowed.includes(customer_email.toLowerCase().trim());
}
if (active && notExpired && started && underGlobalLimit && inScope && emailOk) {
// Discountable base = service fee + add-ons (not state filing fees).
const discountable = BASE_FEE_CENTS + addonFeeCents;
if (dc.discount_type === "percent") {
discountCents = Math.round((discountable * dc.discount_value) / 100);
} else {
discountCents = Math.min(dc.discount_value, discountable);
}
normalizedDiscountCode = code;
}
}
} catch (dcErr) {
console.warn("[fcc-carrier-reg] Discount lookup failed (non-fatal):", dcErr);
}
}
const orderNumber = generateOrderNumber();
const result = await pool.query(
@ -118,11 +166,12 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
state_puc_states,
service_fee_cents, formation_fee_cents, state_fee_cents,
puc_fee_cents, addon_fee_cents,
discount_code, discount_cents,
engagement_accepted_at, engagement_accepted_ip
) VALUES (
$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,
$19::jsonb,$20,$21,$22,$23,$24,$25,$26,$27,$28::text[],
$29,$30,$31,$32,$33,$34,$35
$29,$30,$31,$32,$33,$34,$35,$36,$37
) RETURNING *`,
[
orderNumber,
@ -158,6 +207,8 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
stateFeeCents,
pucFeeCents,
addonFeeCents,
normalizedDiscountCode,
discountCents,
engagement_accepted ? new Date().toISOString() : null,
engagement_accepted ? (req.ip || req.headers["x-forwarded-for"] || null) : null,
],
@ -202,10 +253,38 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
}
}
const totalCents = BASE_FEE_CENTS + formationFeeCents + stateFeeCents + pucFeeCents + addonFeeCents;
const subtotalCents = BASE_FEE_CENTS + formationFeeCents + stateFeeCents + pucFeeCents + addonFeeCents;
const totalCents = Math.max(0, subtotalCents - discountCents);
// If this order used a sales agent's referral code, record a pending commission.
if (normalizedDiscountCode) {
try {
const agentCheck = await pool.query(
"SELECT sa.agent_code FROM sales_agents sa JOIN discount_codes dc ON sa.discount_code_id = dc.id WHERE dc.code = $1 AND sa.active = TRUE",
[normalizedDiscountCode],
);
if (agentCheck.rows.length > 0) {
const { createCommission } = await import("./agents.js");
await createCommission({
agentCode: agentCheck.rows[0].agent_code,
orderType: "fcc_carrier_registration",
orderId: order.id,
orderNumber: orderNumber,
serviceSlug: "fcc-carrier-registration",
customerName: customer_name.trim(),
customerEmail: customer_email.toLowerCase().trim(),
orderAmountCents: totalCents,
discountCents: discountCents,
});
}
} catch (commErr) {
console.warn("[fcc-carrier-reg] Commission creation failed (non-fatal):", commErr);
}
}
console.log(
`[fcc-carrier-reg] Created ${orderNumber}: ${entity_source} for ${customer_email}$${(totalCents / 100).toFixed(2)}`,
`[fcc-carrier-reg] Created ${orderNumber}: ${entity_source} for ${customer_email}$${(totalCents / 100).toFixed(2)}` +
(discountCents > 0 ? ` (discount ${normalizedDiscountCode} -$${(discountCents / 100).toFixed(2)})` : ""),
);
res.json({
@ -219,6 +298,9 @@ router.post("/api/v1/fcc-carrier-registration", async (req: Request, res: Respon
formation: formationFeeCents + stateFeeCents,
addons: addonFeeCents,
puc: pucFeeCents,
subtotal: subtotalCents,
discount_code: normalizedDiscountCode,
discount_cents: discountCents,
total: totalCents,
},
});