Ejemplo n.º 1
0
def notify_new_progress_report_slack(progress_report, updated=False):
    progress_report = clean_instance(progress_report, ProgressReport)

    is_pm_report = progress_report.event.type in [PROGRESS_EVENT_PM, PROGRESS_EVENT_INTERNAL] or \
                   (progress_report.event.type == PROGRESS_EVENT_MILESTONE and progress_report.user.is_project_manager)
    is_client_report = progress_report.event.type == PROGRESS_EVENT_CLIENT or \
                       (
                           progress_report.event.type == PROGRESS_EVENT_MILESTONE and progress_report.user.is_project_owner)
    is_pm_or_client_report = is_pm_report or is_client_report
    is_dev_report = not is_pm_or_client_report

    # All reports go to Tunga #updates Slack
    slack_msg, attachments = create_progress_report_slack_message(
        progress_report, updated=updated)
    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL,
            slack_utils.KEY_ATTACHMENTS: attachments
        })

    if is_dev_report:
        # Re-create report for clients
        # TODO: Respect client's settings
        slack_msg, attachments = create_progress_report_slack_message(
            progress_report, updated=updated, to_client=True)
        slack_utils.send_project_message(progress_report.event.project,
                                         message=slack_msg,
                                         attachments=attachments)
Ejemplo n.º 2
0
def notify_missed_progress_event_slack(progress_event):
    progress_event = clean_instance(progress_event, ProgressEvent)

    if progress_event.project.archived or progress_event.status != "missed" or not progress_event.last_reminder_at or progress_event.missed_notification_at:
        return

    participants = progress_event.participants
    if not participants:
        # No one to report or project is now closed
        return

    target_user = None
    if participants and len(participants) == 1:
        target_user = participants[0]

    project_url = '{}/projects/{}'.format(TUNGA_URL, progress_event.project.id)
    slack_msg = "`Alert (!):` {} {} for \"{}\" | <{}|View on Tunga>".format(
        target_user and '{} missed a'.format(target_user.short_name) or 'Missed',
        (progress_event.type == PROGRESS_EVENT_CLIENT and 'progress survey') or
        (progress_event.type == PROGRESS_EVENT_MILESTONE and 'milestone report') or
        'progress report',
        progress_event.project.title,
        project_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: progress_event.project.title,
            slack_utils.KEY_TITLE_LINK: project_url,
            slack_utils.KEY_TEXT: '*Due Date:* {}\n\n{}'.format(
                progress_event.due_at.strftime("%d %b, %Y"),
                '\n\n'.join(
                    [
                        '*Name:* {}\n'
                        '*Email:* {}{}'.format(
                            user.display_name.encode('utf-8'),
                            user.email,
                            not user.is_project_owner and user.profile and user.profile.phone_number and
                            '\n*Phone Number:* {}'.format(user.profile.phone_number) or '')
                        for user in participants
                    ]
                )
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        }
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_MISSED_UPDATES_CHANNEL
        }
    )

    # Save notification time
    progress_event.missed_notification_at = datetime.datetime.now()
    progress_event.save()
Ejemplo n.º 3
0
def notify_paid_invoice_slack_admin(invoice):
    invoice = clean_instance(invoice, Invoice)

    if invoice.legacy_id or not invoice.paid:
        # ignore legacy invoices
        return

    project_url = '{}/projects/{}/'.format(TUNGA_URL, invoice.project.id)
    person_url = '{}/network/{}/'.format(TUNGA_URL, invoice.user.username)
    invoice_url = '{}/api/invoices/{}/download/?format=pdf'.format(TUNGA_URL, invoice.id)

    slack_msg = ':tada: A {} of *EUR {}* has been {} *<{}|{}>* for <{}|{}> | <{}|Download Invoice>'.format(
        invoice.type == INVOICE_TYPE_SALE and 'payment' or 'payout',
        invoice.amount,
        invoice.type == INVOICE_TYPE_SALE and 'made by' or 'sent to',
        person_url,
        invoice.user.display_name.encode('utf-8'),
        project_url,
        invoice.full_title,
        invoice_url
    )

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PAYMENTS_CHANNEL
        }
    )
Ejemplo n.º 4
0
def notify_missed_progress_event_slack(progress_event):
    progress_event = clean_instance(progress_event, ProgressEvent)

    if progress_event.project.archived or progress_event.status != "missed" or not progress_event.last_reminder_at or progress_event.missed_notification_at:
        return

    participants = progress_event.participants
    if not participants:
        # No one to report or project is now closed
        return

    target_user = None
    if participants and len(participants) == 1:
        target_user = participants[0]

    project_url = '{}/projects/{}'.format(TUNGA_URL, progress_event.project.id)
    slack_msg = "`Alert (!):` {} {} for \"{}\" | <{}|View on Tunga>".format(
        target_user and '{} missed a'.format(target_user.short_name) or 'Missed',
        (progress_event.type == PROGRESS_EVENT_CLIENT and 'progress survey') or
        (progress_event.type == PROGRESS_EVENT_MILESTONE and 'milestone report') or
        'progress report',
        progress_event.project.title,
        project_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: progress_event.project.title,
            slack_utils.KEY_TITLE_LINK: project_url,
            slack_utils.KEY_TEXT: '*Due Date:* {}\n\n{}'.format(
                progress_event.due_at.strftime("%d %b, %Y"),
                '\n\n'.join(
                    [
                        '*Name:* {}\n'
                        '*Email:* {}{}'.format(
                            user.display_name.encode('utf-8'),
                            user.email,
                            not user.is_project_owner and user.profile and user.profile.phone_number and
                            '\n*Phone Number:* {}'.format(user.profile.phone_number) or '')
                        for user in participants
                    ]
                )
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        }
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_MISSED_UPDATES_CHANNEL
        }
    )

    # Save notification time
    progress_event.missed_notification_at = datetime.datetime.now()
    progress_event.save()
Ejemplo n.º 5
0
def notify_new_invite_request_slack(invite_request):
    invite_request = clean_instance(invite_request, InviteRequest)

    slack_msg = "<!channel> {} wants to join Tunga".format(invite_request.name)

    attachments = [{
        slack_utils.KEY_TITLE:
        invite_request.name,
        slack_utils.KEY_TITLE_LINK:
        invite_request.cv_url,
        slack_utils.KEY_TEXT:
        '*Name:* {}\n*Email:* {}\n*Country*: {}\n<{}|Download CV>'.format(
            invite_request.name, invite_request.email,
            invite_request.country.name, invite_request.cv_url),
        slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
        slack_utils.KEY_COLOR:
        SLACK_ATTACHMENT_COLOR_GREEN,
    }, {
        slack_utils.KEY_TITLE: 'Motivation',
        slack_utils.KEY_TEXT: invite_request.motivation,
        slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
        slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE,
    }]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PROFILES_CHANNEL
        })
Ejemplo n.º 6
0
def notify_progress_report_client_not_satisfied_slack_admin(instance):
    instance = clean_instance(instance, ProgressReport)

    task_url = '{}/work/{}/event/{}'.format(TUNGA_URL, instance.event.task.id, instance.event.id)
    slack_msg = "`Alert (!):` Client dissatisfied | <{}|View on Tunga>".format(task_url)

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.event.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: 'The project owner of \"{}\" {} is unsatisfied with the deliverable.\n '
                                  'Please contact all stakeholders.'.format(
                instance.event.task.summary,
                instance.event.task.is_task and 'task' or 'project'
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        },
        create_task_stakeholders_attachment_slack(instance.event.task, show_title=False)
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL
        }
    )
Ejemplo n.º 7
0
def notify_progress_report_deadline_missed_slack_admin(instance):
    instance = clean_instance(instance, ProgressReport)

    task_url = '{}/work/{}'.format(TUNGA_URL, instance.event.task.id)
    slack_msg = "`Alert (!):` Follow up on missed deadline for \"{}\" | <{}|View on Tunga>".format(
        instance.event.task.summary,
        task_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.event.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: 'A deadline has been missed on the "{}" {}\n'
                                  '*Was the client informed before hand?:* {}\n'
                                  'Please contact the stakeholders.'.format(
                instance.event.task.summary,
                instance.event.task.is_task and 'task' or 'project',
                instance.deadline_miss_communicated and 'Yes' or 'No'
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        },
        create_task_stakeholders_attachment_slack(instance.event.task, show_title=False)
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL
        }
    )
Ejemplo n.º 8
0
def notify_new_progress_report_slack(instance, updated=False):
    instance = clean_instance(instance, ProgressReport)

    is_pm_report = instance.event.type in [
        PROGRESS_EVENT_TYPE_PM, PROGRESS_EVENT_TYPE_MILESTONE_INTERNAL
    ]
    is_client_report = instance.event.type == PROGRESS_EVENT_TYPE_CLIENT
    is_pm_or_client_report = is_pm_report or is_client_report
    is_dev_report = not is_pm_or_client_report

    # if not (slack_utils.is_task_notification_enabled(instance.event.task, slugs.EVENT_PROGRESS)):
    #    return

    # All reports go to Tunga #updates Slack
    slack_msg, attachments = create_progress_report_slack_message(
        instance, updated=updated)
    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL,
            slack_utils.KEY_ATTACHMENTS: attachments
        })

    if is_dev_report:
        # Re-create report for clients
        slack_msg, attachments = create_progress_report_slack_message(
            instance, updated=updated, to_client=True)
        slack_utils.send_integration_message(instance.event.task,
                                             message=slack_msg,
                                             attachments=attachments)
Ejemplo n.º 9
0
def notify_progress_report_stuck_slack_admin(instance):
    instance = clean_instance(instance, ProgressReport)

    task_url = '{}/work/{}/event/{}'.format(TUNGA_URL, instance.event.task.id, instance.event.id)
    slack_msg = "`Alert (!):` The status for the \"{}\" {} has been classified as stuck | <{}|View on Tunga>".format(
        instance.event.task.summary,
        instance.event.task.is_task and 'task' or 'project',
        task_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.event.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: 'Please contact all stakeholders.',
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        },
        create_task_stakeholders_attachment_slack(instance.event.task, show_title=False)
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL
        }
    )
Ejemplo n.º 10
0
def notify_progress_report_wont_meet_deadline_slack_admin(instance):
    instance = clean_instance(instance, ProgressReport)

    task_url = '{}/work/{}/event/{}'.format(TUNGA_URL, instance.event.task.id, instance.event.id)
    slack_msg = "`Alert (!):` {} doesn't expect to meet the deadline | <{}|View on Tunga>".format(
        instance.event.type in [LEGACY_PROGRESS_EVENT_TYPE_PM, LEGACY_PROGRESS_EVENT_TYPE_MILESTONE_INTERNAL] and 'PM' or 'Developer',
        task_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.event.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: 'The {} on the \"{}\" {} has indicated that they might not meet the coming deadline.\n'
                                  'Please contact all stakeholders.'.format(
                instance.event.type in [LEGACY_PROGRESS_EVENT_TYPE_PM,
                                        LEGACY_PROGRESS_EVENT_TYPE_MILESTONE_INTERNAL] and 'PM' or 'Developer',
                instance.event.task.summary,
                instance.event.task.is_task and 'task' or 'project'
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        },
        create_task_stakeholders_attachment_slack(instance.event.task, show_title=False)
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL
        }
    )
Ejemplo n.º 11
0
def notify_user_profile_updated_slack(instance, edited=None):
    instance = clean_instance(instance, UserProfile)

    if instance.user.type != USER_TYPE_DEVELOPER:
        return

    profile_url = '{}/developer/{}'.format(TUNGA_URL, instance.user.username)
    slack_msg = "{}'s profile has been updated | <{}|Review on Tunga>".format(
        instance.user.display_name, profile_url)

    attachments = [{
        slack_utils.KEY_TITLE:
        instance.user.display_name,
        slack_utils.KEY_TITLE_LINK:
        profile_url,
        slack_utils.KEY_TEXT:
        '*Name:* {}\n'
        '*Location:* {}\n'
        '*Skills*: {}\n'
        '*Verified:* {}'.format(instance.user.display_name, instance.location,
                                str(instance.skills),
                                instance.user.verified and 'True' or 'False'),
        slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
        slack_utils.KEY_COLOR:
        instance.user.verified and SLACK_ATTACHMENT_COLOR_GREEN
        or SLACK_ATTACHMENT_COLOR_RED
    }]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PROFILES_CHANNEL
        })
Ejemplo n.º 12
0
def notify_missed_progress_event_slack(instance):
    instance = clean_instance(instance, ProgressEvent)

    is_client_report = instance.type in [LEGACY_PROGRESS_EVENT_TYPE_CLIENT, LEGACY_PROGRESS_EVENT_TYPE_CLIENT_MID_SPRINT]

    if instance.task.archived or instance.status != "missed" or not instance.last_reminder_at:
        return

    participants = instance.participants
    if not participants or instance.task.closed:
        # No one to report or task is now closed
        return

    target_user = None
    if participants and len(participants) == 1:
        target_user = participants[0]

    task_url = '{}/work/{}'.format(TUNGA_URL, instance.task.id)
    slack_msg = "`Alert (!):` {} {} for \"{}\" | <{}|View on Tunga>".format(
        target_user and '{} missed a'.format(target_user.short_name) or 'Missed',
        is_client_report and 'weekly survey' or 'progress report',
        instance.task.summary,
        task_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: '\n\n'.join(
                [
                    '*Due Date:* {}\n\n'
                    '*Name:* {}\n'
                    '*Email:* {}{}'.format(
                        instance.due_at.strftime("%d %b, %Y"),
                        user.display_name.encode('utf-8'),
                        user.email,
                        user.profile and user.profile.phone_number and '\n*Phone Number:* {}'.format(
                            user.profile.phone_number) or ''
                    ) for user in participants
                ]
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        }
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_MISSED_UPDATES_CHANNEL
        }
    )

    # Save notification time
    instance.missed_notification_at = datetime.datetime.now()
    instance.save()
Ejemplo n.º 13
0
def notify_new_message_slack(instance):
    instance = clean_instance(instance, Message)
    if instance.channel.type == CHANNEL_TYPE_SUPPORT and instance.source != APP_INTEGRATION_PROVIDER_SLACK:
        if instance.user and (instance.user.is_staff
                              or instance.user.is_superuser):
            # Ignore messages from admins
            return
        channel_url = '%s/help/%s/' % (TUNGA_URL, instance.channel_id)
        message_details = {
            slack_utils.KEY_AUTHOR_NAME:
            instance.sender.display_name,
            slack_utils.KEY_TEXT:
            instance.text_body,
            slack_utils.KEY_MRKDWN_IN:
            [slack_utils.KEY_TEXT, slack_utils.KEY_FOOTER],
            slack_utils.KEY_COLOR:
            SLACK_ATTACHMENT_COLOR_TUNGA,
            slack_utils.KEY_FOOTER:
            'Type C{} <your reply here>'.format(instance.channel_id),
            slack_utils.KEY_FOOTER_ICON:
            TUNGA_ICON_URL_150,
        }
        if instance.channel.subject:
            message_details[slack_utils.KEY_TITLE] = instance.channel.subject
            message_details[slack_utils.KEY_TITLE_LINK] = channel_url
        else:
            inquirer = instance.channel.get_inquirer()
            if inquirer:
                try:
                    message_details[slack_utils.KEY_TITLE] = 'Help{}{}'.format(
                        inquirer.name and ': ' or '', inquirer.name or '')
                    if inquirer.email:
                        message_details[
                            slack_utils.KEY_TEXT] += '\n\nEmail: {}'.format(
                                inquirer.email)
                    message_details[slack_utils.KEY_TITLE_LINK] = channel_url
                except:
                    pass

        if instance.user:
            message_details[slack_utils.KEY_AUTHOR_LINK] = '%s/people/%s/' % (
                TUNGA_URL, instance.user.username)
        try:
            if instance.sender.avatar_url:
                message_details[
                    slack_utils.KEY_AUTHOR_ICON] = instance.sender.avatar_url
        except:
            pass

        slack_msg = {
            slack_utils.KEY_TEXT:
            "New message from {} | <{}|View on Tunga>".format(
                instance.sender.short_name, channel_url),
            slack_utils.KEY_CHANNEL:
            SLACK_STAFF_CUSTOMER_CHANNEL,
            slack_utils.KEY_ATTACHMENTS: [message_details],
        }
        slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK,
                                          slack_msg)
Ejemplo n.º 14
0
def notify_new_task_invoice_admin_slack(instance):
    instance = clean_instance(instance, TaskInvoice)

    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.task.id)
    owner = instance.task.owner or instance.task.user
    client_url = '{}/people/{}/'.format(TUNGA_URL, owner.username)
    invoice_url = '{}/api/task/{}/download/invoice/?format=pdf'.format(
        TUNGA_URL, instance.task.id)
    slack_msg = '{} generated an invoice'.format(instance.user.display_name)

    attachments = [
        {
            slack_utils.KEY_TITLE:
            instance.task.summary,
            slack_utils.KEY_TITLE_LINK:
            task_url,
            slack_utils.KEY_TEXT:
            'Client: <{}|{}>\nFee: {}\nPayment Method: {}\n<{}|Download invoice>'
            .format(client_url, owner.display_name,
                    instance.display_fee().encode('utf-8'),
                    instance.get_payment_method_display(), invoice_url),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR:
            SLACK_ATTACHMENT_COLOR_BLUE
        },
    ]
    if not instance.task.payment_approved:
        if instance.payment_method == TASK_PAYMENT_METHOD_BANK:
            attachments.append({
                slack_utils.KEY_TITLE:
                'No payment approval required.',
                slack_utils.KEY_TEXT:
                'Payment will be completed via bank transfer.',
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR:
                SLACK_ATTACHMENT_COLOR_GREEN
            })
        else:
            task_approval_url = '{}edit/payment-approval/'.format(task_url)
            attachments.append({
                slack_utils.KEY_TITLE:
                'Review and approve payment.',
                slack_utils.KEY_TITLE_LINK:
                task_approval_url,
                slack_utils.KEY_TEXT:
                "The client won't be able to pay until the payment is approved.",
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR:
                SLACK_ATTACHMENT_COLOR_RED
            })

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PAYMENTS_CHANNEL
        })
Ejemplo n.º 15
0
def notify_new_project_slack_admin(project):
    project = clean_instance(project, Project)

    summary, attachments = create_project_slack_message(project)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: summary,
        slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })
Ejemplo n.º 16
0
def notify_new_project_slack_admin(project):
    project = clean_instance(project, Project)

    summary, attachments = create_project_slack_message(project)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: summary,
        slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })
Ejemplo n.º 17
0
def notify_new_task_community_slack(instance):
    instance = clean_instance(instance, Task)

    # Notify Devs or PMs via Slack
    if (not instance.is_developer_ready) or (instance.approved and instance.visibility == VISIBILITY_DEVELOPER):
        slack_msg = create_task_slack_msg(
            instance,
            channel=instance.is_developer_ready and SLACK_DEVELOPER_UPDATES_CHANNEL or SLACK_PMS_UPDATES_CHANNEL
        )
        slack_utils.send_incoming_webhook(SLACK_DEVELOPER_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 18
0
def notify_tunga_new_skill_has_been_added(instance):
    instance = clean_instance(instance, Skill)

    slack_msg = "{} has been added as a new skill".format(instance.name, )

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
        })
Ejemplo n.º 19
0
def notify_new_message_slack(instance):
    instance = clean_instance(instance, Message)
    if instance.channel.type == CHANNEL_TYPE_SUPPORT and instance.source != APP_INTEGRATION_PROVIDER_SLACK:
        if instance.user and (instance.user.is_staff
                              or instance.user.is_superuser):
            # Ignore messages from admins
            return
        channel_url = '%s/help/%s/' % (TUNGA_URL, instance.channel_id)
        summary = "New message from %s" % instance.sender.short_name
        message_details = {
            slack_utils.KEY_PRETEXT:
            summary,
            slack_utils.KEY_AUTHOR_NAME:
            instance.sender.display_name,
            slack_utils.KEY_TEXT:
            '%s\n\n<%s|View on Tunga>' % (instance.text_body, channel_url),
            slack_utils.KEY_MRKDWN_IN:
            [slack_utils.KEY_TEXT, slack_utils.KEY_FOOTER],
            slack_utils.KEY_COLOR:
            SLACK_ATTACHMENT_COLOR_GREEN,
            slack_utils.KEY_FOOTER:
            'Tunga | Type C%s <your reply here>' % instance.channel_id,
            slack_utils.KEY_FOOTER_ICON:
            TUNGA_ICON_URL_150,
            slack_utils.KEY_FALLBACK:
            summary,
        }
        if instance.channel.subject:
            message_details[slack_utils.KEY_TITLE] = instance.channel.subject
            message_details[slack_utils.KEY_TITLE_LINK] = channel_url
        else:
            inquirer = instance.channel.get_inquirer()
            if inquirer:
                try:
                    message_details[
                        slack_utils.KEY_TITLE] = 'Help: %s' % inquirer.name
                    message_details[slack_utils.KEY_TITLE_LINK] = channel_url
                except:
                    pass

        if instance.user:
            message_details[slack_utils.KEY_AUTHOR_LINK] = '%s/people/%s/' % (
                TUNGA_URL, instance.user.username)
        try:
            if instance.sender.avatar_url:
                message_details[
                    slack_utils.KEY_AUTHOR_ICON] = instance.sender.avatar_url
        except:
            pass

        slack_msg = {
            slack_utils.KEY_ATTACHMENTS: [message_details],
        }
        slack_utils.send_incoming_webhook(SLACK_CUSTOMER_INCOMING_WEBHOOK,
                                          slack_msg)
Ejemplo n.º 20
0
def notify_new_task_invoice_admin_slack(instance):
    instance = clean_instance(instance, TaskInvoice)

    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.task.id)
    owner = instance.task.owner or instance.task.user
    client_url = '{}/people/{}/'.format(TUNGA_URL, owner.username)
    invoice_url = '{}/api/task/{}/download/invoice/?format=pdf'.format(TUNGA_URL, instance.task.id)
    slack_msg = '{} generated an invoice'.format(
        instance.user.display_name.encode('utf-8')
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.task.summary,
            slack_utils.KEY_TITLE_LINK: task_url,
            slack_utils.KEY_TEXT: 'Client: <{}|{}>\nFee: {}\nPayment Method: {}\n<{}|Download invoice>'.format(
                client_url,
                owner.display_name.encode('utf-8'),
                instance.display_fee().encode('utf-8'),
                instance.get_payment_method_display(),
                invoice_url
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE
        },
    ]
    if not instance.task.payment_approved:
        task_approval_url = '{}edit/payment-approval/'.format(task_url)
        if instance.payment_method == PAYMENT_METHOD_BANK:
            attachments.append({
                slack_utils.KEY_TITLE: 'Review and approve payment.',
                slack_utils.KEY_TITLE_LINK: task_approval_url,
                slack_utils.KEY_TEXT: "Payment will be completed via bank transfer.\n "
                                      "However, developer payments won't be distributed until the payment"
                                      " is reviewed and approved.",
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_GREEN
            })
        else:
            attachments.append({
                slack_utils.KEY_TITLE: 'Review and approve payment.',
                slack_utils.KEY_TITLE_LINK: task_approval_url,
                slack_utils.KEY_TEXT: "The client won't be able to pay until the payment is approved.",
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_RED
            })

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PAYMENTS_CHANNEL
        }
    )
Ejemplo n.º 21
0
def notify_new_task_invoice_client_email(instance):
    instance = clean_instance(instance, TaskInvoice)

    to = [instance.user.email]
    if instance.task.owner and instance.task.owner.email != instance.user.email:
        to.append(instance.task.owner.email)

    if instance.task.user and instance.task.user.email != instance.user.email:
        to.append(instance.task.user.email)

    task_url = '{}/task/{}/'.format(TUNGA_URL, instance.task.id)

    owner = instance.task.owner or instance.task.user

    merge_vars = [
        mandrill_utils.create_merge_var(MANDRILL_VAR_FIRST_NAME,
                                        owner.first_name),
        mandrill_utils.create_merge_var('invoice_title',
                                        instance.task.summary),
        mandrill_utils.create_merge_var(
            'can_pay',
            bool(instance.payment_method != TASK_PAYMENT_METHOD_BANK
                 and not instance.task.payment_approved)),
    ]

    rendered_html = process_invoices(instance.task.id,
                                     invoice_types=('client', ),
                                     user_id=owner.id,
                                     is_admin=False)
    pdf_file = HTML(string=rendered_html, encoding='utf-8').write_pdf()
    pdf_file_contents = base64.b64encode(pdf_file)

    attachments = [
        dict(content=pdf_file_contents,
             name='Invoice - {}'.format(instance.task.summary),
             type='application/pdf')
    ]

    mandrill_response = mandrill_utils.send_email('69-invoice',
                                                  to,
                                                  merge_vars=merge_vars,
                                                  attachments=attachments)
    if mandrill_response:
        mandrill_utils.log_emails.delay(
            mandrill_response, to, deal_ids=[instance.task.hubspot_deal_id])

        # Notify via Slack of sent email to double check and prevent multiple sends
        slack_utils.send_incoming_webhook(
            SLACK_DEBUGGING_INCOMING_WEBHOOK, {
                slack_utils.KEY_TEXT:
                "Mandrill Email sent to {} for <{}|Invoice: {}>".format(
                    ', '.join(to), task_url, instance.task.summary),
                slack_utils.KEY_CHANNEL:
                '#alerts'
            })
Ejemplo n.º 22
0
def notify_user_has_been_invited_to_developer_slack(instance):
    instance = clean_instance(instance, DeveloperInvitation)
    slack_msg = "{} has been invited to become a Tunga {}".format(
        instance.first_name,
        instance.get_type_display().lower())

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
        })
Ejemplo n.º 23
0
def notify_project_slack_dev(project, reminder=False):
    project = clean_instance(project, Project)

    if project.stage != PROJECT_STAGE_OPPORTUNITY:
        # Only notify devs about opportunities
        return

    summary, attachments = create_project_slack_message(project, to_developer=True, reminder=reminder)
    slack_utils.send_incoming_webhook(SLACK_DEVELOPER_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: summary,
        slack_utils.KEY_CHANNEL: SLACK_DEVELOPER_OPPORTUNITIES_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })
Ejemplo n.º 24
0
def notify_new_user_signup_on_platform(user):
    instance = clean_instance(user, get_user_model())

    slack_msg = '<{}|{}> has joined Tunga'.format(
        '{}/network/{}'.format(TUNGA_URL, instance.user.username),
        instance.user.display_name,
    )

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
        })
Ejemplo n.º 25
0
def notify_project_slack_dev(project, reminder=False):
    project = clean_instance(project, Project)

    if project.stage != PROJECT_STAGE_OPPORTUNITY:
        # Only notify devs about opportunities
        return

    summary, attachments = create_project_slack_message(project, to_developer=True, reminder=reminder)
    slack_utils.send_incoming_webhook(SLACK_DEVELOPER_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: summary,
        slack_utils.KEY_CHANNEL: SLACK_DEVELOPER_OPPORTUNITIES_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })
Ejemplo n.º 26
0
def notify_new_message_slack(instance):
    instance = clean_instance(instance, Message)
    if instance.channel.type == CHANNEL_TYPE_SUPPORT and instance.source != APP_INTEGRATION_PROVIDER_SLACK:
        if instance.user and (instance.user.is_staff or instance.user.is_superuser):
            # Ignore messages from admins
            return
        channel_url = '%s/help/%s/' % (TUNGA_URL, instance.channel_id)
        message_details = {
            slack_utils.KEY_AUTHOR_NAME: instance.sender.display_name,
            slack_utils.KEY_TEXT: instance.text_body,
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT, slack_utils.KEY_FOOTER],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA,
            slack_utils.KEY_FOOTER: 'Type C{} <your reply here>'.format(instance.channel_id),
            slack_utils.KEY_FOOTER_ICON: TUNGA_ICON_URL_150,
        }
        if instance.channel.subject:
            message_details[slack_utils.KEY_TITLE] = instance.channel.subject
            message_details[slack_utils.KEY_TITLE_LINK] = channel_url
        else:
            inquirer = instance.channel.get_inquirer()
            if inquirer:
                try:
                    message_details[slack_utils.KEY_TITLE] = 'Help{}{}'.format(
                        inquirer.name and ': ' or '', inquirer.name or ''
                    )
                    if inquirer.email:
                        message_details[slack_utils.KEY_TEXT] += '\n\nEmail: {}'.format(inquirer.email)
                    message_details[slack_utils.KEY_TITLE_LINK] = channel_url
                except:
                    pass

        if instance.user:
            message_details[slack_utils.KEY_AUTHOR_LINK] = '%s/people/%s/' % (TUNGA_URL, instance.user.username)
        try:
            if instance.sender.avatar_url:
                message_details[slack_utils.KEY_AUTHOR_ICON] = instance.sender.avatar_url
        except:
            pass

        slack_msg = {
            slack_utils.KEY_TEXT: "New message from {} | <{}|View on Tunga>".format(
                instance.sender.short_name, channel_url
            ),
            slack_utils.KEY_CHANNEL: SLACK_STAFF_CUSTOMER_CHANNEL,
            slack_utils.KEY_ATTACHMENTS: [
                message_details
            ],
        }
        slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 27
0
def notify_new_user_signup_on_platform(user):
    instance = clean_instance(user, get_user_model())

    slack_msg = '<{}|{}> has joined Tunga'.format(
        '{}/network/{}'.format(TUNGA_URL, instance.user.username),
        instance.user.display_name,
    )

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,

        {

            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
        }
    )
Ejemplo n.º 28
0
def notify_invoice_slack_admin(invoice, updated=False):
    invoice = clean_instance(invoice, Invoice)

    if invoice.legacy_id:
        # ignore legacy invoices
        return

    project_url = '{}/projects/{}/'.format(TUNGA_URL, invoice.project.id)
    payment_url = '{}pay'.format(project_url)
    person_url = '{}/network/{}/'.format(TUNGA_URL, invoice.user.username)
    invoice_url = '{}/api/invoices/{}/download/?format=pdf'.format(TUNGA_URL, invoice.id)

    slack_msg = '{} {} a {} invoice'.format(
        (updated and invoice.updated_by or invoice.created_by).display_name.encode('utf-8'),
        updated and 'updated' or 'created',
        invoice.type == INVOICE_TYPE_SALE and 'client' or 'developer'
    )

    invoice_summary = '{}: <{}|{}>\nProject: <{}|{}>\nTitle: {}\nFee: EUR {}\n<{}|Download invoice>'.format(
        invoice.type == INVOICE_TYPE_SALE and 'Client' or 'Developer',
        person_url, invoice.user.display_name.encode('utf-8'),
        project_url, invoice.project.title,
        invoice.title,
        invoice.amount,
        invoice_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: invoice.full_title,
            slack_utils.KEY_TITLE_LINK: payment_url,
            slack_utils.KEY_TEXT: invoice_summary,
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE
        },
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PAYMENTS_CHANNEL
        }
    )
Ejemplo n.º 29
0
def notify_new_contact_request_email(contact_request):
    contact_request = clean_instance(contact_request, ContactRequest)

    if contact_request.body:
        slack_msg = '{} {} is inquiring about {}'.format(
            contact_request.fullname,
            contact_request.email,
            contact_request.body,
        )

        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK,
            {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
            }
        )

    else:
        subject = "New {} Request".format(contact_request.item and 'Offer' or 'Contact')
        msg_suffix = 'wants to know more about Tunga.'
        if contact_request.item:
            item_name = contact_request.get_item_display()
            subject = '%s (%s)' % (subject, item_name)
            msg_suffix = 'requested for "%s"' % item_name
        to = TUNGA_CONTACT_REQUEST_EMAIL_RECIPIENTS

        ctx = {
            'email': contact_request.email,
            'message': '%s %s ' % (
                contact_request.email,
                msg_suffix
            )
        }

        slack_msg = "%s %s" % (subject, msg_suffix)

        if slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK,
                {
                    slack_utils.KEY_TEXT: slack_msg,
                    slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
                }
            ):
            contact_request.email_sent_at = datetime.datetime.utcnow()
            contact_request.save()
Ejemplo n.º 30
0
def notify_review_task_admin_slack(instance):
    instance = clean_instance(instance, Task)
    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.id)
    new_user = instance.source == TASK_SOURCE_NEW_USER

    summary = "Reminder: Review {} {} | <{}|View on Tunga>\nCreated: {}".format(
        instance.scope == TASK_SCOPE_TASK and 'task' or 'project',
        new_user and ' (New user)' or '',
        task_url,
        instance.created_at.strftime("%d %b, %Y"),
        instance.approved_at and 'Approved: {}'.format(instance.approved_at.strftime("%d %b, %Y")) or '',
    )
    slack_msg = create_task_slack_msg(
        instance, summary=summary,
        channel=SLACK_STAFF_LEADS_CHANNEL,
        show_contacts=True
    )
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 31
0
def notify_interest_poll_status_slack(interest_poll):
    interest_poll = clean_instance(interest_poll, InterestPoll)

    if interest_poll.project.stage != PROJECT_STAGE_OPPORTUNITY or interest_poll.status != STATUS_INTERESTED:
        # Notify only accepted opportunities
        return

    slack_msg = '<{}|{}> is interested in <{}|{}>'.format(
        '{}/network/{}'.format(TUNGA_URL, interest_poll.user.username),
        interest_poll.user.display_name,
        '{}/projects/{}'.format(TUNGA_URL, interest_poll.project.id),
        interest_poll.project.title)

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
        })
Ejemplo n.º 32
0
def notify_new_task_admin_slack(instance, new_user=False, completed=False, call_scheduled=False):
    instance = clean_instance(instance, Task)
    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.id)

    completed_phrase = ''
    if call_scheduled:
        completed_phrase = 'availability window shared'
    elif completed:
        completed_phrase = 'details completed'

    summary = "{} {} {} by {}{} | <{}|View on Tunga>".format(
        (completed or call_scheduled) and 'New wizard' or 'New',
        instance.scope == TASK_SCOPE_TASK and 'task' or 'project',
        completed_phrase or 'created',
        instance.user.display_name, new_user and ' (New user)' or '',
        task_url
    )
    slack_msg = create_task_slack_msg(instance, summary=summary, channel=SLACK_STAFF_LEADS_CHANNEL, show_contacts=True, is_admin=True)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 33
0
def notify_new_calendly_event(data):
    event_details = data.get('event', None)
    start_time = parse(event_details.get('start_time', None))

    invitee_details = data.get('invitee', dict())
    invitee_name = invitee_details.get('name')

    questions_and_answers = data.get('questions_and_answers', [])

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_CHANNEL:
            SLACK_STAFF_LEADS_CHANNEL,
            slack_utils.KEY_TEXT:
            '*{}* scheduled a call with Calendly'.format(invitee_name),
            slack_utils.KEY_ATTACHMENTS: [{
                slack_utils.KEY_TEXT:
                '\n'.join([
                    '*{}:* {}'.format(item[0], item[1])
                    for item in [['Name', invitee_name],
                                 ['Email',
                                  invitee_details.get('email')],
                                 [
                                     'Start Time', '{} at {} UTC'.format(
                                         start_time.strftime("%a, %d %b, %Y"),
                                         start_time.strftime("%I:%M %p"))
                                 ]]
                ]),
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR:
                SLACK_ATTACHMENT_COLOR_GREEN
            }, {
                slack_utils.KEY_TEXT:
                '\n'.join([
                    '*{}:*\n{}'.format(item.get('question'),
                                       item.get('answer'))
                    for item in questions_and_answers
                ]),
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR:
                SLACK_ATTACHMENT_COLOR_GREEN
            }]
        })
Ejemplo n.º 34
0
def notify_new_task_admin_slack(instance, new_user=False, completed=False, call_scheduled=False):
    instance = clean_instance(instance, Task)
    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.id)

    completed_phrase = ''
    if call_scheduled:
        completed_phrase = 'availability window shared'
    elif completed:
        completed_phrase = 'details completed'

    summary = "{} {} {} by {}{} | <{}|View on Tunga>".format(
        (completed or call_scheduled) and 'New wizard' or 'New',
        instance.scope == TASK_SCOPE_TASK and 'task' or 'project',
        completed_phrase or 'created',
        instance.user.display_name.encode('utf-8'), new_user and ' (New user)' or '',
        task_url
    )
    slack_msg = create_task_slack_msg(instance, summary=summary, channel=SLACK_STAFF_LEADS_CHANNEL, show_contacts=True,
                                      is_admin=True)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 35
0
def remind_no_task_applications_slack(instance, admin=True):
    instance = clean_instance(instance, Task)

    if not instance.is_task:
        return
    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.id)
    new_user = instance.source == TASK_SOURCE_NEW_USER

    summary = "Reminder: No applications yet for {} {} | <{}|View on Tunga>".format(
        instance.scope == TASK_SCOPE_TASK and 'task' or 'project',
        new_user and admin and ' (New user)' or '', task_url)
    slack_msg = create_task_slack_msg(
        instance,
        summary=summary,
        channel=admin and SLACK_STAFF_LEADS_CHANNEL
        or SLACK_DEVELOPER_UPDATES_CHANNEL,
        show_contacts=admin)
    slack_utils.send_incoming_webhook(
        admin and SLACK_STAFF_INCOMING_WEBHOOK
        or SLACK_DEVELOPER_INCOMING_WEBHOOK, slack_msg)
Ejemplo n.º 36
0
def notify_invoice_slack_admin(invoice, updated=False):
    invoice = clean_instance(invoice, Invoice)

    if invoice.legacy_id:
        # ignore legacy invoices
        return

    project_url = '{}/projects/{}/'.format(TUNGA_URL, invoice.project.id)
    payment_url = '{}pay'.format(project_url)
    person_url = '{}/network/{}/'.format(TUNGA_URL, invoice.user.username)
    invoice_url = '{}/api/invoices/{}/download/?format=pdf'.format(
        TUNGA_URL, invoice.id)

    slack_msg = '{} {} a {}'.format(
        (updated and invoice.updated_by
         or invoice.created_by).display_name.encode('utf-8'),
        updated and 'updated' or 'created',
        invoice.type == INVOICE_TYPE_SALE and 'client payment'
        or 'developer payout')

    invoice_summary = '{}: <{}|{}>\nProject: <{}|{}>\nTitle: {}\nFee: EUR {}\n<{}|Download invoice>'.format(
        invoice.type == INVOICE_TYPE_SALE and 'Client' or 'Developer',
        person_url, invoice.user.display_name.encode('utf-8'), project_url,
        invoice.project.title, invoice.title, invoice.amount, invoice_url)

    attachments = [
        {
            slack_utils.KEY_TITLE: invoice.full_title,
            slack_utils.KEY_TITLE_LINK: payment_url,
            slack_utils.KEY_TEXT: invoice_summary,
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE
        },
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK, {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PAYMENTS_CHANNEL
        })
Ejemplo n.º 37
0
def notify_new_calendly_event(data):
    event_details = data.get('event', None)
    start_time = parse(event_details.get('start_time', None))

    invitee_details = data.get('invitee', dict())
    invitee_name = invitee_details.get('name')

    questions_and_answers = data.get('questions_and_answers', [])

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL,
            slack_utils.KEY_TEXT: '*{}* scheduled a call with Calendly'.format(
                invitee_name
            ),
            slack_utils.KEY_ATTACHMENTS: [
                {
                    slack_utils.KEY_TEXT: '\n'.join(
                        ['*{}:* {}'.format(item[0], item[1]) for item in
                         [
                             ['Name', invitee_name],
                             ['Email', invitee_details.get('email')],
                             ['Start Time', '{} at {} UTC'.format(
                                 start_time.strftime("%a, %d %b, %Y"),
                                 start_time.strftime("%I:%M %p")
                             )]
                         ]]),
                    slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                    slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_GREEN
                },
                {
                    slack_utils.KEY_TEXT: '\n'.join(
                        ['*{}:*\n{}'.format(item.get('question'), item.get('answer')) for item in questions_and_answers]
                    ),
                    slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                    slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_GREEN
                }
            ]
        }
    )
Ejemplo n.º 38
0
def notify_interest_poll_status_slack(interest_poll):
    interest_poll = clean_instance(interest_poll, InterestPoll)

    if interest_poll.project.stage != PROJECT_STAGE_OPPORTUNITY or interest_poll.status != STATUS_INTERESTED:
        # Notify only accepted opportunities
        return

    slack_msg = '<{}|{}> is interested in <{}|{}>'.format(
        '{}/network/{}'.format(TUNGA_URL, interest_poll.user.username),
        interest_poll.user.display_name,
        '{}/projects/{}'.format(TUNGA_URL, interest_poll.project.id),
        interest_poll.project.title
    )

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
        }
    )
Ejemplo n.º 39
0
def notify_task_application_response_slack(instance, admin=True):
    instance = clean_instance(instance, Application)

    application_url = '%s/work/%s/applications/' % (TUNGA_URL,
                                                    instance.task_id)
    task_url = '%s/work/%s/' % (TUNGA_URL, instance.task.id)
    slack_msg = "Task Application {} | <{}|View on Tunga>".format(
        instance.status == STATUS_ACCEPTED and 'accepted' or 'rejected',
        task_url)

    attachments = [{
        slack_utils.KEY_TITLE:
        instance.task.summary,
        slack_utils.KEY_TITLE_LINK:
        application_url,
        slack_utils.KEY_TEXT:
        '%s%s%s%s\n\n<%s|View on Tunga>' %
        (truncatewords(convert_to_text(instance.pitch),
                       100), instance.hours_needed
         and '\n*Workload:* {} hrs'.format(instance.hours_needed)
         or '', instance.deliver_at and '\n*Delivery Date:* {}'.format(
             instance.deliver_at.strftime("%d %b, %Y"))
         or '', instance.remarks and '\n*Remarks:* {}'.format(
             truncatewords(convert_to_text(instance.remarks), 100))
         or '', application_url),
        slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
        slack_utils.KEY_COLOR:
        SLACK_ATTACHMENT_COLOR_TUNGA
    }]
    if admin:
        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK, {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_ATTACHMENTS: attachments,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
            })
    else:
        slack_utils.send_integration_message(instance.task,
                                             message=slack_msg,
                                             attachments=attachments)
Ejemplo n.º 40
0
def notify_new_contact_request_email(contact_request):
    contact_request = clean_instance(contact_request, ContactRequest)

    if contact_request.body:
        slack_msg = '{} {} is inquiring about {}'.format(
            contact_request.fullname,
            contact_request.email,
            contact_request.body,
        )

        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK, {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
            })

    else:
        subject = "New {} Request".format(contact_request.item and 'Offer'
                                          or 'Contact')
        msg_suffix = 'wants to know more about Tunga.'
        if contact_request.item:
            item_name = contact_request.get_item_display()
            subject = '%s (%s)' % (subject, item_name)
            msg_suffix = 'requested for "%s"' % item_name
        to = TUNGA_CONTACT_REQUEST_EMAIL_RECIPIENTS

        ctx = {
            'email': contact_request.email,
            'message': '%s %s ' % (contact_request.email, msg_suffix)
        }

        slack_msg = "%s %s" % (subject, msg_suffix)

        if slack_utils.send_incoming_webhook(
                SLACK_STAFF_INCOMING_WEBHOOK, {
                    slack_utils.KEY_TEXT: slack_msg,
                    slack_utils.KEY_CHANNEL: SLACK_STAFF_PLATFORM_ALERTS
                }):
            contact_request.email_sent_at = datetime.datetime.utcnow()
            contact_request.save()
Ejemplo n.º 41
0
def notify_payment_link_client_email(instance):
    instance = clean_instance(instance, Task)

    to = [instance.user.email]
    if instance.owner and instance.owner.email != instance.user.email:
        to.append(instance.owner.email)

    task_url = '{}/task/{}/'.format(TUNGA_URL, instance.id)
    payment_link = '{}pay/'.format(task_url)

    owner = instance.owner or instance.user

    merge_vars = [
        mandrill_utils.create_merge_var(MANDRILL_VAR_FIRST_NAME,
                                        owner.first_name),
        mandrill_utils.create_merge_var('payment_title', instance.summary),
        mandrill_utils.create_merge_var('payment_link', payment_link),
    ]

    mandrill_response = mandrill_utils.send_email('70-payment-link-ready',
                                                  to,
                                                  merge_vars=merge_vars)
    if mandrill_response:
        instance.payment_link_sent = True
        instance.payment_link_sent_at = datetime.datetime.utcnow()
        instance.save()

        mandrill_utils.log_emails.delay(mandrill_response,
                                        to,
                                        deal_ids=[instance.hubspot_deal_id])

        # Notify via Slack of sent email to double check and prevent multiple sends
        slack_utils.send_incoming_webhook(
            SLACK_DEBUGGING_INCOMING_WEBHOOK, {
                slack_utils.KEY_TEXT:
                "Mandrill Email sent to {} for <{}|Payment Link: {}>".format(
                    ', '.join(to), task_url, instance.summary),
                slack_utils.KEY_CHANNEL:
                '#alerts'
            })
Ejemplo n.º 42
0
def notify_new_task_application_slack(instance, admin=True):
    instance = clean_instance(instance, Application)

    if not slack_utils.is_task_notification_enabled(instance.task,
                                                    slugs.EVENT_APPLICATION):
        return

    application_url = '%s/work/%s/applications/' % (TUNGA_URL,
                                                    instance.task_id)
    slack_msg = "New application from %s" % instance.user.short_name
    attachments = [{
        slack_utils.KEY_TITLE:
        instance.task.summary,
        slack_utils.KEY_TITLE_LINK:
        application_url,
        slack_utils.KEY_TEXT:
        '%s%s%s%s\n\n<%s|View on Tunga>' %
        (truncatewords(convert_to_text(instance.pitch),
                       100), instance.hours_needed
         and '\n*Workload:* {} hrs'.format(instance.hours_needed)
         or '', instance.deliver_at and '\n*Delivery Date:* {}'.format(
             instance.deliver_at.strftime("%d %b, %Y"))
         or '', instance.remarks and '\n*Remarks:* {}'.format(
             truncatewords(convert_to_text(instance.remarks), 100))
         or '', application_url),
        slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
        slack_utils.KEY_COLOR:
        SLACK_ATTACHMENT_COLOR_TUNGA
    }]
    if admin:
        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK, {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_ATTACHMENTS: attachments,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
            })
    else:
        slack_utils.send_integration_message(instance.task,
                                             message=slack_msg,
                                             attachments=attachments)
Ejemplo n.º 43
0
def notify_task_application_response_slack(instance, admin=True):
    instance = clean_instance(instance, Application)

    application_url = '%s/work/%s/applications/' % (TUNGA_URL, instance.task_id)
    task_url = '%s/work/%s/' % (TUNGA_URL, instance.task.id)
    slack_msg = "Task Application {} | <{}|View on Tunga>".format(
        instance.status == STATUS_ACCEPTED and 'accepted' or 'rejected',
        task_url
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: instance.task.summary,
            slack_utils.KEY_TITLE_LINK: application_url,
            slack_utils.KEY_TEXT: '%s%s%s%s\n\n<%s|View on Tunga>' %
                                  (truncatewords(convert_to_text(instance.pitch), 100),
                                   instance.hours_needed and '\n*Workload:* {} hrs'.format(instance.hours_needed) or '',
                                   instance.deliver_at and '\n*Delivery Date:* {}'.format(
                                       instance.deliver_at.strftime("%d %b, %Y")
                                   ) or '',
                                   instance.remarks and '\n*Remarks:* {}'.format(
                                       truncatewords(convert_to_text(instance.remarks), 100)
                                   ) or '',
                                   application_url),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        }
    ]
    if admin:
        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK,
            {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_ATTACHMENTS: attachments,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
            }
        )
    else:
        slack_utils.send_integration_message(instance.task, message=slack_msg, attachments=attachments)
