ucr: annual-renewal reminder campaign + order-alert campaign source
UCR (Unified Carrier Registration) is annual: opens Oct 1, due Dec 31, mandatory for interstate carriers (op A, same ~628k pool as IFTA) -> recurring revenue. - build_ucr_annual_campaign.py: 3-touch business-day cadence (30/12/4 bd before Dec 31, wider than IFTA since it's once a year), escalating tone, same-day coupon, 'I already did it' suppression. Reuses build_trucking_campaigns + IFTA business-day/token helpers (DRY). Per-year cycle reset. - ucr_annual_reminder.html: deadline + fines/OOS risk + 'we figure out your fee tier' + coupon + filed link + CAN-SPAM. Source campaign 473. - migration 096: ucr_reminded_at / ucr_touch_no / ucr_self_filed_at. - ifta.ts: add GET /api/v1/ucr/filed (shares the HMAC token scheme). - checkout.ts: order-placement Telegram now shows 'Source: campaign (code X)' when a discount code is present, so IFTA/UCR/CLIA conversions are visible. (Confirmed order-alert Telegram already fires from handlePaymentComplete for all compliance orders via both webhook + session paths.)
This commit is contained in:
parent
2b361a83a8
commit
a2665c22c2
5 changed files with 356 additions and 0 deletions
15
api/migrations/096_fmcsa_ucr_reminder.sql
Normal file
15
api/migrations/096_fmcsa_ucr_reminder.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
-- UCR annual-renewal reminder tracking (mirrors IFTA): per-carrier touch number,
|
||||
-- last-touch timestamp, and "I already did it" self-filed suppression.
|
||||
-- Reset each year by build_ucr_annual_campaign.py.
|
||||
-- ucr_reminded_at : timestamp of the most recent UCR touch
|
||||
-- ucr_touch_no : highest touch number sent this cycle (1=30bd,2=12bd,3=4bd)
|
||||
-- ucr_self_filed_at: clicked "I already registered" -> stop reminding this cycle
|
||||
|
||||
ALTER TABLE fmcsa_carriers
|
||||
ADD COLUMN IF NOT EXISTS ucr_reminded_at TIMESTAMPTZ,
|
||||
ADD COLUMN IF NOT EXISTS ucr_touch_no SMALLINT,
|
||||
ADD COLUMN IF NOT EXISTS ucr_self_filed_at TIMESTAMPTZ;
|
||||
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_fmcsa_carriers_ucr_touch
|
||||
ON fmcsa_carriers (ucr_touch_no)
|
||||
WHERE carrier_operation = 'A';
|
||||
|
|
@ -1735,11 +1735,18 @@ export async function handlePaymentComplete(
|
|||
const idLine = dotNumber ? `DOT#: ${dotNumber}\n`
|
||||
: frn ? `FRN: ${frn}\n`
|
||||
: "";
|
||||
// Campaign-source hint: an order carrying the daily campaign coupon (or any
|
||||
// discount code) almost certainly came from an email campaign. Surface it so
|
||||
// you can see the IFTA/UCR/CLIA/cold-email pipelines actually converting.
|
||||
const srcLine = order.discount_code
|
||||
? `Source: campaign (code ${order.discount_code})\n`
|
||||
: "";
|
||||
const msg = `💰 NEW ORDER\n\n`
|
||||
+ `Customer: ${customerName}\n`
|
||||
+ `Email: ${customerEmail}\n`
|
||||
+ idLine
|
||||
+ serviceLine
|
||||
+ srcLine
|
||||
+ subtotalLine
|
||||
+ discountLine
|
||||
+ surchargeLine
|
||||
|
|
|
|||
|
|
@ -82,4 +82,46 @@ router.get("/api/v1/ifta/filed", async (req, res) => {
|
|||
<a href="https://performancewest.net/order/ifta-quarterly" style="color:#0f766e;font-weight:700">See how it works →</a></p>`));
|
||||
});
|
||||
|
||||
/**
|
||||
* One-click "I already did it" for UCR annual reminders.
|
||||
* GET /api/v1/ucr/filed?dot=1234567&t=<token> (same HMAC token scheme as IFTA)
|
||||
*/
|
||||
router.get("/api/v1/ucr/filed", async (req, res) => {
|
||||
const dot = String(req.query.dot || "").trim();
|
||||
const token = String(req.query.t || "").trim();
|
||||
res.set("Content-Type", "text/html; charset=utf-8");
|
||||
|
||||
if (!dot || !token) {
|
||||
res.status(400).send(page("Invalid link",
|
||||
`<h2 style="color:#b91c1c">That link looks incomplete.</h2>
|
||||
<p style="color:#475569">If you already registered your UCR, you can ignore the reminders. Questions? Call (888) 411-0383.</p>`));
|
||||
return;
|
||||
}
|
||||
const expected = iftaFiledToken(dot); // shared token scheme
|
||||
const ok = token.length === expected.length
|
||||
&& crypto.timingSafeEqual(Buffer.from(token), Buffer.from(expected));
|
||||
if (!ok) {
|
||||
res.status(403).send(page("Invalid link",
|
||||
`<h2 style="color:#b91c1c">We couldn't verify that link.</h2>
|
||||
<p style="color:#475569">If you already registered your UCR, you can ignore the reminders. Questions? Call (888) 411-0383.</p>`));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await pool.query(
|
||||
`UPDATE fmcsa_carriers
|
||||
SET ucr_self_filed_at = COALESCE(ucr_self_filed_at, now())
|
||||
WHERE dot_number = $1`,
|
||||
[dot],
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("[ucr/filed] db error:", err);
|
||||
}
|
||||
res.send(page("Thanks - you're all set",
|
||||
`<h2 style="color:#0f766e">Got it - thanks for letting us know.</h2>
|
||||
<p style="color:#475569;line-height:1.6">We'll stop reminding you about this year's UCR for DOT #${dot}.
|
||||
We'll check back when next year's registration opens.</p>
|
||||
<p style="color:#475569;line-height:1.6">Want us to handle next year's UCR so you don't have to?
|
||||
<a href="https://performancewest.net/order/ucr-registration" style="color:#0f766e;font-weight:700">See how it works →</a></p>`));
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue