# Origamy playbook spec v1. Reference: /playbooks/spec-format/
spec_version: 1
id: base.weekly-team-report
title: Weekly report to a team
sector: base
source:
  kind: engagement
  date: 2026-10-31
  ref: eng-2026-10-church-a
  notes: >-
    The weekly list and the monthly summary from a real build: scheduled reports to teams, built
    on saved questions, with a zero alert and segment sizes. Copied as built, in neutral words.
derived_from: church.first-timer-to-member
vocabulary:
  person: person
  people: people
  group: team
summary: >-
  A team gets an email every week with the new people, a list of who they are, where everyone
  stands, and how the follow-up tasks are going. An optional monthly summary compares with the
  month before.
when_to_use:
  - A team acts on new sign-ups, enquiries or form entries and wants the week's list in their inbox.
  - Leaders want a short monthly summary without opening the dashboard.
  - You want a warning when nothing came in, because that usually means data entry was missed.

requires:
  data_in:
    - how: public_form
      what: "Whatever records your key event: an Origamy form (onboarding.submitted), a sheet or CSV imported as events, or your app."
  channels:
    - channel: email
      for: The reports themselves
      needs: Nothing extra. Reports come from Origamy to the team members' own sign-in addresses.
  events:
    - "{{ params.key_event }}"
  traits: []

parameters:
  - key: team_name
    ask: true
    question: Which team gets the weekly report?
    label: Report team
    type: team_name
    default: Operations
  - key: key_event
    ask: true
    question: Which event counts as a new person for this report? (a form submission, a sign-up…)
    help: Pick from your workspace's events. Forms send onboarding.submitted.
    label: Key event
    type: event_name
    default: onboarding.submitted
  - key: list_columns
    ask: true
    question: Which details should the weekly list show? (event properties, not phone numbers)
    label: List columns
    type: list
    default: [first_name, last_name]
  - key: weekly_cron
    ask: true
    question: When should it arrive?
    label: Weekly send time
    type: cron
    default: "0 8 * * 1"   # Monday 08:00
  - key: monthly_summary
    ask: true
    question: Should leaders also get a monthly summary? Who?
    label: Monthly summary
    type: boolean
    default: true
  - key: leaders_team
    label: Monthly summary team
    type: team_name
    default: Leadership
  - key: timezone
    label: Time zone for the schedule
    type: timezone
    default: "{{ workspace.timezone }}"
  - key: monthly_cron
    label: Monthly send time
    type: cron
    default: "0 9 1 * *"   # 1st of the month, 09:00

timings:
  - "Weekly report: {{ params.weekly_cron }} in {{ params.timezone }}, covering the last 7 days."
  - "Monthly summary: {{ params.monthly_cron }}, covering the previous month and compared with the month before."

customer_must:
  - Add people to the {{ params.team_name }} team (and {{ params.leaders_team }} for the summary). A report to an empty team reaches nobody.
  - Open each report and press Send now once to check it looks right.
  - Switch the reports on.
  - The list includes names. Reports only go to team members inside your workspace; keep it that way.

objects:
  - ref: team_report
    kind: team
    about: Gets the weekly report.
    body: { name: "{{ params.team_name }}" }
  - ref: team_leaders
    kind: team
    when: { param: monthly_summary, equals: true }
    about: Gets the monthly summary.
    body: { name: "{{ params.leaders_team }}" }

  - ref: q_new_people
    kind: saved_question
    about: How many people the key event brought in the report's period.
    body:
      name: "Report: new people"
      data_plane_id: default
      viz_type: number
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: "{{ params.key_event }}" }
        aggregations: [{ fn: distinct, field: canonical_user_id, alias: people }]
  - ref: q_new_people_list
    kind: saved_question
    about: The list of new people, one row per event.
    body:
      name: "Report: new people (list)"
      data_plane_id: default
      viz_type: table
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: "{{ params.key_event }}" }
        aggregations: [{ fn: count, alias: entries }]
        breakouts:
          $each: params.list_columns
          $value: { field: "properties.{{ item }}" }
        limit: 500
  - ref: q_per_week
    kind: saved_question
    about: New people per week, for the monthly summary.
    body:
      name: New people per week
      data_plane_id: default
      viz_type: bar
      viz_settings: {}
      visibility: workspace
      query_ast:
        table: events
        filters:
          operator: and
          conditions:
            - { field: event_name, op: eq, value: "{{ params.key_event }}" }
        aggregations: [{ fn: distinct, field: canonical_user_id, alias: people }]
        breakouts: [{ field: timestamp, bucket: week }]
        order_by: [{ field: timestamp, direction: asc }]

  - ref: report_weekly
    kind: report
    about: The week's new people, with a warning when there were none, and the task summary.
    body:
      name: "Weekly: new people"
      description: The last 7 days of new people, the list, and how follow-up tasks are going.
      schedule_cron: "{{ params.weekly_cron }}"
      timezone: "{{ params.timezone }}"
      enabled: false
      spec:
        period: last_7_days
        compare: none
        week_start: monday
        sections:
          - id: count
            kind: saved_question
            title: New people this week
            viz: number
            params: { question_id: "{{ ref.q_new_people.id }}" }
            alert: { op: eq, value: 0, text: "Nobody new this week. If entries were collected on paper or elsewhere, check they were entered." }
          - { id: list, kind: saved_question, title: Who they are, viz: table, params: { question_id: "{{ ref.q_new_people_list.id }}" } }
          - { id: tasks, kind: tasks_summary, title: Follow-up tasks, params: {} }
      recipients: [{ type: team, id: "{{ ref.team_report.id }}" }]
      channel_policy: { mode: email_only, pii_in_email: true }
  - ref: report_monthly
    kind: report
    when: { param: monthly_summary, equals: true }
    about: Last month's numbers compared with the month before, without names.
    body:
      name: "Monthly: summary"
      description: The previous month compared with the month before.
      schedule_cron: "{{ params.monthly_cron }}"
      timezone: "{{ params.timezone }}"
      enabled: false
      spec:
        period: previous_month
        compare: previous_period
        week_start: monday
        sections:
          - { id: m_count, kind: saved_question, title: New people, viz: number, params: { question_id: "{{ ref.q_new_people.id }}" } }
          - { id: m_weeks, kind: saved_question, title: By week, viz: bar, params: { question_id: "{{ ref.q_per_week.id }}" } }
          - { id: m_tasks, kind: tasks_summary, title: Follow-up tasks, params: {} }
      recipients: [{ type: team, id: "{{ ref.team_leaders.id }}" }]
      channel_policy: { mode: email_only }

eval:
  name: 60_base_weekly_team_report
  mode: task
  vertical: ""
  prompt: >-
    Every Monday morning, email our operations team a list of everyone who signed up in the
    last week, and warn them if nobody did. Once a month send the managers a summary compared
    with the month before.
  expect_artifacts: [report]
  forbid_terms: []
