feat: memo generation with filtering and sorting
This commit is contained in:
parent
239654767a
commit
08db8b8fb1
49
src/teampulse/memo.py
Normal file
49
src/teampulse/memo.py
Normal file
@ -0,0 +1,49 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from teampulse.models import AuditWindow
|
||||
|
||||
|
||||
def generate_memo(window: AuditWindow) -> str:
|
||||
filtered = [
|
||||
e for e in window.entries
|
||||
if e.display_name != window.presenter and e.display_name != window.moderator
|
||||
]
|
||||
sorted_entries = sorted(filtered, key=lambda e: e.email)
|
||||
|
||||
start = window.start_time.strftime("%H:%M:%S")
|
||||
end = window.end_time.strftime("%H:%M:%S")
|
||||
|
||||
lines = [
|
||||
"# Meeting Chat Audit",
|
||||
f"Zeitfenster: {start} – {end}",
|
||||
"",
|
||||
]
|
||||
|
||||
if not sorted_entries:
|
||||
lines += [
|
||||
f"## Teilnehmer am Vortrag von {window.presenter} (0)",
|
||||
f"_Moderator: {window.moderator} — Vortragender und Moderator ausgeschlossen_",
|
||||
"",
|
||||
"_Keine Chat-Aktivität in diesem Zeitfenster._",
|
||||
]
|
||||
else:
|
||||
lines += [
|
||||
f"## Teilnehmer am Vortrag von {window.presenter} ({len(sorted_entries)})",
|
||||
f"_Moderator: {window.moderator} — Vortragender und Moderator ausgeschlossen_",
|
||||
"",
|
||||
]
|
||||
for entry in sorted_entries:
|
||||
lines.append(f"- {entry.display_name} <{entry.email}>")
|
||||
|
||||
created = datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||
lines += ["", f"_Sortiert nach E-Mail-Adresse. Erstellt: {created}_"]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def save_memo(content: str, directory: Path = Path("."), timestamp: datetime | None = None) -> Path:
|
||||
ts = timestamp or datetime.now()
|
||||
filename = f"audit_{ts.strftime('%Y%m%d_%H%M')}.md"
|
||||
path = directory / filename
|
||||
path.write_text(content, encoding="utf-8")
|
||||
return path
|
||||
85
tests/test_memo.py
Normal file
85
tests/test_memo.py
Normal file
@ -0,0 +1,85 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from teampulse.memo import generate_memo, save_memo
|
||||
from teampulse.models import AuditEntry, AuditWindow
|
||||
|
||||
|
||||
def make_window(**kwargs):
|
||||
defaults = dict(
|
||||
presenter="Anna Bauer",
|
||||
moderator="Oliver Hofmann",
|
||||
start_time=datetime(2026, 5, 16, 10, 3, 42),
|
||||
end_time=datetime(2026, 5, 16, 10, 47, 15),
|
||||
entries=[
|
||||
AuditEntry("Thomas Wolf", "t.wolf@company.com"),
|
||||
AuditEntry("Klaus Huber", "k.huber@company.com"),
|
||||
AuditEntry("Sandra Vogel", "s.vogel@company.com"),
|
||||
],
|
||||
)
|
||||
defaults.update(kwargs)
|
||||
return AuditWindow(**defaults)
|
||||
|
||||
|
||||
def test_memo_contains_presenter_name():
|
||||
result = generate_memo(make_window())
|
||||
assert "Anna Bauer" in result
|
||||
|
||||
|
||||
def test_memo_contains_time_window():
|
||||
result = generate_memo(make_window())
|
||||
assert "10:03:42" in result
|
||||
assert "10:47:15" in result
|
||||
|
||||
|
||||
def test_memo_sorts_entries_by_email():
|
||||
result = generate_memo(make_window())
|
||||
idx_huber = result.index("k.huber@company.com")
|
||||
idx_vogel = result.index("s.vogel@company.com")
|
||||
idx_wolf = result.index("t.wolf@company.com")
|
||||
assert idx_huber < idx_vogel < idx_wolf
|
||||
|
||||
|
||||
def test_memo_excludes_presenter():
|
||||
window = make_window(
|
||||
entries=[
|
||||
AuditEntry("Anna Bauer", "a.bauer@company.com"),
|
||||
AuditEntry("Klaus Huber", "k.huber@company.com"),
|
||||
]
|
||||
)
|
||||
result = generate_memo(window)
|
||||
assert "a.bauer@company.com" not in result
|
||||
assert "k.huber@company.com" in result
|
||||
|
||||
|
||||
def test_memo_excludes_moderator():
|
||||
window = make_window(
|
||||
entries=[
|
||||
AuditEntry("Oliver Hofmann", "o.hofmann@company.com"),
|
||||
AuditEntry("Klaus Huber", "k.huber@company.com"),
|
||||
]
|
||||
)
|
||||
result = generate_memo(window)
|
||||
assert "o.hofmann@company.com" not in result
|
||||
assert "k.huber@company.com" in result
|
||||
|
||||
|
||||
def test_memo_empty_window():
|
||||
window = make_window(entries=[])
|
||||
result = generate_memo(window)
|
||||
assert "Keine Chat-Aktivität" in result
|
||||
|
||||
|
||||
def test_memo_contains_moderator_note():
|
||||
result = generate_memo(make_window())
|
||||
assert "Oliver Hofmann" in result
|
||||
|
||||
|
||||
def test_save_memo_writes_file(tmp_path):
|
||||
window = make_window()
|
||||
path = save_memo(generate_memo(window), directory=tmp_path, timestamp=datetime(2026, 5, 16, 10, 51))
|
||||
assert path.exists()
|
||||
assert path.name == "audit_20260516_1051.md"
|
||||
assert "Anna Bauer" in path.read_text()
|
||||
Loading…
x
Reference in New Issue
Block a user