botserver/templates/sales/attendance-crm.gbai/attendance-crm.gbdialog/crm-automations.bas

462 lines
18 KiB
QBasic
Raw Normal View History

REM CRM Automations - Follow-ups, Collections, Lead Nurturing, Sales Pipeline
REM Scheduled jobs that run automatically to handle common CRM workflows.
REM Uses the new attendance keywords for queue integration.
REM
REM Schedules:
REM SET SCHEDULE "follow-ups", "0 9 * * 1-5" (9am weekdays)
REM SET SCHEDULE "collections", "0 8 * * 1-5" (8am weekdays)
REM SET SCHEDULE "lead-nurture", "0 10 * * 1-5" (10am weekdays)
REM SET SCHEDULE "pipeline-review", "0 14 * * 5" (2pm Fridays)
PARAM job_name AS STRING LIKE "follow-ups" DESCRIPTION "Job to run: follow-ups, collections, lead-nurture, pipeline-review, all"
DESCRIPTION "Automated CRM workflows for follow-ups, collections, lead nurturing, and pipeline management"
PRINT "=== CRM Automations Starting: " + job_name + " ==="
PRINT "Time: " + FORMAT(NOW(), "yyyy-MM-dd HH:mm:ss")
results = {}
results.job = job_name
results.started_at = NOW()
results.actions = []
' =====================================================================
' FOLLOW-UPS - Automated follow-up sequences
' =====================================================================
IF job_name = "follow-ups" OR job_name = "all" THEN
PRINT ""
PRINT "--- Running Follow-ups ---"
' 1-day follow-up: Thank you message for new leads
leads_1_day = FIND "leads", "status='new' AND DATEDIFF(NOW(), created_at) = 1"
PRINT "1-day follow-ups: " + UBOUND(leads_1_day)
FOR EACH lead IN leads_1_day
' Send thank you message
IF lead.phone IS NOT NULL THEN
SEND TEMPLATE lead.phone, "follow_up_thanks", {
"name": lead.name,
"interest": lead.interest OR "our services"
}
END IF
IF lead.email IS NOT NULL THEN
SEND MAIL lead.email, "Obrigado pelo seu interesse!", "Olá " + lead.name + ",\n\nObrigado por entrar em contato conosco. Estamos à disposição para ajudá-lo.\n\nAtenciosamente,\nEquipe de Vendas"
END IF
' Update lead status
UPDATE "leads", "id='" + lead.id + "'", {
"status": "contacted",
"last_contact": NOW(),
"follow_up_1_sent": NOW()
}
' Log activity
SAVE "activities", {
"type": "follow_up",
"lead_id": lead.id,
"description": "1-day thank you sent",
"created_at": NOW()
}
APPEND results.actions, {"type": "follow_up_1", "lead": lead.name}
NEXT
' 3-day follow-up: Value proposition
leads_3_day = FIND "leads", "status='contacted' AND DATEDIFF(NOW(), last_contact) = 3 AND follow_up_3_sent IS NULL"
PRINT "3-day follow-ups: " + UBOUND(leads_3_day)
FOR EACH lead IN leads_3_day
IF lead.phone IS NOT NULL THEN
SEND TEMPLATE lead.phone, "follow_up_value", {
"name": lead.name,
"interest": lead.interest OR "our services"
}
END IF
UPDATE "leads", "id='" + lead.id + "'", {
"last_contact": NOW(),
"follow_up_3_sent": NOW()
}
SAVE "activities", {
"type": "follow_up",
"lead_id": lead.id,
"description": "3-day value proposition sent",
"created_at": NOW()
}
APPEND results.actions, {"type": "follow_up_3", "lead": lead.name}
NEXT
' 7-day follow-up: Special offer for hot leads
leads_7_day = FIND "leads", "status IN ('contacted', 'nurturing') AND DATEDIFF(NOW(), last_contact) = 7 AND follow_up_7_sent IS NULL AND score >= 50"
PRINT "7-day follow-ups: " + UBOUND(leads_7_day)
FOR EACH lead IN leads_7_day
IF lead.phone IS NOT NULL THEN
SEND TEMPLATE lead.phone, "follow_up_offer", {
"name": lead.name,
"discount": "10%"
}
END IF
UPDATE "leads", "id='" + lead.id + "'", {
"status": "offer_sent",
"last_contact": NOW(),
"follow_up_7_sent": NOW()
}
' Alert sales for hot leads
IF lead.score >= 70 THEN
attendants = GET ATTENDANTS "online"
FOR EACH att IN attendants.items
IF att.department = "commercial" OR att.preferences CONTAINS "sales" THEN
SEND MAIL att.email, "🔥 Hot Lead Follow-up: " + lead.name, "Lead " + lead.name + " recebeu oferta de 7 dias.\nScore: " + lead.score + "\nTelefone: " + lead.phone + "\n\nRecomendado: Entrar em contato nas próximas 24h."
END IF
NEXT
END IF
APPEND results.actions, {"type": "follow_up_7", "lead": lead.name, "score": lead.score}
NEXT
results.follow_ups_completed = UBOUND(leads_1_day) + UBOUND(leads_3_day) + UBOUND(leads_7_day)
PRINT "Follow-ups completed: " + results.follow_ups_completed
END IF
' =====================================================================
' COLLECTIONS - Automated payment reminders (Cobranças)
' =====================================================================
IF job_name = "collections" OR job_name = "all" THEN
PRINT ""
PRINT "--- Running Collections ---"
' Due today: Friendly reminder
due_today = FIND "invoices", "status='pending' AND due_date = CURDATE()"
PRINT "Due today: " + UBOUND(due_today)
FOR EACH invoice IN due_today
customer = FIND "customers", "id='" + invoice.customer_id + "'"
IF customer.phone IS NOT NULL THEN
SEND TEMPLATE customer.phone, "payment_due_today", {
"name": customer.name,
"invoice_id": invoice.id,
"amount": FORMAT(invoice.amount, "R$ #,##0.00")
}
END IF
SAVE "collection_log", {
"invoice_id": invoice.id,
"action": "reminder_due_today",
"created_at": NOW()
}
APPEND results.actions, {"type": "payment_reminder", "customer": customer.name, "days": 0}
NEXT
' 3 days overdue: First notice
overdue_3 = FIND "invoices", "status='pending' AND DATEDIFF(NOW(), due_date) = 3"
PRINT "3 days overdue: " + UBOUND(overdue_3)
FOR EACH invoice IN overdue_3
customer = FIND "customers", "id='" + invoice.customer_id + "'"
IF customer.phone IS NOT NULL THEN
SEND TEMPLATE customer.phone, "payment_overdue_3", {
"name": customer.name,
"invoice_id": invoice.id,
"amount": FORMAT(invoice.amount, "R$ #,##0.00")
}
END IF
IF customer.email IS NOT NULL THEN
SEND MAIL customer.email, "Pagamento Pendente - Fatura #" + invoice.id, "Prezado(a) " + customer.name + ",\n\nSua fatura #" + invoice.id + " no valor de R$ " + invoice.amount + " está vencida há 3 dias.\n\nPor favor, regularize o pagamento para evitar encargos adicionais.\n\nEm caso de dúvidas, entre em contato conosco.\n\nAtenciosamente,\nDepartamento Financeiro"
END IF
UPDATE "invoices", "id='" + invoice.id + "'", {
"first_notice_sent": NOW()
}
SAVE "collection_log", {
"invoice_id": invoice.id,
"action": "first_notice",
"created_at": NOW()
}
APPEND results.actions, {"type": "collection_notice_1", "customer": customer.name}
NEXT
' 7 days overdue: Second notice with urgency
overdue_7 = FIND "invoices", "status='pending' AND DATEDIFF(NOW(), due_date) = 7"
PRINT "7 days overdue: " + UBOUND(overdue_7)
FOR EACH invoice IN overdue_7
customer = FIND "customers", "id='" + invoice.customer_id + "'"
IF customer.phone IS NOT NULL THEN
SEND TEMPLATE customer.phone, "payment_overdue_7", {
"name": customer.name,
"invoice_id": invoice.id,
"amount": FORMAT(invoice.amount, "R$ #,##0.00")
}
END IF
UPDATE "invoices", "id='" + invoice.id + "'", {
"second_notice_sent": NOW()
}
' Notify collections team
SEND MAIL "cobranca@company.com", "Cobrança 7 dias: " + customer.name, "Cliente: " + customer.name + "\nFatura: " + invoice.id + "\nValor: R$ " + invoice.amount + "\nTelefone: " + customer.phone
SAVE "collection_log", {
"invoice_id": invoice.id,
"action": "second_notice",
"created_at": NOW()
}
APPEND results.actions, {"type": "collection_notice_2", "customer": customer.name}
NEXT
' 15 days overdue: Final notice + queue for human call
overdue_15 = FIND "invoices", "status='pending' AND DATEDIFF(NOW(), due_date) = 15"
PRINT "15 days overdue: " + UBOUND(overdue_15)
FOR EACH invoice IN overdue_15
customer = FIND "customers", "id='" + invoice.customer_id + "'"
' Calculate late fees
late_fee = invoice.amount * 0.02
interest = invoice.amount * 0.01 * 15
total_due = invoice.amount + late_fee + interest
IF customer.phone IS NOT NULL THEN
SEND TEMPLATE customer.phone, "payment_final_notice", {
"name": customer.name,
"invoice_id": invoice.id,
"total": FORMAT(total_due, "R$ #,##0.00")
}
END IF
UPDATE "invoices", "id='" + invoice.id + "'", {
"late_fee": late_fee,
"interest": interest,
"total_due": total_due,
"final_notice_sent": NOW()
}
' Create task for human follow-up call
CREATE TASK "Ligar para cliente: " + customer.name + " - Cobrança 15 dias", "cobranca@company.com", NOW()
' Find finance attendant and assign
attendants = GET ATTENDANTS
FOR EACH att IN attendants.items
IF att.department = "finance" OR att.preferences CONTAINS "collections" THEN
' Create session for outbound call
SAVE "outbound_queue", {
"customer_id": customer.id,
"customer_name": customer.name,
"customer_phone": customer.phone,
"reason": "collection_15_days",
"invoice_id": invoice.id,
"amount_due": total_due,
"assigned_to": att.id,
"priority": "high",
"created_at": NOW()
}
END IF
NEXT
SAVE "collection_log", {
"invoice_id": invoice.id,
"action": "final_notice",
"total_due": total_due,
"created_at": NOW()
}
APPEND results.actions, {"type": "collection_final", "customer": customer.name, "total": total_due}
NEXT
' 30+ days: Send to legal/collections agency
overdue_30 = FIND "invoices", "status='pending' AND DATEDIFF(NOW(), due_date) >= 30 AND status <> 'collections'"
PRINT "30+ days overdue: " + UBOUND(overdue_30)
FOR EACH invoice IN overdue_30
customer = FIND "customers", "id='" + invoice.customer_id + "'"
UPDATE "invoices", "id='" + invoice.id + "'", {
"status": "collections",
"sent_to_collections": NOW()
}
UPDATE "customers", "id='" + customer.id + "'", {
"status": "suspended"
}
SEND MAIL "juridico@company.com", "Inadimplência 30+ dias: " + customer.name, "Cliente enviado para cobrança jurídica.\n\nCliente: " + customer.name + "\nFatura: " + invoice.id + "\nValor total: R$ " + invoice.total_due + "\nDias em atraso: " + DATEDIFF(NOW(), invoice.due_date)
SAVE "collection_log", {
"invoice_id": invoice.id,
"action": "sent_to_legal",
"created_at": NOW()
}
APPEND results.actions, {"type": "collection_legal", "customer": customer.name}
NEXT
results.collections_processed = UBOUND(due_today) + UBOUND(overdue_3) + UBOUND(overdue_7) + UBOUND(overdue_15) + UBOUND(overdue_30)
PRINT "Collections processed: " + results.collections_processed
END IF
' =====================================================================
' LEAD NURTURE - Re-engage cold leads
' =====================================================================
IF job_name = "lead-nurture" OR job_name = "all" THEN
PRINT ""
PRINT "--- Running Lead Nurture ---"
' Find cold leads that haven't been contacted in 30 days
cold_leads = FIND "leads", "status IN ('cold', 'nurturing') AND DATEDIFF(NOW(), last_contact) >= 30 AND DATEDIFF(NOW(), last_contact) < 90"
PRINT "Cold leads to nurture: " + UBOUND(cold_leads)
FOR EACH lead IN cold_leads
' Send nurture content based on interest
content_type = "general"
IF lead.interest CONTAINS "pricing" OR lead.interest CONTAINS "preço" THEN
content_type = "pricing_update"
ELSE IF lead.interest CONTAINS "feature" OR lead.interest CONTAINS "funcionalidade" THEN
content_type = "feature_update"
END IF
IF lead.email IS NOT NULL THEN
SEND TEMPLATE lead.email, "nurture_" + content_type, {
"name": lead.name,
"company": lead.company
}
END IF
UPDATE "leads", "id='" + lead.id + "'", {
"last_contact": NOW(),
"nurture_count": (lead.nurture_count OR 0) + 1
}
SAVE "activities", {
"type": "nurture",
"lead_id": lead.id,
"description": "Nurture email sent: " + content_type,
"created_at": NOW()
}
APPEND results.actions, {"type": "nurture", "lead": lead.name, "content": content_type}
NEXT
' Archive very old leads (90+ days, low score)
stale_leads = FIND "leads", "DATEDIFF(NOW(), last_contact) >= 90 AND score < 30 AND status <> 'archived'"
PRINT "Stale leads to archive: " + UBOUND(stale_leads)
FOR EACH lead IN stale_leads
UPDATE "leads", "id='" + lead.id + "'", {
"status": "archived",
"archived_at": NOW(),
"archive_reason": "No engagement after 90 days"
}
APPEND results.actions, {"type": "archive", "lead": lead.name}
NEXT
results.leads_nurtured = UBOUND(cold_leads)
results.leads_archived = UBOUND(stale_leads)
PRINT "Leads nurtured: " + results.leads_nurtured + ", Archived: " + results.leads_archived
END IF
' =====================================================================
' PIPELINE REVIEW - Weekly pipeline analysis
' =====================================================================
IF job_name = "pipeline-review" OR job_name = "all" THEN
PRINT ""
PRINT "--- Running Pipeline Review ---"
' Get all active opportunities
opportunities = FIND "opportunities", "stage NOT IN ('closed_won', 'closed_lost')"
PRINT "Active opportunities: " + UBOUND(opportunities)
' Calculate pipeline metrics
total_value = 0
weighted_value = 0
stale_count = 0
at_risk_count = 0
FOR EACH opp IN opportunities
total_value = total_value + opp.amount
weighted_value = weighted_value + (opp.amount * opp.probability / 100)
' Check for stale opportunities
days_since_activity = DATEDIFF(NOW(), opp.last_activity)
IF days_since_activity > 14 THEN
stale_count = stale_count + 1
' Alert owner
owner = FIND "attendants", "id='" + opp.owner_id + "'"
IF owner IS NOT NULL AND owner.email IS NOT NULL THEN
SEND MAIL owner.email, "⚠️ Oportunidade Estagnada: " + opp.name, "A oportunidade '" + opp.name + "' está sem atividade há " + days_since_activity + " dias.\n\nValor: R$ " + opp.amount + "\nEstágio: " + opp.stage + "\n\nPor favor, atualize o status ou registre uma atividade."
END IF
' Create task
CREATE TASK "Atualizar oportunidade: " + opp.name, owner.email, NOW()
APPEND results.actions, {"type": "stale_alert", "opportunity": opp.name, "days": days_since_activity}
END IF
' Check for at-risk (past close date)
IF opp.close_date < NOW() THEN
at_risk_count = at_risk_count + 1
UPDATE "opportunities", "id='" + opp.id + "'", {
"at_risk": TRUE,
"risk_reason": "Past expected close date"
}
END IF
NEXT
' Generate weekly report
report = "📊 PIPELINE SEMANAL\n"
report = report + "════════════════════════════════════════\n\n"
report = report + "Total Pipeline: R$ " + FORMAT(total_value, "#,##0.00") + "\n"
report = report + "Valor Ponderado: R$ " + FORMAT(weighted_value, "#,##0.00") + "\n"
report = report + "Oportunidades Ativas: " + UBOUND(opportunities) + "\n"
report = report + "Estagnadas (14+ dias): " + stale_count + "\n"
report = report + "Em Risco: " + at_risk_count + "\n\n"
' Top 5 opportunities
top_opps = FIND "opportunities", "stage NOT IN ('closed_won', 'closed_lost') ORDER BY amount DESC LIMIT 5"
report = report + "TOP 5 OPORTUNIDADES:\n"
FOR EACH opp IN top_opps
report = report + "• " + opp.name + " - R$ " + FORMAT(opp.amount, "#,##0.00") + " (" + opp.probability + "%)\n"
NEXT
' Send to sales leadership
SEND MAIL "vendas@company.com", "Pipeline Semanal - " + FORMAT(NOW(), "dd/MM/yyyy"), report
results.pipeline_total = total_value
results.pipeline_weighted = weighted_value
results.stale_opportunities = stale_count
results.at_risk = at_risk_count
PRINT "Pipeline review completed. Total: R$ " + total_value
END IF
' =====================================================================
' FINISH
' =====================================================================
results.completed_at = NOW()
results.duration_seconds = DATEDIFF("second", results.started_at, results.completed_at)
PRINT ""
PRINT "=== CRM Automations Completed ==="
PRINT "Duration: " + results.duration_seconds + " seconds"
PRINT "Actions taken: " + UBOUND(results.actions)
' Log results
SAVE "automation_logs", results
RETURN results