Compare commits
2 commits
8d301a1ab7
...
9fa2c86f01
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa2c86f01 | ||
|
|
3dbf5b3bb2 |
3 changed files with 63 additions and 2 deletions
|
|
@ -1,3 +1,6 @@
|
|||
# NOTE: logs go to /opt/performancewest/logs/ (deploy-owned). The deploy user
|
||||
# cannot write /var/log, so a /var/log redirect makes cron silently fail before
|
||||
# the command runs. Ensure /opt/performancewest/logs exists + is deploy-owned.
|
||||
# Healthcare warmup: import the next slice across ALL active segments
|
||||
# (revalidation, OIG screening, NPPES, reactivation, bundle) into listmonk-hc
|
||||
# and keep each campaign running. Mon-Fri only, 7 AM Central (host TZ =
|
||||
|
|
@ -7,4 +10,4 @@
|
|||
# Deliverability guard: warmup only mails SLIGHTLY-overdue providers (1-90 days
|
||||
# by default, HC_OVERDUE_MIN/MAX) -- recently-lapsed practices still have live
|
||||
# inboxes; heavily-overdue ones likely bounce and burn the warming IPs.
|
||||
0 7 * * 1-5 deploy cd /opt/performancewest && HC_VERIFIED_CSV=/opt/performancewest/data/hc_warmup_nongoogle.csv python3 scripts/build_healthcare_campaigns_cron.py --start-campaign >> /var/log/pw-hc-campaign.log 2>&1
|
||||
0 7 * * 1-5 deploy cd /opt/performancewest && HC_VERIFIED_CSV=/opt/performancewest/data/hc_warmup_nongoogle.csv python3 scripts/build_healthcare_campaigns_cron.py --start-campaign >> /opt/performancewest/logs/pw-hc-campaign.log 2>&1
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# NOTE: logs go to /opt/performancewest/logs/ (deploy-owned). The deploy user
|
||||
# cannot write /var/log, so a /var/log redirect makes cron silently fail before
|
||||
# the command runs. Ensure /opt/performancewest/logs exists + is deploy-owned.
|
||||
# Healthcare data refresh: re-check every emailable NPI against the live
|
||||
# government sources (CMS Revalidation list, OIG LEIE) + MX re-classification
|
||||
# (Google-host detection) so warmup sends never go stale. Runs Mon/Wed/Fri 06:00
|
||||
|
|
@ -7,4 +10,4 @@
|
|||
# Takes ~8 min. SAM is opt-in (--sam-pages); SAM exclusions rarely carry an NPI,
|
||||
# so OIG LEIE is the NPI-bearing exclusion source. Then prune-only removes newly-
|
||||
# Google-hosted and suppressed subscribers from the warmup lists.
|
||||
0 6 * * 1,3,5 deploy cd /opt/performancewest && python3 -u scripts/hc_data_refresh.py >> /var/log/pw-hc-refresh.log 2>&1 && python3 -u scripts/build_healthcare_campaigns_cron.py --prune-only >> /var/log/pw-hc-refresh.log 2>&1
|
||||
0 6 * * 1,3,5 deploy cd /opt/performancewest && python3 -u scripts/hc_data_refresh.py >> /opt/performancewest/logs/pw-hc-refresh.log 2>&1 && python3 -u scripts/build_healthcare_campaigns_cron.py --prune-only >> /opt/performancewest/logs/pw-hc-refresh.log 2>&1
|
||||
|
|
|
|||
55
scripts/rescue-mitchell-email.mjs
Normal file
55
scripts/rescue-mitchell-email.mjs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Send Mitchell Allen his portal password-set link + a note that his e-sign
|
||||
* authorization emails are now on the way (after the SMTP fix). CC justin.
|
||||
* Run: docker exec performancewest-api-1 node /app/scripts/rescue-mitchell-email.mjs
|
||||
*/
|
||||
import pg from "pg";
|
||||
import crypto from "crypto";
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
const EMAIL = "mitchell@allenscrapmetal.com";
|
||||
const CC = "justin@performancewest.net";
|
||||
const SITE = process.env.DOMAIN ? `https://${process.env.DOMAIN}` : "https://performancewest.net";
|
||||
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
|
||||
const mailer = nodemailer.createTransport({
|
||||
host: process.env.SMTP_HOST || "co.carrierone.com",
|
||||
port: parseInt(process.env.SMTP_PORT || "587", 10),
|
||||
secure: false,
|
||||
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
|
||||
});
|
||||
const FROM = process.env.SMTP_FROM || "Performance West <noreply@performancewest.net>";
|
||||
|
||||
const cust = await pool.query(`SELECT id, name FROM customers WHERE email=$1`, [EMAIL]);
|
||||
if (!cust.rows.length) { console.log("no customers row for", EMAIL); process.exit(1); }
|
||||
const customer = cust.rows[0];
|
||||
const firstName = (customer.name || "there").split(" ")[0];
|
||||
|
||||
const { rows: orders } = await pool.query(
|
||||
`SELECT order_number, service_name FROM compliance_orders WHERE customer_email=$1 ORDER BY created_at`, [EMAIL]);
|
||||
|
||||
const token = crypto.randomBytes(32).toString("hex");
|
||||
await pool.query(
|
||||
`INSERT INTO password_reset_tokens (customer_id, token, expires_at) VALUES ($1,$2,$3)`,
|
||||
[customer.id, token, new Date(Date.now() + 60 * 60 * 1000)],
|
||||
);
|
||||
const resetLink = `${SITE}/account/reset-password?token=${token}`;
|
||||
const orderList = orders.map(o => `<li style="margin:4px 0">${o.service_name} <span style="color:#888;font-family:monospace">(${o.order_number})</span></li>`).join("");
|
||||
|
||||
await mailer.sendMail({
|
||||
from: FROM, to: EMAIL, cc: CC,
|
||||
subject: "Your Performance West login + signature requests are on the way",
|
||||
html: `<div style="font-family:Arial,sans-serif;max-width:560px;margin:0 auto;padding:24px;color:#222">
|
||||
<h2 style="color:#1a2744;margin:0 0 8px">You're all set, ${firstName}</h2>
|
||||
<p>Thanks for your order. We had a delivery issue that kept our earlier emails from reaching you - that's fixed now, so here is everything you need.</p>
|
||||
<p style="margin:18px 0 6px"><strong>1. Set your password to log in</strong> (expires in 60 minutes):</p>
|
||||
<p style="margin:6px 0 18px"><a href="${resetLink}" style="background:#2d4e78;color:#fff;padding:12px 28px;border-radius:8px;text-decoration:none;font-weight:600">Set my password →</a></p>
|
||||
<p style="font-size:13px;color:#666;margin:0 0 18px">Or paste this link: ${resetLink}</p>
|
||||
<p style="margin:18px 0 6px"><strong>2. Sign your authorizations.</strong> We're sending you a separate signature request for each filing below. Each filing begins once you sign it - for the MCS-150 and USDOT reactivation we prepare the form and you review/sign before we submit to FMCSA.</p>
|
||||
<ul style="padding-left:18px">${orderList}</ul>
|
||||
<p style="font-size:13px;color:#666">You can also track everything in your portal once you log in. Questions? Reply here or call 1-888-411-0383.</p>
|
||||
<p style="font-size:12px;color:#9ca3af">Performance West Inc. · performancewest.net · 1-888-411-0383</p>
|
||||
</div>`,
|
||||
text: `Hi ${firstName}, set your password to log in: ${resetLink} (expires 60 min). You'll also receive a signature request for each filing: ${orders.map(o => o.service_name + " (" + o.order_number + ")").join("; ")}. Each filing begins once you sign. Questions? 1-888-411-0383.`,
|
||||
});
|
||||
console.log(`[rescue] login + signature note sent to ${EMAIL} (cc ${CC}) for ${orders.length} orders`);
|
||||
await pool.end();
|
||||
Loading…
Add table
Add a link
Reference in a new issue