CommunityPro / CommunityPro/community-pro-api

Mentorship: session booking + ICS emails (Phase 6.4)

Open
#11 0 comments 0 reactions 0 assignees View on GitHub
mentorship
Dominant language
C#
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Scope
Book sessions against mentor availability, with calendar-attachment emails.

## Data model
```csharp
public sealed class Session
{
public Guid Id { get; set; }
public Guid MentorshipId { get; set; }
public DateTimeOffset StartUtc { get; set; } // stored UTC, always
public int DurationMinutes { get; set; } // 30 | 60
public SessionStatus Status { get; set; } // Scheduled | Completed | Cancelled
public string? MeetingUrl { get; set; } // mentor-provided free text (Meet/Zoom)
}
```

## Endpoints (participants of the mentorship only)
| Method | Path | Notes |
|---|---|---|
| GET | `/mentorship/{id}/slots?weekOf=` | open slots: availability minus existing sessions, computed in the mentor's IANA tz via NodaTime, returned as UTC instants |
| POST | `/mentorship/{id}/sessions` | book; validations below |
| POST | `/mentorship/sessions/{id}/cancel` | either participant, only while `Scheduled` |

## Booking validations
1. Slot falls entirely inside the mentor's availability (evaluated in mentor-local time — DST-correct via NodaTime).
2. No overlap with any of the mentor's existing `Scheduled` sessions (across all their mentorships).
3. Start ≥ 12h in the future.
4. Duration ∈ {30, 60}; mentorship is `Active`.

## Emails
Booked/cancelled → **both** parties via Brevo, with an `.ics` attachment generated via [Ical.Net](https://github.com/ical-org/ical.net) (UTC times, summary, meeting URL when present). Best-effort as always.

## Error codes
`mentorship.not_found`, `mentorship.slot_unavailable`, `mentorship.slot_conflict`, `mentorship.too_soon`, `mentorship.invalid_state`, `mentorship.forbidden`

## Dependencies
Blocked by #9 and #10.

## Acceptance criteria
- [ ] **DST boundary tests are mandatory**: a slot spanning a DST transition in e.g. `Europe/London` or `America/New_York` books correctly; test both spring-forward and fall-back weeks
- [ ] Overlap check covers sessions from the mentor's *other* mentorships
- [ ] Concurrent booking of the same slot → exactly one succeeds
- [ ] ICS content asserted in tests (times, attendees)

### Conventions (project-wide, non-negotiable)
- .NET 9, records for immutable shapes, file-scoped namespaces, primary constructors where they read well. Minimal-API endpoints grouped per module via `IEndpointModule.MapEndpoints`.
- `Result` (SharedKernel) instead of exception-driven control flow. Endpoint results map failures to ProblemDetails with the stable error codes listed above — the frontend keys off them.
- Module owns its EF Core `DbContext` mapped to its own Postgres schema. Modules never reference each other's internals — cross-module needs go through a public contract interface or an in-process domain event (`IEventPublisher`).
- All external calls (GitHub, Stripe, Brevo, Cloudinary, Meilisearch) behind interfaces owned by the consuming module.
- Every list endpoint paginated (offset is fine). xUnit tests in `tests/CommunityPro.Tests//` following the existing harness patterns (see `Members/MembersTestHarness.cs`).

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.