Repository navigation
feat(sub-event): event sub-event counts + guest participations (AIRLST-5445) - #145
Open
mish-ka-mishka wants to merge 38 commits into
Open
mish-ka-mishka wants to merge 38 commits into
mish-ka-mishka wants to merge 38 commits into
Conversation
…s (AIRLST-5445)
Core adds two fields to every event object (EventApiResource): is_parent
(boolean) and sub_events_count (integer). They appear on GET /events/{uuid},
the company events list and the contact events list. The sub-events list
endpoint itself is session-authed and stays outside this SDK.
Core PR: airlst/core#5649
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…AIRLST-5445)
Core M1.2 adds sub_event_participations to GET /events/{uuid}/guests/{code}
(GuestApiResource): the guest's sub-event participations with their
per-sub-event status. The key is present only while the company's
sub-events module is active, so the field is optional. The assignment
endpoint is session-authed and stays outside this SDK.
Core PR: airlst/core#5649
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…PI (AIRLST-5445)
GET /api/events/{event}/sub-events is now key-authed in core (the
ticket's two-surface rewording), so it enters SDK scope. The resource
returns sub-events with quota state; assigning guests ships with M1.2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ment (AIRLST-5445) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… (AIRLST-5445)
Core M1.2 ships POST /events/{uuid}/guests/{code}/sub-events on the
key-authed Suite API. Guest.assignSubEvents(code, subEventIds) posts the
batch and returns the created participations with their per-sub-event
status (invited, or waitlisted when the quota is full). The API runs the
batch in one transaction and rolls back on any error.
Core PR: airlst/core#5649
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…age root (AIRLST-5445) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The comments predate the key-authed API surface. SubEvent.list() and Guest.assignSubEvents() now cover both operations in this SDK. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…(AIRLST-5445) SubEventQuotaInterface types `guest_group_name`, but no test exercised it and the README never mentioned it, so the one field whose presence on this endpoint is new went unverified. Core only started returning it here once the guestGroup eager load moved out of the suite page and into the action that the page and the key-authed endpoint share — before that the endpoint omitted the key while the page emitted it. The test asserts both halves of the contract: absent on the default quota, present as a locale-keyed object on a group quota.
…ngs, participation extended fields (AIRLST-5446) Mirror the core M2 foundation on the key-authed API: - SubEventInterface gains released_at (GM-facing bookability gate, null while unreleased). - SubEventQuotaInterface gains guest_manager_id and guest_manager_name — a quota row is now a group row, a guest-manager row or the default row. - assignSubEvents() accepts optional participation extended-field values keyed by sub-event UUID, and its response carries overlap_warnings (groups of overlapping sub-events; a warning, never a block). No version bump — ships in the open 0.0.25-beta PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…IRLST-5446) Mirror the guest-manager surface of the SubEvents API. Guest managers exist only on the parent event. A parent-scoped manager acts across the parent and its released sub-events, so the manager is named by its UUID in the path. Add three GuestManager methods: - listSubEvents() reads the released sub-events with the manager's own contingent. It reports booked, limit and remaining. limit and remaining are null when the manager has no quota row. - assignGuestSubEvents() books one of the manager's guests onto released sub-events. It uses the same transaction and response body as Guest.assignSubEvents(). - promoteSubEventParticipation() promotes a waitlisted participation. Export GuestManagerSubEventContingentInterface from the package root. SubEvent.list() stays the full integrator view. It returns released and unreleased sub-events alike. The README now names the guest-manager methods as the surface a guest-manager consumer must use instead. The version stays 0.0.25-beta. This change ships in the open PR #145. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…RLST-5446) GuestManager.assignGuestsSubEvents() books up to 200 of the manager's guests onto the same released sub-events in one call. It mirrors the core endpoint core#5649 adds: bounded and synchronous, one result entry per guest carrying the same participations/overlap_warnings pair as the single-guest method plus guest_code and error, and in the order the codes were posted. Isolation is per guest: a guest that fails carries its own error while the rest of the call still books, and a guest that already participates is skipped rather than rejected, so a pre-assignment is safe to run twice. Bulk assignment exists on the guest-manager surface only — an integrator key uses Guest.assignSubEvents() one guest at a time, because a bulk route outside that surface would skip the manager-ownership and released-sub-event rules. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ion text (AIRLST-5446) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… (AIRLST-5447) Mirrors the M3 core additions (airlst/core#5649): - Guest.listSubEvents(): GET /events/{event}/guests/{code}/sub-events — every sub-event with the guest's participation (null while not assigned) and a guest-specific has_free_seat (R40). false means a confirm or a new assignment for THIS guest would be waitlisted. - Guest.updateSubEventParticipation(): PATCH .../sub-events/ participations/{id} with confirmed|declined. A confirm from the waitlist re-checks quotas (422 while full, the guest stays waitlisted); a cancelled parent guest blocks a confirm (422); declines are always allowed; a foreign guest's participation is 404. Optional sendAutomatedEmail (API default true). - SubEventInterface.send_status_emails: the per-SubEvent auto-send switch (default off). - EmailTemplateInterface.sub_event_id + sub_event_status_hook: the per-SubEvent status email hook, mutually exclusive with booking_status_hook. Same branch and version (0.0.25-beta) as the rest of the sub-events work; release only after the core PR deploys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent-subevent-counts # Conflicts: # package.json
…response (AIRLST-5447) Core now derives the guest's status on the parent event from its sub-event participations, in the same transaction as the answer, and the RSVP endpoint reports it as `data.guest.status`. The landing page renders the new state without a second request. The status is the guest's real one, not always one of the three derived values: a guest held at `listed` or `requested` is not moved to `invited`, and one in the payment-owned `unpaid` or `checkout` states is not moved at all. The new exported `BookingStatus` type carries all nine cases. Only this endpoint returns the field. The assign endpoints do not: at assign time the derived value carries no information, and their response type is shared with the guest-manager resource, which must stay byte-identical. Core PR: airlst/core (AIRLST-5447, M3b). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ign endpoint (AIRLST-5447) Review follow-up. The assign endpoint derives the guest's parent status too, so it gained a 422 on `limits` that callers have to expect: a request that used to answer 201 can now be refused when the derived status no longer fits the parent event's guest limit, and nothing is written. The derived write is silent there — an assignment is an administrative act and must not mail an invitation to a guest who already answered. Only the guest's own RSVP sends a parent status email. The response deliberately does not report the derived status: a fresh assignment derives `invited`, which tells the caller nothing it does not already know. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…st (AIRLST-5534)
GET /events/{event}/guest-managers/{manager}/sub-events gains three
nullable numbers: guest_group_limit, guest_group_used and
guest_group_remaining. A manager that reaches a SubEvent through its own
guest group needs the numbers of the contingent it books against; its own
limit and remaining are null in that case. guest_group_used counts every
guest of the group, not only the ones this manager brought.
Core also narrows what the endpoint returns: a manager reaches a SubEvent
only when it is released AND carries an applicable quota row — one for the
manager, or one for its guest group. The default row grants nothing; an
exhausted row still grants access. The docs say so on the method, the
interface and in the README.
Quota rows themselves are still never exposed on this surface.
…nt and import (AIRLST-5578) Core adds an optional boolean waitlist_all_subevents_on_limit. When any targeted SubEvent has no free seat, every participation of the call is created as waitlisted instead of only the exhausted one. It defaults to false, so an existing caller sees no change. Endpoints that accept it, and the SDK methods that carry it: - Guest.assignSubEvents, as an optional fourth argument - GuestManager.assignGuestSubEvents, as an optional fifth argument - GuestManager.assignGuestsSubEvents, as an optional fifth argument, per guest - Guest.processImport, as waitlist_all_subevents_on_limit on the body interface The key is omitted from the request body when the argument is not given, so the serialized payload of an existing call is unchanged. On the import the flag governs the SubEvent membership columns only. A per-SubEvent column that names an explicit status still wins. It does not make the import itself transactional. Version stays 0.0.25-beta: this rides on the open sub-events SDK branch and is not released on its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…irror guest promote (AIRLST-5448, ACP-30143) Mirrors core M4a. Every participation object carries `waitlist_cause`, `waitlist_cause_quota_id` and `queue_position`. The guest-manager contingent reports `waitlisted` and `guest_group_waitlisted`. Both promote endpoints answer with `data.warnings` (`queue_skipped`, a warning only). Adds `Guest.promoteSubEventParticipation()` for the key-authed guest promote endpoint that core shipped in 2094d90047 (ACP-30143) and that the SDK did not mirror yet. The response carries the participation, the derived parent guest status and the warnings. No version bump: the branch already carries 0.0.25-beta. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…-5842 C9) Guest.list() accepts includeSubEventParticipations. With it, core adds sub_event_participations to every guest of the page, in the same shape as Guest.get(), while the company's sub-events module is active. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…C10) SubEventInterface gets response_deadline_at, reminder_at and reminder_sent_at. GuestSubEventInterface gets response_deadline_at. The docs of the guest RSVP and the guest promote name the new 422 after the deadline; a decline stays allowed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilter (AIRLST-5842 C2)
SubEvent.create() and SubEvent.update() call the new key-authed core
endpoints POST /sub-events and PATCH /sub-events/{subEvent}.
SubEvent.list() takes an optional key filter. The sub-event and the
guest-manager contingent carry the integration key and the descriptive
content. The create and update bodies accept the C10 deadline fields.
Core: airlst/core 883a9d4fe0 on AIRLST-5842-side-events (PR #6255).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SubEvent gets uploadImage() and deleteImage(). The upload sends the file as multipart with POST, because core reads multipart bodies on POST only. The sub-event, guest sub-event and guest-manager contingent interfaces get image_url. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irlst/sdk-js into HEAD # Conflicts: # README.md # src/resources/SubEvent.ts # tests/resources/SubEvent.spec.ts
SubEvent.syncQuotas() calls the new key-authed core endpoint
PUT /sub-events/{subEvent}/quotas. It replaces the complete matrix, and
an empty array clears it.
Core: airlst/core e243696c94 on AIRLST-5842-side-events (PR #6255).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irlst/sdk-js into HEAD # Conflicts: # README.md # src/resources/SubEvent.ts # tests/resources/SubEvent.spec.ts
The participation status union gets planned: a row assigned while its
sub-event is in planning. SubEventInterface reports
invitations_sent_at, null while the sub-event is in planning.
SubEvent.create() takes plan_before_invitation; update() does not.
SubEvent.sendInvitations() calls the new key-authed core endpoint
POST /sub-events/{subEvent}/send-invitations (202, planned_count).
GuestManager.promoteSubEventParticipation() takes planned, the only
target while the sub-event is in planning. The guest promote and the
email template hook stay without planned, as in core.
Core: airlst/core c24d363524 on AIRLST-5842-side-events (PR #6255).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SubEvent.updateParticipation() writes one participation as the
integrator, mainly { status: 'cancelled' }. GuestManager
.cancelSubEventParticipation() cancels a participation of the manager's
own guest. Both keep the row as cancelled and free its seat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Guest.assignSubEvents(), GuestManager.assignGuestSubEvents() and GuestManager.assignGuestsSubEvents() take mandatory as a new last argument. A mandatory row is confirmed without an RSVP and never goes on the waitlist. The participation reports is_mandatory. Quota rows report mandatory, and the syncQuotas() and create() bodies accept it. The JSDoc says that only a guest-group row can be mandatory, because the API responds 422 otherwise. The RSVP JSDoc says that a mandatory row responds 422. Core: airlst/core 8c6804f43e on AIRLST-5842-side-events (PR #6255). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ST-5842 C11)
Guest.bookSubEvent(code, subEventId, { extendedFields, sendAutomatedEmail })
books one open sub-event as the guest. A free seat confirms at once; a full
quota row or a full capacity waitlists with a cause. The JSDoc lists the
422 and 404 cases.
SubEventInterface gets capacity, and the create and update bodies accept
it. SubEventWaitlistCause gets 'capacity' for the overall cap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every object payload in the SDK is a snake_case body interface that goes to the API as it is (JSON.stringify(body)). bookSubEvent() now follows that convention: BookSubEventBodyInterface with extended_fields and send_automated_email replaces the camelCase options object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SubEventParticipationInterface gets the read-only booked_by_guest_at. Core sets it when the guest books the seat through bookSubEvent(), also on a re-booking. It stays null for rows that an integrator, a guest manager or an admin assigned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mirror core F3. The participation status `planned` is now `listed`. The create flag `plan_before_invitation` is replaced by `default_assignment_status` (`listed` or `invited`) on create and update. SubEventInterface and the guest-manager contingent return the field. The sendInvitations() response reports `listed_count`. The API no longer accepts the old names. The version stays 0.0.25-beta. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SubEventInterface and the create and update bodies get assignment_rule and assignment_mode, with the rule tree types. Participations get the read-only assigned_by_rule_at and rule_mismatch_at. The quota row loses mandatory: the sub-event rule replaces it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every sub-event interface carries extended_fields: the values of the event's subEventDetails extended fields, keyed by field key. The create and update bodies accept extended_fields. Core checks each value against its definition and refuses an unknown key with 422. An update merges the values, and a key with null clears that one value. Core: airlst/core 149b431901 on AIRLST-5842-feedback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irlst/sdk-js into lane-b-sdk # Conflicts: # src/interfaces.ts
Mirror core d49bd4f032. Every sub-event response carries waitlist_enabled:
SubEventInterface, GuestManagerSubEventContingentInterface and
GuestSubEventInterface. SubEvent.create() and update() accept it (default
true on create).
With false, an assignment without a free seat responds 422 on
sub_event_ids.{index} ("This SubEvent is fully booked.") instead of a
waitlisted row. The docs on Guest.assignSubEvents(), bookSubEvent(),
listSubEvents() and the guest-manager assign methods say so. The bulk
guest-manager call reports the refused guest in its own entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
Core changes from airlst/core#5649 (AIRLST-5445, SubEvents M1):
is_parent(boolean) andsub_events_count(integer) — onEvent.get(),Event.list()andContact.getEvents()(all serialize throughEventApiResource).Guest.get()) gains optionalsub_event_participations— the guest's sub-event participations with their per-sub-event status. The key is present only while the company'ssub-eventsmodule is active.SubEventresource:new SubEvent('event-uuid').list()→GET /events/{uuid}/sub-events(key-authed). Each sub-event carries its quota state:participations_count(occupying = invited + confirmed) andquotaswithlimit/used;guest_group_id: nullmarks the default quota. Group quotas also carryguest_group_name(locale-keyed).Guest.assignSubEvents(code, subEventIds)→POST /events/{uuid}/guests/{code}/sub-events(key-authed). Assigns the guest to the sub-events in one transaction and returns the created participations with their per-sub-eventstatus—invited, orwaitlistedwhen the quota is full. Any error rolls back the whole batch; a sub-event of another event, or one the guest already participates in, responds 422.M3 additions (AIRLST-5447)
Guest.listSubEvents(code)→GET /events/{uuid}/guests/{code}/sub-events(key-authed). The registration-form read (R40): every sub-event with the guest'sparticipation(null while not assigned) and a guest-specifichas_free_seat—falsemeans a confirm or a new assignment for this guest would be waitlisted.Guest.updateSubEventParticipation(code, participationId, status, sendAutomatedEmail?)→PATCH /events/{uuid}/guests/{code}/sub-events/participations/{id}(key-authed). The guest RSVP:confirmedordeclinedonly. A confirm from the waitlist re-checks quotas (422 while full — the guest stays waitlisted); a cancelled parent guest blocks a confirm (422, reactivate on the parent event first); declines are always allowed; a foreign guest's participation is 404.SubEventInterface.send_status_emails— the per-SubEvent auto-send switch for status emails (default off).EmailTemplateInterface.sub_event_id+sub_event_status_hook— the per-SubEvent status email hook, mutually exclusive withbooking_status_hook.Same version (
0.0.25-beta), unreleased.Version
0.0.25-beta. npmlatestis now the stable0.0.24(republished 2026-08-24), so0.0.25-betais the correct next pre-release and never published — the merge from masterkept it over master's
0.0.24.Release with
--prerelease(the version carries-beta), and only once0.0.25-betais on
master— the publish workflow reads the version from master'spackage.json,not from the tag.
🤖 Generated with Claude Code