Example #1
0
def send_submission_slack(submission_pk: str):
    submission = Submission.objects.get(pk=submission_pk)
    text = get_text(submission)
    logging.info("Notifying Slack of Submission<%s>", submission_pk)
    send_slack_message(settings.SLACK_MESSAGE.CLIENT_INTAKE, text)
    # Mark request as sent
    Submission.objects.filter(pk=submission.pk).update(is_alert_sent=True)
Example #2
0
def test_send_issue_slack(slug):
    """
    Ensure send_issue_slack call Slack without anything exploding
    https://github.com/getsentry/responses
    """
    # Set up API response.
    responses.add(method=responses.POST,
                  url="https://example.com",
                  status=200,
                  json={})  # Not used
    # Prepare database
    channel = SlackChannel.objects.last()
    assert channel.webhook_url == "https://example.com"
    msg = SlackMessage.objects.select_related("channel").get(slug=slug)
    assert msg.channel == channel
    user_1 = SlackUser.objects.create(name="Alice", slack_id="1234")
    user_2 = SlackUser.objects.create(name="Bob", slack_id="5678")
    msg.users.add(user_1)
    msg.users.add(user_2)
    msg.save()

    # Send the message
    text = "This is a cool Slack message!"
    send_slack_message(msg.slug, text)

    # Check it worked!
    assert len(responses.calls) == 1
    body_text = responses.calls[0].request.body.decode("utf-8")
    body_json = json.loads(body_text)
    assert body_json["text"] == ("Hi <@1234> and <@5678>.\n\n"
                                 "This is a cool Slack message!\n\n"
                                 ":heart: Client Bot :robot_face:")
Example #3
0
def send_issue_slack(issue_pk: str):
    issue = Issue.objects.select_related("client").get(pk=issue_pk)
    text = get_text(issue)
    logging.info("Notifying Slack of Issue<%s>", issue_pk)
    send_slack_message(settings.SLACK_MESSAGE.CLIENT_INTAKE, text)
    # Mark request as sent
    Issue.objects.filter(pk=issue.pk).update(is_alert_sent=True)
Example #4
0
def send_submission_failure_slack(sub_pk: str):
    logger.info("Sending failure Slack message for Submission[%s]", sub_pk)
    msg = (
        "*Submission failed to process*\n"
        f"A new client intake submission ({sub_pk}) has failed to process.\n"
        f"The tech team needs to fix this manually\n"
    )
    send_slack_message(settings.SLACK_MESSAGE.CLIENT_INTAKE, msg)
Example #5
0
def send_webflow_contact_slack(webflow_contact_pk: str):
    webflow_contact = WebflowContact.objects.get(pk=webflow_contact_pk)
    text = get_text(webflow_contact)
    logging.info("Notifying Slack of WebflowContact<%s>", webflow_contact_pk)
    send_slack_message(settings.SLACK_MESSAGE.LANDING_FORM, text)
    # Mark request as sent
    WebflowContact.objects.filter(pk=webflow_contact.pk).update(
        is_alert_sent=True)
Example #6
0
def send_weekly_report_slack():
    """
    Tell #general about our metrics.
    """
    quarterly_text = get_report_text(90)
    annual_text = get_report_text(365)
    text = (
        "*Monthly Metrics Report*\n"
        "This is an automated monthly report on some of our key metrics.\n\n"
        f"\tIn the last 90 days we saw:\n\n{quarterly_text}\n\n"
        f"\tIn the last 365 days we saw:\n\n{annual_text}\n\n"
        f"See more details at our submissions/outcomes <{PUBLIC_REPORTING_URL}|dashboard>."
    )
    send_slack_message(settings.SLACK_MESSAGE.WEEKLY_REPORT, text)
Example #7
0
def send_email_alert_slack(email_pk: str):
    """
    Notify alerts channel of new unhandled email.
    """
    logging.info("Sending alert for Email<%s>", email_pk)
    email = Email.objects.get(pk=email_pk)
    issue = email.issue
    assert issue, f"Email<{email_pk}> does not have an associated Issue"
    paralegal = issue.paralegal
    alert_sent = False
    case_email_url = settings.CLERK_BASE_URL + reverse(
        "case-email-list", args=(str(issue.pk),)
    )
    case_url = settings.CLERK_BASE_URL + reverse(
        "case-detail-view", args=(str(issue.pk),)
    )
    msg = (
        "*New Email Notification*\n"
        f"A new email has been received for case <{case_url}|{issue.fileref}> .\n"
        f"You can view this case's emails here: <{case_email_url}|here>.\n"
    )
    if paralegal and issue.is_open:
        # Send alert directly to paralegal for open issues.
        alert_email = settings.SLACK_EMAIL_ALERT_OVERRIDE or paralegal.email
        logging.info("Looking up %s in Slack", alert_email)
        slack_user = get_slack_user_by_email(alert_email)
        if slack_user:
            logging.info("Notifying %s of Email<%s> via Slack", alert_email, email_pk)
            send_slack_direct_message(msg, slack_user["id"])
            alert_sent = True

    if not alert_sent:
        # In all other cases send to alerts channel.
        logging.info(
            "Could not find someone to DM in Slack, sending generic alert for Email<%s>",
            email_pk,
        )
        send_slack_message(settings.SLACK_MESSAGE.CLIENT_INTAKE, msg)

    Email.objects.filter(pk=email_pk).update(is_alert_sent=True)
    logging.info("Alert sent sucessfully for Email<%s>", email_pk)
Example #8
0
def _send_issue_actionstep(issue_pk: str):
    """
    Send a issue to Actionstep.
    """
    if not settings.ACTIONSTEP_WEB_URI:
        logger.info("Skipping sending Issue<%s]> to Actionstep: not set up.",
                    issue_pk)
        return

    issue = Issue.objects.get(pk=issue_pk)
    logger.info("Sending Issue<%s]> to Actionstep", issue.id)
    api = ActionstepAPI()

    # Fetch new action owner.
    owner_email = settings.ACTIONSTEP_SETUP_OWNER
    owner_data = api.participants.get_by_email(owner_email)
    logger.info("Assigning Issue<%s]> to owner %s", issue_pk,
                owner_data["email"])

    answers = issue.answers
    client = issue.client

    # Ensure participant is in the system.
    logger.info("Try to create participant %s, %s.", client.get_full_name(),
                client.email)
    participant_data, created = api.participants.get_or_create(
        client.first_name, client.last_name, client.email, client.phone_number)
    if created:
        logger.info("Created participant %s, %s.", client.get_full_name(),
                    client.email)
    else:
        logger.info("Participant %s, %s already exists.",
                    client.get_full_name(), client.email)

    # Check if this issue already has an action
    action_id = None
    issue_filenotes = api.filenotes.list_by_text_match(issue.pk)
    if issue_filenotes:
        action_id = max([int(fn["links"]["action"]) for fn in issue_filenotes])
    else:
        action_id = None

    if action_id:
        # An matter has already been created for this issue
        logger.info("Found existing matter %s for %s", action_id, issue.pk)
        action_data = api.actions.get(action_id)
        fileref_name = action_data["reference"]
        logger.info("Existing matter has fileref %s", fileref_name)

    else:
        # We need to create a new matter
        file_ref_prefix = PREFIX_LOOKUP[issue.topic]
        fileref_name = api.actions.get_next_ref(file_ref_prefix)
        logger.info("Creating new matter %s for %s", fileref_name,
                    client.get_full_name())
        action_type_name = ACTION_TYPE_LOOKUP[issue.topic]
        action_type_data = api.actions.action_types.get_for_name(
            action_type_name)
        action_type_id = action_type_data["id"]
        action_data = api.actions.create(
            issue_id=issue.pk,
            action_type_id=action_type_id,
            action_name=client.get_full_name(),
            file_reference=fileref_name,
            participant_id=owner_data["id"],
        )
        Issue.objects.filter(pk=issue_pk).update(fileref=fileref_name)
        action_id = action_data["id"]
        client_id = participant_data["id"]
        api.participants.set_action_participant(action_id, client_id,
                                                Participant.CLIENT)

    # Upload files. Note that multiple uploads will create copies.
    logger.info("Generating PDF for Issue<%s>", issue.id)
    pdf_bytes = create_pdf(issue)
    pdf_filename = f"client-intake-{issue_pk}.pdf"

    logger.info("Uploading PDF for Issue<%s>", issue.id)
    file_data = api.files.upload(pdf_filename, pdf_bytes)
    file_id = file_data["id"]
    folder_name = "Client"
    logger.info("Attaching PDF for Issue<%s>", issue.id)
    api.files.attach(pdf_filename, file_id, action_id, folder_name)

    logger.info("Setting up training materials for Actionstep action %s",
                action_id)
    topic_docs = ActionDocument.objects.filter(topic=issue.topic)
    for doc in topic_docs:
        name = doc.get_filename()
        logger.info("Attaching doc %s to Actionstep action %s", name,
                    action_id)
        api.files.attach(name, doc.actionstep_id, action_id, doc.folder)

    logger.info("Marking Actionstep integration complete for Issue<%s>",
                issue.id)
    Issue.objects.filter(pk=issue.pk).update(is_case_sent=True)

    # Try send a Slack message
    logging.info("Notifying Slack of Actionstep integration for Issue<%s>",
                 issue_pk)

    action_url = urljoin(
        settings.ACTIONSTEP_WEB_URI,
        f"/mym/asfw/workflow/action/overview/action_id/{action_id}",
    )

    topic_title = issue.topic.title()
    text = f"{topic_title} issue has been uploaded to Actionstep as <{action_url}|{fileref_name}> ({issue.pk})"
    send_slack_message(settings.SLACK_MESSAGE.ACTIONSTEP_CREATE, text)
Example #9
0
def _send_submission_actionstep(submission_pk: str):
    """
    Send a submission to Actionstep.
    FIXME: add tests
    FIXME: Make it harder to sync the same data twice.
    """
    submission = Submission.objects.get(pk=submission_pk)
    logger.info("Sending Submission<%s]> to Actionstep", submission.id)
    api = ActionstepAPI()

    # Fetch new action owner.
    owner_email = settings.ACTIONSTEP_SETUP_OWNERS[submission.topic]
    owner_data = api.participants.get_by_email(owner_email)
    logger.info("Assigning Submission<%s]> to owner %s", submission_pk,
                owner_data["email"])

    # Pull client data out of the Submission answers JSON.
    # FIXME: This is pretty bad in that we depend on an schemaless JSON object that is set by the frontend.
    answers = {a["name"]: a["answer"] for a in submission.answers}
    client_name = answers["CLIENT_NAME"]
    client_phone = answers["CLIENT_PHONE"]
    client_email = answers["CLIENT_EMAIL"]
    client_firstname = client_name.split(" ")[0]
    client_lastname = client_name.split(" ")[-1]

    # Ensure participant is in the system.
    logger.info("Try to create participant %s, %s.", client_name, client_email)
    participant_data, created = api.participants.get_or_create(
        client_firstname, client_lastname, client_email, client_phone)
    if created:
        logger.info("Created participant %s, %s.", client_name, client_email)
    else:
        logger.info("Participant %s, %s already exists.", client_name,
                    client_email)

    # Check if this submission already has an action
    action_id = None
    submission_filenotes = api.filenotes.get_by_text_match(submission.pk)
    # This can be a list or a dict >.<
    if type(submission_filenotes) is list:
        action_id = max(
            [int(fn["links"]["action"]) for fn in submission_filenotes])
    elif type(submission_filenotes) is dict:
        action_id = int(submission_filenotes["links"]["action"])

    if action_id:
        # An matter has already been created for this submission
        logger.info("Found existing matter %s for %s", action_id,
                    submission.pk)
        action_data = api.actions.get(action_id)
        fileref_name = action_data["reference"]
        logger.info("Existing matter has fileref %s", fileref_name)

    else:
        # We need to create a new matter
        file_ref_prefix = PREFIX_LOOKUP[submission.topic]
        fileref_name = api.actions.get_next_ref(file_ref_prefix)
        logger.info("Creating new matter %s for %s", fileref_name, client_name)
        action_type_name = ACTION_TYPE_LOOKUP[submission.topic]
        action_type_data = api.actions.action_types.get_for_name(
            action_type_name)
        action_type_id = action_type_data["id"]
        action_data = api.actions.create(
            submission_id=submission.pk,
            action_type_id=action_type_id,
            action_name=client_name,
            file_reference=fileref_name,
            participant_id=owner_data["id"],
        )
        action_id = action_data["id"]
        client_id = participant_data["id"]
        api.participants.set_action_participant(action_id, client_id,
                                                Participant.CLIENT)

    # Upload files. Note that multiple uploads will create copies.
    logger.info("Generating PDF for Submission<%s>", submission.id)
    pdf_bytes = create_pdf(submission)
    pdf_filename = f"client-intake-{submission_pk}.pdf"

    logger.info("Uploading PDF for Submission<%s>", submission.id)
    file_data = api.files.upload(pdf_filename, pdf_bytes)
    file_id = file_data["id"]
    folder_name = "Client"
    logger.info("Attaching PDF for Submission<%s>", submission.id)
    api.files.attach(pdf_filename, file_id, action_id, folder_name)

    logger.info("Setting up training materials for Actionstep action %s",
                action_id)
    topic_docs = ActionDocument.objects.filter(topic=submission.topic)
    for doc in topic_docs:
        name = doc.get_filename()
        logger.info("Attaching doc %s to Actionstep action %s", name,
                    action_id)
        api.files.attach(name, doc.actionstep_id, action_id, doc.folder)

    logger.info("Marking Actionstep integration complete for Submission<%s>",
                submission.id)
    Submission.objects.filter(pk=submission.pk).update(is_case_sent=True)

    # Try send a Slack message
    logging.info(
        "Notifying Slack of Actionstep integration for Submission<%s>",
        submission_pk)
    action_url = urljoin(
        settings.ACTIONSTEP_WEB_URI,
        f"/mym/asfw/workflow/action/overview/action_id/{action_id}",
    )
    text = (
        f"Submission {submission.topic}: {submission.pk} has been uploaded to Actionstep with file reference {fileref_name}.\n"
        f"You can find the action at {action_url}")
    send_slack_message(settings.SLACK_MESSAGE.ACTIONSTEP_CREATE, text)