Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
f8cd37ac8c
1823 changed files with 145167 additions and 0 deletions
326
api/src/routes/formations.ts
Normal file
326
api/src/routes/formations.ts
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
import { Router } from "express";
|
||||
import { pool } from "../db.js";
|
||||
import { submitLimiter } from "../middleware/rate-limit.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { createFormationOrder } from "../erpnext-client.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/v1/states — Return all states with fees for the order form
|
||||
router.get("/api/v1/states", async (_req, res) => {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`SELECT state_code, state_name, llc_formation_fee, corp_formation_fee,
|
||||
llc_annual_fee, llc_annual_period, corp_annual_fee, corp_annual_period,
|
||||
expedited_fee, expedited_label, publication_required, publication_est_cost,
|
||||
franchise_tax_required, franchise_tax_min, franchise_tax_notes,
|
||||
business_license_required, business_license_fee,
|
||||
portal_name, online_filing_available, typical_processing_days, notes
|
||||
FROM state_filing_fees ORDER BY state_name`,
|
||||
);
|
||||
res.json({ states: result.rows });
|
||||
} catch (err) {
|
||||
console.error("[formations] Error fetching states:", err);
|
||||
res.status(500).json({ error: "Could not load state data." });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/v1/formations — Create a formation order
|
||||
router.post("/api/v1/formations", submitLimiter, async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
customer_name,
|
||||
customer_email,
|
||||
customer_phone,
|
||||
customer_company,
|
||||
state_code,
|
||||
entity_type,
|
||||
entity_name,
|
||||
entity_name_alt,
|
||||
management_type,
|
||||
purpose,
|
||||
principal_address,
|
||||
principal_city,
|
||||
principal_state,
|
||||
principal_zip,
|
||||
mailing_address,
|
||||
mailing_city,
|
||||
mailing_state,
|
||||
mailing_zip,
|
||||
members,
|
||||
include_ra_service,
|
||||
include_ein,
|
||||
include_operating_agreement,
|
||||
expedited,
|
||||
state_fee_cents,
|
||||
service_fee_cents,
|
||||
expedited_fee_cents,
|
||||
total_cents,
|
||||
discount_code,
|
||||
} = req.body ?? {};
|
||||
|
||||
// Validation
|
||||
if (
|
||||
!customer_name ||
|
||||
!customer_email ||
|
||||
!state_code ||
|
||||
!entity_type ||
|
||||
!entity_name
|
||||
) {
|
||||
res.status(400).json({
|
||||
error:
|
||||
"Missing required fields: name, email, state, entity type, entity name",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!["llc", "corporation", "s_corp"].includes(entity_type)) {
|
||||
res
|
||||
.status(400)
|
||||
.json({ error: "Entity type must be: llc, corporation, or s_corp" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!customer_email ||
|
||||
typeof customer_email !== "string" ||
|
||||
!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(customer_email)
|
||||
) {
|
||||
res.status(400).json({ error: "Valid email address is required." });
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Discount code validation ---
|
||||
let discountCents = 0;
|
||||
let validatedDiscountCode: string | null = null;
|
||||
let discountCodeId: number | null = null;
|
||||
let referralPayout = 0;
|
||||
|
||||
if (discount_code && typeof discount_code === "string" && discount_code.trim()) {
|
||||
const dc = discount_code.toUpperCase().trim();
|
||||
const dcResult = await pool.query("SELECT * FROM discount_codes WHERE code = $1", [dc]);
|
||||
|
||||
if (dcResult.rows.length > 0) {
|
||||
const row = dcResult.rows[0];
|
||||
const now = new Date();
|
||||
const isActive = row.active;
|
||||
const notExpired = !row.expires_at || new Date(row.expires_at) > now;
|
||||
const hasStarted = new Date(row.starts_at) <= now;
|
||||
const underLimit = row.max_uses === null || row.current_uses < row.max_uses;
|
||||
|
||||
// Check per-email limit
|
||||
let emailOk = true;
|
||||
if (customer_email && row.max_uses_per_email > 0) {
|
||||
const eu = await pool.query(
|
||||
"SELECT COUNT(*) as cnt FROM discount_usage WHERE code = $1 AND customer_email = $2",
|
||||
[dc, customer_email.toLowerCase().trim()],
|
||||
);
|
||||
emailOk = parseInt(eu.rows[0]?.cnt || "0", 10) < row.max_uses_per_email;
|
||||
}
|
||||
|
||||
// Check service scope
|
||||
let scopeOk = true;
|
||||
if (row.applies_to) {
|
||||
const allowed = row.applies_to.split(",").map((s: string) => s.trim().toLowerCase());
|
||||
scopeOk = allowed.includes("formation");
|
||||
}
|
||||
|
||||
if (isActive && notExpired && hasStarted && underLimit && emailOk && scopeOk) {
|
||||
validatedDiscountCode = dc;
|
||||
discountCodeId = row.id;
|
||||
|
||||
// Discount applies ONLY to our service fee — never to state filing fees,
|
||||
// expedited fees, or attorney review fees. Those are pass-through costs.
|
||||
const serviceFee = service_fee_cents || 17900;
|
||||
if (row.discount_type === "percent") {
|
||||
discountCents = Math.round((serviceFee * row.discount_value) / 100);
|
||||
} else {
|
||||
discountCents = Math.min(row.discount_value, serviceFee);
|
||||
}
|
||||
|
||||
// Referral payout based on service fee only (not state fees)
|
||||
if (row.referral_pct > 0) {
|
||||
referralPayout = Math.round((serviceFee * row.referral_pct) / 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Silently ignore invalid codes — don't block the order
|
||||
}
|
||||
|
||||
const finalServiceFee = (service_fee_cents || 17900) - discountCents;
|
||||
const finalTotal = (total_cents || 0) - discountCents;
|
||||
|
||||
const year = new Date().getFullYear();
|
||||
const short = uuidv4().split("-")[0]!.toUpperCase();
|
||||
const orderNumber = `PW-${year}-${short}`;
|
||||
|
||||
const principalFull = principal_address
|
||||
? `${principal_address}, ${principal_city}, ${principal_state} ${principal_zip}`
|
||||
: null;
|
||||
const mailingFull = mailing_address
|
||||
? `${mailing_address}, ${mailing_city}, ${mailing_state} ${mailing_zip}`
|
||||
: null;
|
||||
|
||||
const result = await pool.query(
|
||||
`INSERT INTO formation_orders (
|
||||
order_number, customer_name, customer_email, customer_phone, customer_company,
|
||||
state_code, entity_type, entity_name, entity_name_alt,
|
||||
management_type, principal_address, mailing_address,
|
||||
members_json, include_ra_service, include_ein, include_operating_agreement,
|
||||
expedited, state_fee_cents, service_fee_cents, expedited_fee_cents, total_cents,
|
||||
status
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,'received')
|
||||
RETURNING id, order_number`,
|
||||
[
|
||||
orderNumber,
|
||||
customer_name.trim(),
|
||||
customer_email.toLowerCase().trim(),
|
||||
customer_phone || null,
|
||||
customer_company || null,
|
||||
state_code.toUpperCase(),
|
||||
entity_type,
|
||||
entity_name.trim(),
|
||||
entity_name_alt || null,
|
||||
management_type || "member_managed",
|
||||
principalFull,
|
||||
mailingFull,
|
||||
JSON.stringify(members || []),
|
||||
include_ra_service !== false,
|
||||
include_ein || false,
|
||||
include_operating_agreement || false,
|
||||
expedited || false,
|
||||
state_fee_cents || 0,
|
||||
finalServiceFee,
|
||||
expedited_fee_cents || 0,
|
||||
finalTotal,
|
||||
],
|
||||
);
|
||||
|
||||
const orderId = result.rows[0].id;
|
||||
|
||||
// Push to ERPNext as source of truth — non-blocking, don't fail the response
|
||||
const ENTITY_TYPE_MAP: Record<string, "LLC" | "Corporation" | "S-Corp"> = {
|
||||
llc: "LLC",
|
||||
corporation: "Corporation",
|
||||
s_corp: "S-Corp",
|
||||
};
|
||||
const MGMT_TYPE_MAP: Record<string, "Member Managed" | "Manager Managed"> = {
|
||||
member_managed: "Member Managed",
|
||||
manager_managed: "Manager Managed",
|
||||
};
|
||||
|
||||
try {
|
||||
await createFormationOrder({
|
||||
order_number: orderNumber,
|
||||
customer: customer_name.trim(),
|
||||
customer_email: customer_email.toLowerCase().trim(),
|
||||
customer_phone: customer_phone || undefined,
|
||||
state_code: state_code.toUpperCase(),
|
||||
entity_type: ENTITY_TYPE_MAP[entity_type] || "LLC",
|
||||
entity_name: entity_name.trim(),
|
||||
entity_name_alt: entity_name_alt || undefined,
|
||||
management_type: MGMT_TYPE_MAP[management_type || "member_managed"] || "Member Managed",
|
||||
purpose: purpose || undefined,
|
||||
principal_address: principalFull || undefined,
|
||||
mailing_address: mailingFull || undefined,
|
||||
members: members || [],
|
||||
include_ra_service: include_ra_service !== false,
|
||||
include_ein: include_ein || false,
|
||||
include_operating_agreement: include_operating_agreement || false,
|
||||
expedited: expedited || false,
|
||||
state_fee_cents: state_fee_cents || 0,
|
||||
service_fee_cents: finalServiceFee,
|
||||
discount_code: validatedDiscountCode || undefined,
|
||||
discount_cents: discountCents > 0 ? discountCents : undefined,
|
||||
total_cents: finalTotal,
|
||||
});
|
||||
} catch (erpErr) {
|
||||
console.error("[formations] ERPNext createFormationOrder failed (non-fatal):", erpErr);
|
||||
}
|
||||
|
||||
// Record discount usage
|
||||
if (validatedDiscountCode && discountCodeId) {
|
||||
const ip = (req as any).clientIp || req.ip || "";
|
||||
await pool.query(
|
||||
`INSERT INTO discount_usage (discount_code_id, code, order_type, order_id, customer_email, discount_amount, referral_payout, ip_address)
|
||||
VALUES ($1, $2, 'formation', $3, $4, $5, $6, $7)`,
|
||||
[discountCodeId, validatedDiscountCode, orderId, customer_email.toLowerCase().trim(), discountCents, referralPayout, ip],
|
||||
);
|
||||
// Increment usage counter
|
||||
await pool.query(
|
||||
"UPDATE discount_codes SET current_uses = current_uses + 1, updated_at = now() WHERE id = $1",
|
||||
[discountCodeId],
|
||||
);
|
||||
}
|
||||
|
||||
// Create commission if this order used an agent's referral code
|
||||
if (discount_code) {
|
||||
try {
|
||||
const { createCommission } = await import("./agents.js");
|
||||
// Check if the discount code belongs to a sales agent
|
||||
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",
|
||||
[discount_code.toUpperCase()],
|
||||
);
|
||||
if (agentCheck.rows.length > 0) {
|
||||
await createCommission({
|
||||
agentCode: agentCheck.rows[0].agent_code,
|
||||
orderType: "formation",
|
||||
orderId: result.rows[0].id,
|
||||
orderNumber: result.rows[0].order_number,
|
||||
serviceSlug: "formation",
|
||||
customerName: customer_name,
|
||||
customerEmail: customer_email,
|
||||
orderAmountCents: finalTotal,
|
||||
discountCents: discountCents,
|
||||
});
|
||||
}
|
||||
} catch (commErr) {
|
||||
console.error("[formations] Commission creation failed (non-blocking):", commErr);
|
||||
}
|
||||
}
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
order_number: result.rows[0].order_number,
|
||||
message: "Formation order received. We will begin processing within one business day.",
|
||||
discount_applied: discountCents > 0 ? {
|
||||
code: validatedDiscountCode,
|
||||
discount_cents: discountCents,
|
||||
service_fee_after_discount: finalServiceFee,
|
||||
} : null,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("[formations] Error:", err);
|
||||
res
|
||||
.status(500)
|
||||
.json({ error: "Could not place your order. Please try again." });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/v1/formations/:orderNumber — Check order status
|
||||
router.get("/api/v1/formations/:orderNumber", async (req, res) => {
|
||||
try {
|
||||
const { orderNumber } = req.params;
|
||||
const result = await pool.query(
|
||||
`SELECT order_number, state_code, entity_type, entity_name, status,
|
||||
state_filing_number, filed_at, delivered_at, created_at
|
||||
FROM formation_orders WHERE order_number = $1`,
|
||||
[orderNumber],
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
res.status(404).json({ error: "Order not found" });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ order: result.rows[0] });
|
||||
} catch (err) {
|
||||
console.error("[formations] Error fetching order:", err);
|
||||
res
|
||||
.status(500)
|
||||
.json({ error: "Could not retrieve order. Please try again." });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue