Repository navigation
feat(publishers)!: drop the Member.type column - #378
Merged
Merged
Conversation
Final step: PioneerEnrolment has been the source of truth for a member's standing pioneer status since the plan/actual split, and the previous release moved every reader onto the stints and backfilled anyone holding a type without one. This removes what nothing reads any more, plus the CHECK constraint that referenced it (dropped first, or the column drop fails on the dependency). Two behaviours had to be translated rather than deleted, because the column was carrying them: Turning off the permanent-auxiliary profile used to flip every auxiliary member's cached type. It now closes their ongoing auxiliary stints at the current month via endOngoingEnrolmentsOfType — the same intent against the source of truth, and it keeps the history of what they actually did. The old version was already incoherent: it flipped the cache and left the stints open, so the two disagreed immediately. Filtering the publisher list by type now filters on stints — an ongoing stint of that type, or for Normal the absence of one. A single-month auxiliary is closed, so it still reads as Normal, exactly as the column did. The create form no longer offers a pioneer type. A pioneer appointment is an enrolment with a period, made from the pioneer section of the edit page, which is where the edit form already sent people. The form schemas drop the field, so a member is created Normal and appointed afterwards. Also: the S-21 export and the group roster derive the status from the stints; the archive export stops emitting the field and the importer ignores it on older archives; the activity-derived backfill loses its `memberType` fallback, so contiguous auxiliary months now backfill as single-month stints — the snapshots cannot distinguish a monthly auxiliary from a permanent one, and single-month is the safe guess because it grants no standing status. Three readers were invisible to the compiler and only failed at runtime: a `where` clause inside an `OR`, a spread-built filter, and a spread `select`. They were found by applying the migration locally and running the whole suite against a database without the column, which is the only check that catches this class.
…ry close Two real defects from review, both in the path that runs when a congregation turns off the permanent-auxiliary profile. A future-dated stint made the whole settings save fail. The create form offers start years from -2 to +2, so an auxiliary appointment can be dated ahead. Closing it at the current month is an end before its start, which closeEnrolment rejects — and because the close runs congregation-wide, that one stint threw and took every other member's close with it. Stints that have not started are now left open and counted in the return value rather than attempted. The close month came from the server's clock. Closing picks a MONTH, so a server an hour either side of midnight on the 1st dated it to the wrong one. It now takes the congregation's clock via zonedNow, matching how pioneer-goals and the dashboard already resolve "now" for congregation-scoped work. Also from review: - An integration test for the standing-type filter. The unit test asserts the `where` shape, which cannot tell whether Prisma builds SQL that selects the right people — and this branch already produced three column reads that typechecked and failed only at runtime. It pins that a closed single-month auxiliary reads as Normal. - A test that the bulk close spans several members, which the single-member cases never exercised. - `getPublishersWithGroup`'s filter option is now `standingType`, matching the rename the role predicate already took; it selects on stints, not on a member field. - The S-21 export selects only the stint fields it reads, via an ENROLMENT_PERIOD_SELECT kept beside EnrolmentPeriod so the two cannot drift. It was fetching whole rows for every publisher in a congregation-wide zip to read three fields. - Eight test names still described setting `Member.type`; they assert standing status.
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.
Final step of removing
Member.type. It cached a member's standing pioneer status;PioneerEnrolmentis the source of truth for the same fact and has been since the plan/actual split — the schema comment on that model already said so. The previous release moved every reader onto the stints and backfilled anyone holding a type without one, so this removes what nothing reads any more.The
member_pioneer_requires_baptismCHECK is dropped first; Postgres refuses to drop a column a constraint still references.Two behaviours were translated, not deleted
Turning off the permanent-auxiliary profile. It used to flip every auxiliary member's cached type. It now closes their ongoing auxiliary stints at the current month, via a new
endOngoingEnrolmentsOfType— the same intent against the source of truth, keeping the history of what they actually did. The old version was already incoherent: it flipped the cache and left the stints open, so the two disagreed immediately, and after the previous PR the recompute would simply have undone the demotion.Filtering the publisher list by type. Now filters on stints — an ongoing stint of that type, or for Normal the absence of one. A single-month auxiliary is closed, so it still reads as Normal, exactly as the column did.
One deliberate product change
The create form no longer offers a pioneer type. A pioneer appointment is an enrolment with a period, made from the pioneer section of the edit page — which is where the edit form already sent people (
hideTypeSelect). A member is created Normal and appointed afterwards. This also closes the hole that produced pioneer-typed members with no stint in the first place.Also
The S-21 export and the group roster derive the status from the stints (the group roster turned out to select the column and never render it). The archive export stops emitting the field; the importer ignores it on older archives. The activity-derived backfill loses its
memberTypefallback, so contiguous auxiliary months backfill as single-month stints — snapshots cannot distinguish a monthly auxiliary from a permanent one, and single-month is the safe guess because it grants no standing status.Three readers the compiler could not see
A
whereclause inside anOR, a spread-built filter, and a spreadselectall pass typecheck and fail at runtime. They were found by applying the migration locally and running the whole suite against a database without the column — the only check that catches this class, and worth repeating for any future column removal.Verified
3438 unit, 412 integration, and all eight architecture gates — against a database where the column is actually gone, not just against the schema. TDD for the new service function (
endOngoingEnrolmentsOfTypetests written first) and for the schema change; the publisher-filter tests were written after the fact, so I proved them load-bearing by restoring the old filter and watching them fail.Merge order
unitae-platformfeat: redesign display board UX #68 — must be deployed before this merges. Platform CD applies this repo's migrations before rolling its own image.unitae-platformfix: improve unsaved changes guard across all forms #69 — the schema copy, alongside or after this.