new-site/site/src/components/intake/steps/Block6CertStep.astro
justin f8cd37ac8c 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>
2026-04-27 06:54:22 -05:00

242 lines
12 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
// Block6CertStep — Lines 603-605, 612 + de minimis election.
// Exemption certifications (USF/TRS/NANPA/LNP/ITSP), 501(c)/government,
// nondisclosure request, filing type, and the de minimis vs. regular
// election (with explainer).
import { NONDISCLOSURE_CERT_TEXT, FILING_TYPE_LABELS } from "../../../lib/fcc_constants";
import DeMinimisChoiceExplainer from "../DeMinimisChoiceExplainer.astro";
---
<div class="pw-step">
<h2>Certifications (Block 6)</h2>
<section class="pw-block" id="pw-demin-section">
<h3>De minimis filing election</h3>
<p class="pw-help">
Based on your revenue + safe-harbor interstate % and the current
year's de minimis factor, your estimated annual USF contribution is
<strong id="pw-demin-estimate">—</strong>. The exemption threshold
is $10,000 (Appendix A).
</p>
<div id="pw-demin-status-banner" class="pw-demin-banner" hidden></div>
<DeMinimisChoiceExplainer />
<label class="pw-field">How do you want to file?</label>
<select id="pw-demin-election" class="pw-input">
<option value="auto">Let the Appendix A calculation decide (standard)</option>
<option value="deminimis">File as de minimis — no USF contribution</option>
<option value="regular">File as regular contributor — pay USF directly (waive exemption)</option>
</select>
<div id="pw-waive-reason-wrap" hidden>
<label class="pw-field">Reason for filing regular (optional — shown to reviewers)</label>
<textarea id="pw-waive-reason" class="pw-input" rows="2"
placeholder="e.g., 'Wholesale SIP vendor charges us USF surcharge on trunking — filing regular so we can show Filer ID + reseller cert.'"></textarea>
</div>
</section>
<section class="pw-block">
<h3>Line 603 — Claim exemption from contribution mechanisms</h3>
<p class="pw-help">
Check any mechanism you're exempt from. Exemptions require a written
explanation and evidence your legal team can produce on audit.
</p>
<div class="pw-cert-grid">
<label><input type="checkbox" id="pw-ex-usf" /> USF (Universal Service Fund)</label>
<label><input type="checkbox" id="pw-ex-trs" /> TRS (Telecom Relay Service)</label>
<label><input type="checkbox" id="pw-ex-nanpa" /> NANPA (numbering)</label>
<label><input type="checkbox" id="pw-ex-lnp" /> LNP (number portability)</label>
<label><input type="checkbox" id="pw-ex-itsp" /> ITSP (regulatory fees)</label>
</div>
<div id="pw-ex-expl-wrap" hidden>
<label class="pw-field">Explanation (required for any exemption)</label>
<textarea id="pw-ex-expl" class="pw-input" rows="3"></textarea>
</div>
</section>
<section class="pw-block">
<h3>Line 604 — Organization type</h3>
<label><input type="checkbox" id="pw-gov" /> State or local government entity</label><br>
<label><input type="checkbox" id="pw-501c" /> 501(c) tax-exempt organization</label>
</section>
<section class="pw-block">
<h3>Line 605 — Confidential treatment of revenue data</h3>
<label>
<input type="checkbox" id="pw-nondisclosure" />
Request nondisclosure of revenue information
</label>
<p id="pw-nondisclosure-text" class="pw-cert-text" hidden></p>
</section>
<section class="pw-block">
<h3>Line 612 — Type of filing</h3>
<select id="pw-filing-type" class="pw-input">
<option value="original_april_1">Original Filing (April 1)</option>
<option value="registration_new_filer">Registration — New Filer</option>
<option value="revised_registration">Revised Filing (Registration Info)</option>
<option value="revised_revenue">Revised Filing (Revenue Info)</option>
</select>
</section>
<div id="pw-b6-err" class="pw-err" hidden></div>
</div>
<style>
.pw-step h2 { margin: 0 0 0.5rem; color: #1a2744; }
.pw-step h3 { margin: 0 0 0.4rem; color: #1a2744; font-size: 1rem; }
.pw-block { padding: 1rem; border: 1px solid #e2e8f0; border-radius: 8px; margin-bottom: 0.75rem; }
.pw-help { color: #64748b; font-size: 0.85rem; margin-bottom: 0.75rem; }
.pw-field { display: block; font-weight: 600; color: #1f2937; margin: 0.6rem 0 0.2rem; font-size: 0.88rem; }
.pw-input { width: 100%; padding: 0.5rem 0.7rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.93rem; font-family: inherit; }
.pw-demin-banner {
padding: 0.5rem 0.75rem; border-radius: 6px;
margin-top: 0.5rem; font-size: 0.88rem;
}
.pw-demin-banner.pw-exempt { background: #d1fae5; color: #065f46; border-left: 3px solid #059669; }
.pw-demin-banner.pw-no-exempt{ background: #fee2e2; color: #991b1b; border-left: 3px solid #dc2626; }
.pw-demin-banner.pw-near { background: #fef3c7; color: #92400e; border-left: 3px solid #d97706; }
.pw-cert-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.4rem; margin-bottom: 0.5rem; }
.pw-cert-grid label { font-size: 0.9rem; }
.pw-cert-text {
font-size: 0.82rem; color: #475569;
background: #f8fafc; padding: 0.5rem 0.75rem; border-radius: 6px;
margin-top: 0.5rem;
}
.pw-err { color: #b91c1c; margin-top: 0.75rem; font-size: 0.9rem; }
</style>
<script>
import { NONDISCLOSURE_CERT_TEXT } from "../../../lib/fcc_constants";
const exUsf = document.getElementById("pw-ex-usf") as HTMLInputElement;
const exTrs = document.getElementById("pw-ex-trs") as HTMLInputElement;
const exNanpa = document.getElementById("pw-ex-nanpa") as HTMLInputElement;
const exLnp = document.getElementById("pw-ex-lnp") as HTMLInputElement;
const exItsp = document.getElementById("pw-ex-itsp") as HTMLInputElement;
const exExplWrap = document.getElementById("pw-ex-expl-wrap") as HTMLElement;
const exExpl = document.getElementById("pw-ex-expl") as HTMLTextAreaElement;
const gov = document.getElementById("pw-gov") as HTMLInputElement;
const nfp = document.getElementById("pw-501c") as HTMLInputElement;
const nd = document.getElementById("pw-nondisclosure") as HTMLInputElement;
const ndText = document.getElementById("pw-nondisclosure-text") as HTMLElement;
const filingType = document.getElementById("pw-filing-type") as HTMLSelectElement;
const err = document.getElementById("pw-b6-err") as HTMLDivElement;
const deminElection = document.getElementById("pw-demin-election") as HTMLSelectElement;
const deminEstimate = document.getElementById("pw-demin-estimate") as HTMLElement;
const deminBanner = document.getElementById("pw-demin-status-banner") as HTMLElement;
const waiveReason = document.getElementById("pw-waive-reason") as HTMLTextAreaElement;
const waiveReasonWrap = document.getElementById("pw-waive-reason-wrap") as HTMLElement;
ndText.textContent = NONDISCLOSURE_CERT_TEXT;
async function refreshDeMinimisEstimate() {
const s = (window as any).PWIntake.get();
const year = Number(s.intake_data?.form_year) || new Date().getUTCFullYear() - 1;
const totalRev = Number(s.intake_data?.total_revenue_cents) || 0;
const interPct = Number(s.intake_data?.interstate_pct) || 0;
const intlPct = Number(s.intake_data?.international_pct) || 0;
if (!totalRev) {
deminEstimate.textContent = "— (enter revenue on the Revenue step first)";
deminBanner.hidden = true;
return;
}
// Quick estimate: contribution base × year factor. We fetch the
// factor via the late-filing-estimate endpoint (convenient wrapper).
try {
const r = await fetch(
`/api/v1/fcc/late-filing-estimate?year=${year}&total_revenue_cents=${totalRev}&interstate_pct=${interPct + intlPct}`,
);
if (!r.ok) throw new Error(`${r.status}`);
const data = await r.json();
const est = data.estimated_usf_cents;
const isExempt = est < 1000000; // $10,000 threshold
const nearThreshold = est < 1500000 && est >= 750000;
deminEstimate.textContent = `$${(est / 100).toLocaleString("en-US", { minimumFractionDigits: 2 })}`;
deminBanner.hidden = false;
if (isExempt) {
deminBanner.className = "pw-demin-banner pw-exempt";
deminBanner.textContent = `✓ You qualify as de minimis. Your estimated $${(est/100).toFixed(2)} annual contribution is below the $10,000 threshold.`;
} else if (nearThreshold) {
deminBanner.className = "pw-demin-banner pw-near";
deminBanner.textContent = `⚠ You're near the de minimis threshold. Small changes in interstate % could push you over — we recommend reviewing your traffic study carefully.`;
} else {
deminBanner.className = "pw-demin-banner pw-no-exempt";
deminBanner.textContent = `You do NOT qualify as de minimis. Estimated $${(est/100).toFixed(2)} exceeds the $10,000 threshold.`;
}
} catch {
deminEstimate.textContent = "— (could not reach server)";
}
}
deminElection.addEventListener("change", () => {
waiveReasonWrap.hidden = deminElection.value !== "regular";
});
function anyExempt() {
return exUsf.checked || exTrs.checked || exNanpa.checked || exLnp.checked || exItsp.checked;
}
function updateExplVisibility() {
exExplWrap.hidden = !anyExempt();
}
[exUsf, exTrs, exNanpa, exLnp, exItsp].forEach((cb) => cb.addEventListener("change", updateExplVisibility));
nd.addEventListener("change", () => { ndText.hidden = !nd.checked; });
window.addEventListener("pw:step-shown", (evt: any) => {
if (evt.detail.step !== "block6_cert") return;
const s = (window as any).PWIntake.get();
const d = s.intake_data || {};
exUsf.checked = !!d.exempt_usf;
exTrs.checked = !!d.exempt_trs;
exNanpa.checked = !!d.exempt_nanpa;
exLnp.checked = !!d.exempt_lnp;
exItsp.checked = !!d.exempt_itsp;
exExpl.value = d.exemption_explanation || "";
gov.checked = !!d.is_state_local_gov;
nfp.checked = !!d.is_tax_exempt_501c;
nd.checked = !!d.nondisclosure_requested;
filingType.value = d.filing_type || "original_april_1";
deminElection.value = d.deminimis_election || "auto";
waiveReasonWrap.hidden = deminElection.value !== "regular";
waiveReason.value = d.waive_deminimis_reason || "";
updateExplVisibility();
ndText.hidden = !nd.checked;
refreshDeMinimisEstimate();
});
window.addEventListener("pw:step-next", (evt: any) => {
const PW = (window as any).PWIntake;
if (PW.steps[PW.get().step_index] !== "block6_cert") return;
if (anyExempt() && !exExpl.value.trim()) {
err.hidden = false; err.textContent = "Exemption claims require a written explanation."; evt.preventDefault(); return;
}
err.hidden = true;
const election = deminElection.value;
PW.patchIntakeData({
exempt_usf: exUsf.checked,
exempt_trs: exTrs.checked,
exempt_nanpa: exNanpa.checked,
exempt_lnp: exLnp.checked,
exempt_itsp: exItsp.checked,
exemption_explanation: exExpl.value.trim() || null,
is_state_local_gov: gov.checked,
is_tax_exempt_501c: nfp.checked,
nondisclosure_requested: nd.checked,
filing_type: filingType.value,
deminimis_election: election,
// If the filer explicitly elected "regular", mark is_deminimis false
// and set the waive flag. If "deminimis", mark is_deminimis true.
// "auto" leaves is_deminimis to be set by the server-side calc.
is_deminimis: election === "regular" ? false : (election === "deminimis" ? true : undefined),
waive_deminimis_reason: election === "regular" ? (waiveReason.value.trim() || null) : null,
});
// Expose waive flag on the top-level state so order creation reads it.
const st = PW.get();
PW.set({
...st,
waive_deminimis_exemption: election === "regular",
waive_deminimis_reason: election === "regular" ? (waiveReason.value.trim() || null) : null,
});
});
</script>