Put schedule_interview and the calendar's dated things on the plugin surface (#330) #1087

Merged
tiagoagueda merged 1 commit from 330-interview-surface into main 2026-10-31 02:10:10 +00:00
Owner

A plugin pairing an event made elsewhere with something on Postulo
(postulo/postulo-dav#11) could neither make an interview nor read the
calendar's deadlines, closing dates and answer dates.

  • schedule_interview, InterviewKind and InterviewRefused are on the
    surface. The checks the form and the API made first now live in the
    service (interview_refusals): a kind that is an InterviewKind, an
    end after the start, and everybody met the owner's own contact at the
    application's company. The form asks it in clean() and the API maps
    each refusal onto the words it already answered with, so the three are
    refused alike, before anything is written. InterviewRefused is a
    ValueError whose field names the argument. The day-ahead reminder
    is made through create_reminder (#331), with the interview's actor.
  • calendar_items(user, start, end, kinds=None) reads the Calendar
    page's dated things through events_between as plain values
    (CalendarItem, in CalendarItems): kind, the page's two lines, the
    moment in the person's own zone or the day, whether it is over, the
    path and a calendar uid. It runs in the person's zone and language
    whoever calls it. A whole day carries the DayEntry the feed writes,
    and day_lines is on the surface to write it. With POSTULO_PUBLIC_URL
    unset there are no whole days (a UUID over a bare path collides
    between instances), and withheld says why.
  • As the maintainer decided: event_lines keeps no uid=, no Offer
    or JobPosting and no absolute_url on the surface.

Closes #330

Notes for review

  • On the plugin surface: schedule_interview, InterviewKind and InterviewRefused, a ValueError with a field.
    • The checks moved into one service, interview_refusals: the kind, the end after the start, and every contact being the owner's own and at the company.
    • The form, the API and plugins all get the same refusals.
    • An existing interview's contacts aren't re-checked on edit, so somebody who has left the company stays on it (#443).
  • The reminder is made through #331's create_reminder, actor included.
  • calendar_items(user, start, end, kinds=None): a plain-values view of the calendar.
    • It returns CalendarItem, CalendarItems with withheld, DayEntry and day_lines.
    • It works in the person's own time zone and language whoever calls it.
    • With no POSTULO_PUBLIC_URL, it returns no whole days, and withheld says why.
    • It returns paths, not absolute URLs.
  • Decisions the issue left open:
    • The view covers every kind by default; kinds= narrows it.
    • An unknown kind, or a range over 366 days, is a ValueError.
    • The API checks contact ids before the kind.
  • No migration and no format bump.

🤖 Generated with Claude Code

A plugin pairing an event made elsewhere with something on Postulo (postulo/postulo-dav#11) could neither make an interview nor read the calendar's deadlines, closing dates and answer dates. - `schedule_interview`, `InterviewKind` and `InterviewRefused` are on the surface. The checks the form and the API made first now live in the service (`interview_refusals`): a kind that is an `InterviewKind`, an end after the start, and everybody met the owner's own contact at the application's company. The form asks it in `clean()` and the API maps each refusal onto the words it already answered with, so the three are refused alike, before anything is written. `InterviewRefused` is a `ValueError` whose `field` names the argument. The day-ahead reminder is made through `create_reminder` (#331), with the interview's actor. - `calendar_items(user, start, end, kinds=None)` reads the Calendar page's dated things through `events_between` as plain values (`CalendarItem`, in `CalendarItems`): kind, the page's two lines, the moment in the person's own zone or the day, whether it is over, the path and a calendar uid. It runs in the person's zone and language whoever calls it. A whole day carries the `DayEntry` the feed writes, and `day_lines` is on the surface to write it. With POSTULO_PUBLIC_URL unset there are no whole days (a UUID over a bare path collides between instances), and `withheld` says why. - As the maintainer decided: `event_lines` keeps no `uid=`, no `Offer` or `JobPosting` and no `absolute_url` on the surface. Closes #330 ## Notes for review - **On the plugin surface:** `schedule_interview`, `InterviewKind` and `InterviewRefused`, a `ValueError` with a `field`. - The checks moved into one service, `interview_refusals`: the kind, the end after the start, and every contact being the owner's own and at the company. - The form, the API and plugins all get the same refusals. - An existing interview's contacts aren't re-checked on edit, so somebody who has left the company stays on it (#443). - **The reminder** is made through #331's `create_reminder`, actor included. - **`calendar_items(user, start, end, kinds=None)`:** a plain-values view of the calendar. - It returns `CalendarItem`, `CalendarItems` with `withheld`, `DayEntry` and `day_lines`. - It works in the person's own time zone and language whoever calls it. - With no `POSTULO_PUBLIC_URL`, it returns no whole days, and `withheld` says why. - It returns paths, not absolute URLs. - **Decisions the issue left open:** - The view covers every kind by default; `kinds=` narrows it. - An unknown kind, or a range over 366 days, is a `ValueError`. - The API checks contact ids before the kind. - **No migration and no format bump.** 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Put schedule_interview and the calendar's dated things on the plugin surface (#330)
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 15m15s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m55s
CI / Security audit (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
769f5ba5a3
A plugin pairing an event made elsewhere with something on Postulo
(postulo/postulo-dav#11) could neither make an interview nor read the
calendar's deadlines, closing dates and answer dates.

- `schedule_interview`, `InterviewKind` and `InterviewRefused` are on the
  surface. The checks the form and the API made first now live in the
  service (`interview_refusals`): a kind that is an `InterviewKind`, an
  end after the start, and everybody met the owner's own contact at the
  application's company. The form asks it in `clean()` and the API maps
  each refusal onto the words it already answered with, so the three are
  refused alike, before anything is written. `InterviewRefused` is a
  `ValueError` whose `field` names the argument. The day-ahead reminder
  is made through `create_reminder` (#331), with the interview's actor.
- `calendar_items(user, start, end, kinds=None)` reads the Calendar
  page's dated things through `events_between` as plain values
  (`CalendarItem`, in `CalendarItems`): kind, the page's two lines, the
  moment in the person's own zone or the day, whether it is over, the
  path and a calendar uid. It runs in the person's zone and language
  whoever calls it. A whole day carries the `DayEntry` the feed writes,
  and `day_lines` is on the surface to write it. With POSTULO_PUBLIC_URL
  unset there are no whole days (a UUID over a bare path collides
  between instances), and `withheld` says why.
- As the maintainer decided: `event_lines` keeps no `uid=`, no `Offer`
  or `JobPosting` and no `absolute_url` on the surface.

Closes #330

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 330-interview-surface from 769f5ba5a3
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 15m15s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m55s
CI / Security audit (pull_request) Has been cancelled
CI / Database tests on PostgreSQL (pull_request) Has been cancelled
CI / Browser tests (Chromium) (pull_request) Has been cancelled
to 9d908695c8
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 15m3s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 2m55s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m2s
CI / Security audit (pull_request) Successful in 1m13s
CI / Browser tests (Chromium) (pull_request) Successful in 36m3s
2026-10-30 21:53:30 +00:00
Compare
tiagoagueda deleted branch 330-interview-surface 2026-10-31 02:10:15 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo!1087
No description provided.