Allow multiple referral codes per sales agent
Drop the UNIQUE constraint on sales_agents.email (migration 084) so a single agent (person/company) can hold several referral codes, each with its own client discount and commission split. All commission lookups already key on the unique agent_code, so no lookup logic changes. Agent-creation endpoint now: - accepts repeat emails (creates an additional code instead of 409) - accepts client_discount_value, commission_type, commission_pct per code - reports existing codes for the email in the response Both Jay Kordic codes (REF-JKORDIC 7%/12%, REF-JAYK05 5%/15%) now share his real email jay_kordic@thehorizongroup.biz.
This commit is contained in:
parent
53857574d3
commit
345979ed00
2 changed files with 57 additions and 15 deletions
|
|
@ -76,18 +76,30 @@ export async function createCommission(params: {
|
|||
// =====================================================================
|
||||
router.post("/api/v1/admin/agents", requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const { name, email, phone, company, commission_default_cents, commission_pct, commission_overrides, notes } = req.body ?? {};
|
||||
const {
|
||||
name, email, phone, company,
|
||||
commission_type, commission_default_cents, commission_pct, commission_overrides,
|
||||
client_discount_value, notes,
|
||||
} = req.body ?? {};
|
||||
if (!name || !email) {
|
||||
res.status(400).json({ error: "Name and email are required." });
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate email
|
||||
const existing = await pool.query("SELECT id FROM sales_agents WHERE email = $1", [email.toLowerCase().trim()]);
|
||||
if (existing.rows.length > 0) {
|
||||
res.status(409).json({ error: "An agent with this email already exists." });
|
||||
return;
|
||||
}
|
||||
// A single agent (person/company) may hold MULTIPLE referral codes, each with
|
||||
// its own client discount + commission split. We therefore allow repeat emails;
|
||||
// each call creates a new code. We surface any existing codes for the same email
|
||||
// in the response so the caller knows it's an additional code, not a mistake.
|
||||
const existing = await pool.query(
|
||||
"SELECT agent_code, commission_pct FROM sales_agents WHERE email = $1 ORDER BY created_at",
|
||||
[email.toLowerCase().trim()],
|
||||
);
|
||||
const existingCodes = existing.rows.map((r) => r.agent_code);
|
||||
|
||||
// Per-code config (defaults preserve prior behaviour: 5% client discount, 10% commission)
|
||||
const clientDiscount = client_discount_value !== undefined ? client_discount_value : 5;
|
||||
const commType = commission_type === "flat" ? "flat" : "percent";
|
||||
const commPct = commission_pct !== undefined ? commission_pct : 10;
|
||||
|
||||
// Generate unique agent code
|
||||
let agentCode = generateAgentCode();
|
||||
|
|
@ -99,22 +111,23 @@ router.post("/api/v1/admin/agents", requireAdmin, async (req, res) => {
|
|||
attempts++;
|
||||
}
|
||||
|
||||
// Create the linked discount code (5% off service fees)
|
||||
// Create the linked discount code (client discount off service fees;
|
||||
// referral_pct mirrors the agent commission for reporting).
|
||||
const dcResult = await pool.query(
|
||||
`INSERT INTO discount_codes (code, description, discount_type, discount_value, referral_partner, referral_email, referral_pct, active)
|
||||
VALUES ($1, $2, 'percent', 5, $3, $4, 0, TRUE)
|
||||
VALUES ($1, $2, 'percent', $3, $4, $5, $6, TRUE)
|
||||
RETURNING id`,
|
||||
[agentCode, `Sales agent: ${name}`, name, email.toLowerCase().trim()],
|
||||
[agentCode, `Sales agent: ${name}`, clientDiscount, name, email.toLowerCase().trim(), commType === "percent" ? commPct : 0],
|
||||
);
|
||||
const discountCodeId = dcResult.rows[0].id;
|
||||
|
||||
// Create the agent
|
||||
// Create the agent (one row per referral code)
|
||||
const result = await pool.query(
|
||||
`INSERT INTO sales_agents (agent_code, discount_code_id, name, email, phone, company, commission_default_cents, commission_pct, commission_overrides, notes, onboarded_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, now())
|
||||
`INSERT INTO sales_agents (agent_code, discount_code_id, name, email, phone, company, commission_type, commission_default_cents, commission_pct, commission_overrides, notes, onboarded_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, now())
|
||||
RETURNING id, agent_code`,
|
||||
[agentCode, discountCodeId, name, email.toLowerCase().trim(), phone || null, company || null,
|
||||
commission_default_cents || 30000, commission_pct || 10,
|
||||
commType, commission_default_cents || 30000, commPct,
|
||||
JSON.stringify(commission_overrides || {}), notes || null],
|
||||
);
|
||||
|
||||
|
|
@ -123,8 +136,14 @@ router.post("/api/v1/admin/agents", requireAdmin, async (req, res) => {
|
|||
success: true,
|
||||
agent_id: agent.id,
|
||||
agent_code: agent.agent_code,
|
||||
client_discount_value: clientDiscount,
|
||||
commission_type: commType,
|
||||
commission_pct: commType === "percent" ? commPct : undefined,
|
||||
existing_codes_for_email: existingCodes,
|
||||
referral_url: `https://performancewest.net/order/canada-crtc?code=${agent.agent_code}`,
|
||||
message: `Agent created. Referral code: ${agent.agent_code}. Client gets 5% off, agent earns commission per sale.`,
|
||||
message: existingCodes.length > 0
|
||||
? `Additional referral code created for ${email}. New code: ${agent.agent_code} (${clientDiscount}% client discount${commType === "percent" ? `, ${commPct}% commission` : ""}). This agent now has ${existingCodes.length + 1} codes.`
|
||||
: `Agent created. Referral code: ${agent.agent_code}. Client gets ${clientDiscount}% off, agent earns commission per sale.`,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[agents] Create error:", err);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue