feat(events): move assignment eligibility onto parts, merge midweek talk kinds - #364
Merged
Conversation
… campaigns
The campaigns migration collapsed all legacy type='campaign' attributions
into one synthetic ended 'Campagne' per congregation. This follow-up data
migration splits each synthetic into one campaign per date cluster (a gap of
more than 30 days between an attribution's start and the latest end seen so
far opens a new cluster), named by its period ('Campagne 03/2024'),
repoints the attributions and drops the emptied synthetic. Synthetics are
recognized by the backfill's exact stamps (name + activatedAt = startDate +
endedAt = endDate), so campaigns that went through the real lifecycle —
even ones named 'Campagne' — and single-cluster synthetics are untouched.
Single data-modifying CTE chain (temp tables don't survive Prisma's
statement execution); verified against seeded multi-cluster, decoy and
single-cluster states on the dev database.
…alk kinds
Trying the preset feature showed eligibility sits at the wrong level: two
parts of the same kind can be done by completely different roles, so which
roles may fill a slot belongs to the part, not to the kind. The preset keeps
capability only (reader slot, slot labels, external-speaker rule, share
message).
- Drop PartPresetAllowedRole (schema, services, preset editor pickers) and
the preset-wins resolution rule; part rows are the single source of truth
- Part editors always show the role pickers, preset chosen or not
- Migration materializes the previously effective eligibility into
TemplatePartAllowedRole/EventPartAllowedRole so no part widens or narrows
- With eligibility gone, nothing distinguishes the three seeded midweek talk
kinds: merge spiritual-gems, spiritual-pearls and christian-life-talk into
one midweek-talk kind ("Sujet VCM"), repointing existing parts
- Archive format 2.6: no part-preset-allowed-roles file; importing a 2.5
archive folds the legacy kinds into midweek-talk and discards preset-level
eligibility with a log line
… shows Review of the eligibility move found the reader half of 78a9219 reopened. The reader picker is hidden whenever the chosen kind has no second slot, an unrendered picker submits nothing, and the schema turns that absence into [] — so saving a part after giving it such a kind deleted the reader restriction it already carried and widened the slot to every member. The form now declares which pickers it drew, and partAllowedRolesToWrite maps that to the services' undefined ("not managed") versus [] ("managed, and empty"). Declaring it beats re-deriving it in the action: the render condition and the write decision were two copies of one rule in different features, free to drift, which is how this arrived the first time. Also from the review: - validateImport now warns, before the user confirms, that a v2.5 archive loses its preset-level eligibility and that the three midweek kinds merge with their custom wording dropped. A logger.warn alone told nobody who would act on it. - The migration carries an integration test that runs the shipped SQL over a fixture and asserts each part keeps the eligibility it actually resolved to. It fails if the DELETE stops matching on asKind. - The migration claimed nothing widens. Merging the three kinds does widen allowExternalSpeaker for parts that were Joyaux or Perles, since one kind holds one answer; it keeps yes deliberately, and now says so. - The PartPreset doc comment listed eligibility under capability, where a reader deciding a new field's home would have been misled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Trying the preset feature showed that assignment eligibility (which roles may fill a slot) was modeled at the wrong level. Two parts of the same kind — two "Sujet VCM" — can legitimately be done by different populations depending on where they sit in the programme. Eligibility is a property of the slot, not of the kind. Keeping it on the preset also required a subtle precedence rule (preset wins only when non-empty, because empty means "any member"), hidden role pickers in the part editors, and dormant part-level rows — all complexity serving the wrong model.
What
Eligibility moves onto the parts
PartPresetAllowedRoleis removed: schema model,setPartPresetAllowedRoles, theresolveAllowedRoleIds/partAllowedRolesToWriteprecedence module, and the preset editor's role pickersgetPartAssignmentAllowedRoleIdsand the batch programme query now read the part's own rows onlyTemplatePartAllowedRole/EventPartAllowedRole(preset roles replace part rows only for slots the preset had configured), so existing data behaves identically, then drops the tableSeeded kinds simplified
spiritual-gems,spiritual-pearlsandchristian-life-talkmerge into onemidweek-talkkind ("Sujet VCM" / "Midweek Talk") with a generic share message that includes{{partName}}Data transfer
part-preset-allowed-roles.ndjsonis gonemidweek-talkrow (all three old ids map to it, so parts stay linked) and discards preset-level eligibility with a warning logTesting
pnpm test:unit— 3108 passingpnpm test:integration— 322 passing (includes the data-transfer round-trip)pnpm test:lint,pnpm test:typecheck, and all architecture guards passmidweek-talkpresent per congregation, linked parts repointed, join table dropped