Ejemplo n.º 44
0
def remind_no_task_applications_slack(instance, admin=True):
    instance = clean_instance(instance, Task)

    if not instance.is_task:
        return
    task_url = '{}/work/{}/'.format(TUNGA_URL, instance.id)
    new_user = instance.source == TASK_SOURCE_NEW_USER

    summary = "Reminder: No applications yet for {} {} | <{}|View on Tunga>".format(
        instance.scope == TASK_SCOPE_TASK and 'task' or 'project',
        new_user and admin and ' (New user)' or '',
        task_url
    )
    slack_msg = create_task_slack_msg(
        instance, summary=summary,
        channel=admin and SLACK_STAFF_LEADS_CHANNEL or SLACK_DEVELOPER_UPDATES_CHANNEL,
        show_contacts=admin
    )
    slack_utils.send_incoming_webhook(
        admin and SLACK_STAFF_INCOMING_WEBHOOK or SLACK_DEVELOPER_INCOMING_WEBHOOK,
        slack_msg
    )
Ejemplo n.º 45
0
def notify_new_progress_report_slack(instance, updated=False):
    instance = clean_instance(instance, ProgressReport)

    is_pm_report = instance.event.type in [LEGACY_PROGRESS_EVENT_TYPE_PM, LEGACY_PROGRESS_EVENT_TYPE_MILESTONE_INTERNAL]
    is_client_report = instance.event.type in [LEGACY_PROGRESS_EVENT_TYPE_CLIENT, LEGACY_PROGRESS_EVENT_TYPE_CLIENT_MID_SPRINT]
    is_pm_or_client_report = is_pm_report or is_client_report
    is_dev_report = not is_pm_or_client_report

    # if not (slack_utils.is_task_notification_enabled(instance.event.task, slugs.EVENT_PROGRESS)):
    #    return

    # All reports go to Tunga #updates Slack
    slack_msg, attachments = create_progress_report_slack_message(instance, updated=updated)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: slack_msg,
        slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })

    if is_dev_report:
        # Re-create report for clients
        slack_msg, attachments = create_progress_report_slack_message(instance, updated=updated, to_client=True)
        slack_utils.send_integration_message(instance.event.task, message=slack_msg, attachments=attachments)
Ejemplo n.º 46
0
def notify_new_task_application_slack(instance, admin=True):
    instance = clean_instance(instance, Application)

    if not slack_utils.is_task_notification_enabled(instance.task, slugs.EVENT_APPLICATION):
        return

    application_url = '%s/work/%s/applications/' % (TUNGA_URL, instance.task_id)
    slack_msg = "New application from %s" % instance.user.short_name
    attachments = [
        {
            slack_utils.KEY_TITLE: instance.task.summary,
            slack_utils.KEY_TITLE_LINK: application_url,
            slack_utils.KEY_TEXT: '%s%s%s%s\n\n<%s|View on Tunga>' %
                                  (truncatewords(convert_to_text(instance.pitch), 100),
                                   instance.hours_needed and '\n*Workload:* {} hrs'.format(instance.hours_needed) or '',
                                   instance.deliver_at and '\n*Delivery Date:* {}'.format(
                                       instance.deliver_at.strftime("%d %b, %Y")
                                   ) or '',
                                   instance.remarks and '\n*Remarks:* {}'.format(
                                       truncatewords(convert_to_text(instance.remarks), 100)
                                   ) or '',
                                   application_url),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_TUNGA
        }
    ]
    if admin:
        slack_utils.send_incoming_webhook(
            SLACK_STAFF_INCOMING_WEBHOOK,
            {
                slack_utils.KEY_TEXT: slack_msg,
                slack_utils.KEY_ATTACHMENTS: attachments,
                slack_utils.KEY_CHANNEL: SLACK_STAFF_LEADS_CHANNEL
            }
        )
    else:
        slack_utils.send_integration_message(instance.task, message=slack_msg, attachments=attachments)
Ejemplo n.º 47
0
def notify_new_progress_report_slack(progress_report, updated=False):
    progress_report = clean_instance(progress_report, ProgressReport)

    is_pm_report = progress_report.event.type in [PROGRESS_EVENT_PM, PROGRESS_EVENT_INTERNAL] or \
                   (progress_report.event.type == PROGRESS_EVENT_MILESTONE and progress_report.user.is_project_manager)
    is_client_report = progress_report.event.type == PROGRESS_EVENT_CLIENT or \
                       (
                           progress_report.event.type == PROGRESS_EVENT_MILESTONE and progress_report.user.is_project_owner)
    is_pm_or_client_report = is_pm_report or is_client_report
    is_dev_report = not is_pm_or_client_report

    # All reports go to Tunga #updates Slack
    slack_msg, attachments = create_progress_report_slack_message(progress_report, updated=updated)
    slack_utils.send_incoming_webhook(SLACK_STAFF_INCOMING_WEBHOOK, {
        slack_utils.KEY_TEXT: slack_msg,
        slack_utils.KEY_CHANNEL: SLACK_STAFF_UPDATES_CHANNEL,
        slack_utils.KEY_ATTACHMENTS: attachments
    })

    if is_dev_report:
        # Re-create report for clients
        # TODO: Respect client's settings
        slack_msg, attachments = create_progress_report_slack_message(progress_report, updated=updated, to_client=True)
        slack_utils.send_project_message(progress_report.event.project, message=slack_msg, attachments=attachments)
Ejemplo n.º 48
0
def notify_new_invite_request_slack(invite_request):
    invite_request = clean_instance(invite_request, InviteRequest)

    slack_msg = "<!channel> {} wants to join Tunga".format(
        invite_request.name
    )

    attachments = [
        {
            slack_utils.KEY_TITLE: invite_request.name,
            slack_utils.KEY_TITLE_LINK: invite_request.cv_url,
            slack_utils.KEY_TEXT: '*Name:* {}\n*Email:* {}\n*Country*: {}\n<{}|Download CV>'.format(
                invite_request.name,
                invite_request.email,
                invite_request.country.name,
                invite_request.cv_url
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_GREEN,
        },
        {
            slack_utils.KEY_TITLE: 'Motivation',
            slack_utils.KEY_TEXT: invite_request.motivation,
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE,
        }
    ]

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: slack_msg,
            slack_utils.KEY_ATTACHMENTS: attachments,
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PROFILES_CHANNEL
        }
    )
Ejemplo n.º 49
0
def notify_hubspot_deal_changes_slack(deal_id, changes, event_ids=None):
    deal_url = None
    final_subscription_type = None

    deal_details = hubspot_utils.get_deal(deal_id)

    if deal_details and deal_details.get('properties', None):
        deal_properties = deal_details['properties']
        deal_name = deal_properties.get(hubspot_utils.KEY_DEALNAME, {})['value'] or ''

        deal_property_changes = []
        deal_property_details = hubspot_utils.get_deal_properties()
        deal_pipelines = hubspot_utils.get_deal_pipelines()

        for payload in changes:
            if deal_id != payload.get(hubspot_utils.KEY_OBJECT_ID):
                # Ignore changes from other deals
                continue

            subscription_type = payload.get(hubspot_utils.KEY_SUBSCRIPTION_TYPE)
            if subscription_type in [
                hubspot_utils.KEY_VALUE_DEAL_CREATED,
                hubspot_utils.KEY_VALUE_DEAL_DELETION,
                hubspot_utils.KEY_VALUE_DEAL_PROPERTY_CHANGE
            ]:
                if subscription_type != hubspot_utils.KEY_VALUE_DEAL_PROPERTY_CHANGE or not final_subscription_type:
                    final_subscription_type = subscription_type

                if not deal_url:
                    deal_url = 'https://app.hubspot.com/sales/{}/deal/{}/'.format(
                        payload.get(hubspot_utils.KEY_PORTAL_ID),
                        deal_id
                    )

                if deal_properties and subscription_type == hubspot_utils.KEY_VALUE_DEAL_PROPERTY_CHANGE:
                    current_deal_property_name = payload.get(hubspot_utils.KEY_PROPERTY_NAME, '')
                    if current_deal_property_name != hubspot_utils.KEY_DEALSTAGE:
                        # Deal stage is already shown
                        current_property_value = payload.get(hubspot_utils.KEY_PROPERTY_VALUE, '')

                        display_property_label, display_property_value = hubspot_utils.clean_property(
                            current_deal_property_name, current_property_value,
                            deal_details, deal_property_details, deal_pipelines
                        )

                        if current_deal_property_name:
                            deal_property_changes.append(
                                '*{}:* {}'.format(
                                    display_property_label,
                                    display_property_value
                                )
                            )

        if deal_url and final_subscription_type:
            current_deal_stage = deal_properties.get(hubspot_utils.KEY_DEALSTAGE, {})['value']
            display_deal_stage_label, display_deal_stage_value = hubspot_utils.clean_property(
                hubspot_utils.KEY_DEALSTAGE, current_deal_stage,
                deal_details, deal_property_details, deal_pipelines
            )

            slack_utils.send_incoming_webhook(
                SLACK_STAFF_INCOMING_WEBHOOK,
                {
                    slack_utils.KEY_CHANNEL: SLACK_STAFF_HUBSPOT_CHANNEL,
                    slack_utils.KEY_TEXT: '{} in HubSpot | <{}|View details>'.format(
                        final_subscription_type == hubspot_utils.KEY_VALUE_DEAL_CREATED and 'New deal created' or (
                            'Deal {}'.format(final_subscription_type == hubspot_utils.KEY_VALUE_DEAL_DELETION and 'deleted' or 'updated')
                        ),
                        deal_url
                    ),
                    slack_utils.KEY_ATTACHMENTS: [
                        {
                            slack_utils.KEY_TITLE: deal_name,
                            slack_utils.KEY_TITLE_LINK: deal_url,
                            slack_utils.KEY_TEXT: '*Deal Stage:* {}{}'.format(
                                display_deal_stage_value or 'Unknown',
                                deal_property_changes and '\n\n{}'.format('\n'.join(deal_property_changes)) or ''
                            ),
                            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_GREEN
                        }
                    ]
                }
            )

            if event_ids:
                ExternalEvent.objects.filter(id__in=event_ids).update(notification_sent_at=datetime.datetime.utcnow())
