Monitor Project Deadlines and Send Alerts
Missing deadlines costs client relationships. This script checks all active projects and tasks daily and sends an alert when anything is at risk.
The Script
python
#!/usr/bin/env python3
# deadline-monitor.py
import subprocess, json, datetime, urllib.request
SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
ALERT_DAYS = 7 # warn when deadline is within this many days
def ao(cmd):
r = subprocess.run(["ao"] + cmd.split() + ["--json"], capture_output=True, text=True)
return json.loads(r.stdout).get("data", [])
def slack(text: str):
data = json.dumps({"text": text}).encode()
urllib.request.urlopen(urllib.request.Request(
SLACK_WEBHOOK, data=data,
headers={"Content-Type": "application/json"}
))
today = datetime.date.today()
warnings = []
critical = []
# Check project deadlines
for proj in ao("projects list --status active"):
due = proj.get("due_date")
if not due:
continue
due_date = datetime.date.fromisoformat(due)
days = (due_date - today).days
name = proj["name"]
if days < 0:
critical.append(f":red_circle: *{name}* — OVERDUE by {-days} days (due {due})")
elif days <= ALERT_DAYS:
warnings.append(f":yellow_circle: *{name}* — due in {days} days ({due})")
# Check critical tasks
for proj in ao("projects list --status active"):
pid = proj["id"]
pname = proj["name"]
tasks = ao(f"projects task list {pid} --priority critical")
for task in tasks:
if task.get("status") in ("done", "cancelled"):
continue
due = task.get("due_date")
if due:
due_date = datetime.date.fromisoformat(due)
days = (due_date - today).days
if days < 0:
critical.append(f":red_circle: *[{pname}]* {task['title']} — OVERDUE by {-days} days")
elif days <= ALERT_DAYS:
warnings.append(f":yellow_circle: *[{pname}]* {task['title']} — due in {days} days")
# Send alerts
if not critical and not warnings:
print("All clear — no deadlines at risk.")
else:
lines = [f"*Deadline Monitor — {today}*"]
if critical:
lines.append("\n*OVERDUE:*")
lines.extend(critical)
if warnings:
lines.append(f"\n*Due within {ALERT_DAYS} days:*")
lines.extend(warnings)
message = "\n".join(lines)
print(message)
slack(message)
print(f"\nAlert sent: {len(critical)} overdue, {len(warnings)} upcoming")
Cron Schedule
bash
# Every morning at 7:30 AM
30 7 * * * python3 /path/to/deadline-monitor.py
Email Version
python
import smtplib
from email.mime.text import MIMEText
def email_alert(subject: str, body: str):
msg = MIMEText(body)
msg["Subject"] = subject
msg["From"] = "alerts@yourcompany.com"
msg["To"] = "team@yourcompany.com"
with smtplib.SMTP("smtp.gmail.com", 587) as s:
s.starttls()
s.login("alerts@yourcompany.com", "your-app-password")
s.send_message(msg)
if critical or warnings:
email_alert(
f"⚠️ Deadline Alert — {len(critical)} overdue, {len(warnings)} upcoming",
"\n".join(critical + warnings)
)
Extend: Check Invoices Too
python
# Add to the script
for inv in ao("invoice list --status overdue --limit 50"):
amount = inv.get("total_amount") or inv.get("amount") or 0
critical.append(f":moneybag: Invoice #{inv.get('invoice_number','?')} — ${amount:,.0f} overdue since {inv.get('due_date','?')} ")
Tip: Adjust ALERT_DAYS per project type — you might want 3 days for internal projects and 14 days for client-facing ones.