Skip to content

Architecture

SituationReport follows the C4 model (Simon Brown): Context → Containers → Components. The diagrams show three levels of detail — from the bird's-eye view down to individual files.


Level 1 — System Context

Who uses the system and what external systems does it interact with?

C4Context
    title System Context: SituationReport

    Person(user, "Agile Coach / PI Manager", "Analyses Jira data and generates flow metrics")

    System(sr, "SituationReport", "Toolsuite for transforming Jira raw data into flow metrics and reports")

    System_Ext(jira, "Jira", "Issue tracking system (Atlassian)")

    Rel(user, sr, "starts", "GUI / CLI")
    Rel(sr, jira, "reads raw data", "REST API / JSON export")
    Rel(sr, user, "delivers", "HTML report / PDF / XLSX")

Level 2 — Containers (Modules)

What modules exist, what technologies do they use, and how does data flow?

C4Container
    title Containers: SituationReport

    Person(user, "Agile Coach / PI Manager")

    System_Ext(jira, "Jira", "Issue tracking system")

    System_Boundary(sr, "SituationReport") {
        Container(get_data, "get_data", "Python", "Fetches Jira issues via REST API and stores JSON export (planned)")
        Container(transform_data, "transform_data", "Python · tkinter", "Reads JSON export + workflow definition, computes stage times, writes XLSX files")
        Container(build_reports, "build_reports", "Python · tkinter · Plotly", "Reads XLSX, filters issues, computes flow metrics, exports HTML/PDF")
        Container(testdata_generator, "testdata_generator", "Python", "Generates synthetic Jira JSON exports for testing (planned)")
        Container(simulate, "simulate", "Python", "Simulations and forecasting models (planned)")
    }

    Rel(user, get_data, "starts", "CLI")
    Rel(user, transform_data, "starts", "GUI / CLI")
    Rel(user, build_reports, "starts", "GUI / CLI")
    Rel(get_data, jira, "reads", "REST API")
    Rel(get_data, transform_data, "delivers", "JSON export (.json)")
    Rel(transform_data, build_reports, "delivers", "IssueTimes.xlsx · CFD.xlsx")

Data flow

Jira
  │  JSON export
get_data  ──►  transform_data  ──►  build_reports
                 │                        │
                 │  Transitions.xlsx       │  HTML report
                 │  IssueTimes.xlsx        │  PDF export
                 └  CFD.xlsx             ◄─┘

Level 3 — Components: transform_data

C4Component
    title Components: transform_data

    Person(user, "User")
    System_Ext(jira_json, "JSON export", "Jira raw data")
    System_Ext(xlsx_out, "XLSX files", "Transitions · IssueTimes · CFD")

    Container_Boundary(td, "transform_data") {
        Component(main, "__main__ / transform", "Python", "Entry point: detects GUI vs. CLI call and delegates")
        Component(gui, "gui", "tkinter", "File dialogs, log area, progress bar; runs processing in background thread")
        Component(workflow, "workflow", "Python", "Reads workflow definition file, validates markers and stage names, builds status_to_stage mapping")
        Component(processor, "processor", "Python", "Processes JSON export: carry-forward, stage times, milestone dates (First / InProgress / Closed)")
        Component(writers, "writers", "openpyxl", "Writes Transitions.xlsx, IssueTimes.xlsx, CFD.xlsx")
    }

    Rel(user, main, "starts")
    Rel(main, gui, "opens (no argument)")
    Rel(main, processor, "calls (CLI)")
    Rel(gui, workflow, "reads workflow file")
    Rel(gui, processor, "starts in thread")
    Rel(processor, workflow, "uses mapping and stage order")
    Rel(processor, jira_json, "reads")
    Rel(processor, writers, "passes IssueRecords")
    Rel(writers, xlsx_out, "writes")
File Responsibility
__main__.py / transform.py Entry point; detects GUI vs. CLI mode
gui.py tkinter UI; background thread; progress bar after 3 s
workflow.py Read, validate, and map workflow definition file
processor.py Process Jira JSON; stage times, carry-forward, milestone fallbacks
writers.py XLSX output (Transitions, IssueTimes, CFD)

Level 3 — Components: build_reports

C4Component
    title Components: build_reports

    Person(user, "User")
    System_Ext(xlsx_in, "XLSX input", "IssueTimes · CFD (from transform_data)")
    System_Ext(report_out, "Report output", "HTML · PDF")

    Container_Boundary(br, "build_reports") {
        Component(main, "__main__ / cli", "Python · argparse", "Entry point: parse CLI args, call run_reports()")
        Component(gui, "gui", "tkinter", "Filter UI, template management, exclusions, progress bar, browser and PDF export")
        Component(loader, "loader", "openpyxl", "Reads IssueTimes and CFD XLSX into typed data structures (ReportData)")
        Component(filters, "filters", "Python", "FilterConfig: date range, projects, issue type, exclusions by status/resolution")
        Component(metrics, "metrics/", "Plotly", "Plugin system with 5 metrics: Flow Time, CFD, Flow Load, Flow Velocity, Flow Distribution")
        Component(export, "export", "Plotly · WeasyPrint", "Renders HTML report and PDF from MetricResults")
        Component(stage_groups, "stage_groups", "Python", "Stage group definitions for aggregated analyses")
        Component(pi_config, "pi_config", "Python", "PI configuration: time ranges and sprint lengths")
        Component(terminology, "terminology", "Python", "Terminology mapping: custom stage labels")
    }

    Rel(user, main, "starts (CLI)")
    Rel(user, gui, "starts (GUI)")
    Rel(main, loader, "loads data")
    Rel(main, filters, "configures FilterConfig")
    Rel(gui, loader, "loads data")
    Rel(gui, filters, "configures FilterConfig")
    Rel(gui, export, "triggers export")
    Rel(loader, xlsx_in, "reads")
    Rel(filters, metrics, "delivers filtered ReportData")
    Rel(metrics, export, "delivers MetricResults (figures)")
    Rel(export, report_out, "writes")
File / Directory Responsibility
__main__.py / cli.py Entry point; argparse; run_reports()
gui.py tkinter UI; templates; exclusions; progress bar; browser/PDF export
loader.py Read XLSX → ReportData (typed dataclasses)
filters.py FilterConfig; apply_filters(); exclusion logic
metrics/base.py Abstract MetricPlugin class + MetricResult container
metrics/*.py Concrete metrics: flow_time, cfd, flow_load, flow_velocity, flow_distribution
export.py HTML rendering; PDF export via WeasyPrint
stage_groups.py Stage group definitions
pi_config.py PI time ranges, sprint lengths
terminology.py Custom terminology