Ejemplo n.º 50
0
def send_survey_summary_report_slack(event, client_report, pm_report, dev_report):
    event = clean_instance(event, ProgressEvent)
    client_report = clean_instance(client_report, ProgressReport)
    pm_report = clean_instance(pm_report, ProgressReport)
    dev_report = clean_instance(dev_report, ProgressReport)

    attachments = list()
    if not client_report:
        attachments.append({
            slack_utils.KEY_TEXT: '`Client survey was not filled`',
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_RED,
        })

    if event.task.pm and not pm_report:
        attachments.append({
            slack_utils.KEY_TEXT: '`PM Report was not filled`',
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_RED,
        })

    if event.task.active_participants and not dev_report:
        attachments.append({
            slack_utils.KEY_TEXT: '`No Developer report was filled`',
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_RED,
        })
    if client_report or pm_report or dev_report:
        if client_report:
            summary_report = list()
            summary_report.append(dict(
                title='Was the last deadline met?:',
                client=client_report and (client_report.last_deadline_met and 'Yes' or 'No') or None,
                pm=pm_report and (pm_report.last_deadline_met and 'Yes' or 'No') or None,
                dev=dev_report and (dev_report.last_deadline_met and 'Yes' or 'No') or None,
                color=client_report.last_deadline_met and SLACK_ATTACHMENT_COLOR_GREEN or SLACK_ATTACHMENT_COLOR_RED
            ))

            if not client_report.last_deadline_met:
                summary_report.append(dict(
                    title='Was the client informed about missing the deadline?:',
                    client=(client_report.deadline_miss_communicated and 'Yes' or 'No') or None,
                    pm=pm_report and (pm_report.deadline_miss_communicated and 'Yes' or 'No') or None,
                    dev=dev_report and (dev_report.deadline_miss_communicated and 'Yes' or 'No') or None,
                    color=client_report.deadline_miss_communicated and SLACK_ATTACHMENT_COLOR_GREEN or SLACK_ATTACHMENT_COLOR_RED
                ))

            if client_report.deliverable_satisfaction is not None:
                summary_report.append(dict(
                    title='Are you satisfied with the deliverable?:',
                    client=(client_report.deliverable_satisfaction and 'Yes' or 'No') or None,
                    pm=None,
                    dev=None,
                    color=client_report.deliverable_satisfaction and SLACK_ATTACHMENT_COLOR_GREEN or SLACK_ATTACHMENT_COLOR_RED
                ))

            if client_report.rate_deliverables is not None:
                summary_report.append(dict(
                    title='Deliverable rating:',
                    client=client_report.rate_deliverables or None,
                    pm=pm_report and pm_report.rate_deliverables or None,
                    dev=dev_report and dev_report.rate_deliverables or None,
                    color=(client_report.rate_deliverables > 3 and SLACK_ATTACHMENT_COLOR_GREEN) or (
                    client_report.rate_deliverables < 3 and SLACK_ATTACHMENT_COLOR_RED or SLACK_ATTACHMENT_COLOR_NEUTRAL)
                ))

            if pm_report or dev_report:
                summary_report.append(dict(
                    title='Status:',
                    client=None,
                    pm=pm_report and pm_report.get_status_display() or None,
                    dev=dev_report and dev_report.get_status_display() or None,
                    color=SLACK_ATTACHMENT_COLOR_RED
                ))

                if (pm_report and pm_report.stuck_reason) or (dev_report and dev_report.stuck_reason):
                    summary_report.append(dict(
                        title='Stuck reason:',
                        client=None,
                        pm=pm_report and pm_report.get_stuck_reason_display() or None,
                        dev=dev_report and dev_report.get_stuck_reason_display() or None,
                        color=SLACK_ATTACHMENT_COLOR_BLUE
                    ))

            for item in summary_report:
                client = item.get('client', None)
                pm = item.get('pm', None)
                dev = item.get('dev', None)
                attachments.append({
                    slack_utils.KEY_TITLE: item['title'],
                    slack_utils.KEY_TEXT: '{} {} {}'.format(
                        client and 'Client: {}'.format(client) or '',
                        pm and '{}PM: {}{}'.format(
                            client_report and '*|* ' or '', pm, dev_report and ' *|*' or ''
                        ) or '{}'.format(dev_report and '*|*' or ''),
                        dev and 'Dev: {}'.format(dev) or ''),
                    slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                    slack_utils.KEY_COLOR: item.get('color', SLACK_ATTACHMENT_COLOR_NEUTRAL)
                })
        else:
            attachments.append({
                slack_utils.KEY_TEXT: '`Insufficent data for creating a summary report`',
                slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
                slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_RED,
            })

        attachments.append({
            slack_utils.KEY_TITLE: 'Reports:',
            slack_utils.KEY_TEXT: '{}{}{}'.format(
                client_report and '<{}|Client Survey>'.format(
                    '{}/work/{}/event/{}'.format(TUNGA_URL, event.task.id, client_report.event.id)) or '',
                pm_report and '{}<{}|PM Report>{}'.format(client_report and '\n' or '',
                                                          '{}/work/{}/event/{}'.format(TUNGA_URL, event.task.id,
                                                                                       pm_report.event.id),
                                                          dev_report and '\n' or '') or '{}'.format(
                    dev_report and '\n' or ''),
                dev_report and '<{}|Developer Report>'.format(
                    '{}/work/{}/event/{}'.format(TUNGA_URL, event.task.id, dev_report.event.id)) or '',
            ),
            slack_utils.KEY_MRKDWN_IN: [slack_utils.KEY_TEXT],
            slack_utils.KEY_COLOR: SLACK_ATTACHMENT_COLOR_BLUE,
        })

    owner = event.task.owner or event.task.user

    slack_utils.send_incoming_webhook(
        SLACK_STAFF_INCOMING_WEBHOOK,
        {
            slack_utils.KEY_TEXT: "*Summary Report:* <{}|{}>\nProject Owner: <{}|{}>{}".format(
                '{}/work/{}'.format(TUNGA_URL, event.task.id), event.task.summary,
                '{}/people/{}'.format(TUNGA_URL, owner.username), owner.display_name.encode('utf-8'),
                event.task.pm and '\nPM: <{}|{}>'.format('{}/people/{}'.format(
                    TUNGA_URL, event.task.pm.username), event.task.pm.display_name.encode('utf-8')
                ) or ''
            ),
            slack_utils.KEY_CHANNEL: SLACK_STAFF_PROJECT_EXECUTION_CHANNEL,
            slack_utils.KEY_ATTACHMENTS: attachments
        }
    )