Meeting Report

Last step of our application is to report all collected data back to the SLACK_CHANNEL

This is going to be again the scheduled event but this time called send_report. We will schedule this event after send_questions and give users enough time to respond (30m ~ 2h).

Implementation will take place again inside standup_bot/scheduled.py file.

Where we are going to write 3 functions in a style that is easy to convert into asynchronous code.

  • one_report - Send report of 1 user to the SLACK_CHANNEL
  • all_reports - Iterate through all reports collected that day and send them to the SLACK_CHANNEL
  • send_report - Our entry point function, which starts the whole orchestra.

Sending one report

In this case we assume we already have our report object available. And all we need to do is to send a request to the Slack and return response.

53
54
55
56
57
58
59
60
61
62
63
64
65
def one_report(report):
    """Show report of one user."""
    user_id = report.user_id

    response = SC.chat_postMessage(
        channel=SLACK_CHANNEL,
        username=report.display_name,
        icon_url=report.icon_url,
        text=f"*{report.display_name}* posted and update for stand up meeting.",
        blocks=report_block(QUESTIONS, report.answers)
    )

    return user_id, response

All reports

In method all_reports we are going to query for all reports from a given day and apply one_report on each.

68
69
70
71
72
73
74
75
76
77
def all_reports(report_id):
    """Show reports of all users."""
    reports = Report.query(report_id, Report.report_user_id.startswith(report_id))

    SC.chat_postMessage(
        channel=SLACK_CHANNEL,
        text=f"Here are the standup results from *{dt.datetime.strptime(report_id, '%Y%m%d')}*.",
    )
    for report in reports:
        yield one_report(report)

Using a generator is very similar to asynchronous programming in Python. So if you are interested into async python but not yet familiar with generators, I strongly suggest to start there.

Send report

Now we have everything ready and all we need to do is to call function all_reports.

80
81
82
83
def send_report(report_id):
    """Entry point for sending reports."""
    results = list(all_reports(report_id))
    LOGGER.info("Sent report log: %s", results)

Now we can let lambda_handler decide what is the appropriate entry point (send_report or send_questions)

Note that explanation of sending report and question took a bottom up approach. Where we first implemented a single (atomic) operation and in next steps we simply run this in a loop. You can use this approach in asynchronous version of this application and run all_reports at the same time, instead iterating through each.