# Business Logic Model — Unit: Offerings ## Flow 1: Create/Update an Offering (with Featured Exclusivity) ```mermaid sequenceDiagram box rgba(246,224,94,0.4) Admin participant Admin as CMS Administrator end box rgba(99,179,237,0.4) Frontend participant Form as OfferingFormPage end box rgba(159,122,234,0.4) Backend participant Ctrl as OfferingsController participant Svc as OfferingsService participant Repo as OfferingRepository end Admin->>Form: Fills form, toggles Featured, submits Form->>Form: Validate against zod schema (BR-OFF-04, client-side mirror) Form->>Ctrl: POST or PUT with offering data Ctrl->>Svc: CreateAsync or UpdateAsync Svc->>Svc: Re-validate (BR-OFF-04, server-side, authoritative) alt Featured set to true Svc->>Repo: GetFeaturedAsync Repo-->>Svc: currently-featured Offering or none Svc->>Repo: UpdateAsync (unfeature previous, if any) end Svc->>Repo: AddAsync or UpdateAsync (this offering) Repo-->>Svc: saved Offering Svc-->>Ctrl: OfferingAdminDto Ctrl-->>Form: 200/201 with the saved offering Form-->>Admin: Redirect to offerings list ``` Text alternative: the admin fills the create/edit page (a full page, not a modal — Functional Design Q2), client-side validation runs first for immediate feedback, then the server re-validates authoritatively; if `Featured` is being set to true, the service un-features any previously-featured offering in the same operation before saving (yellow = admin actor, blue = frontend page, purple = backend layers). ## Flow 2: Delete an Offering (with Confirmation) ```mermaid sequenceDiagram box rgba(246,224,94,0.4) Admin participant Admin as CMS Administrator end box rgba(99,179,237,0.4) Frontend participant List as OfferingsListPage participant Dialog as DeleteOfferingDialog end box rgba(159,122,234,0.4) Backend participant Ctrl as OfferingsController participant Svc as OfferingsService end Admin->>List: Clicks delete on a row List->>Dialog: Open confirmation dialog (Functional Design Q4) Admin->>Dialog: Confirms Dialog->>Ctrl: DELETE request Ctrl->>Svc: DeleteAsync (always allowed, BR-OFF-02) Svc-->>Ctrl: success Ctrl-->>List: 204, remove row from list ``` Text alternative: deletion always shows a confirmation dialog first (a frontend-only safeguard); once confirmed, the delete request is unconditionally accepted by the backend, including for the last remaining offering. ## Flow 3: Reorder via Drag-and-Drop (US-08) ```mermaid sequenceDiagram box rgba(246,224,94,0.4) Admin participant Admin as CMS Administrator end box rgba(99,179,237,0.4) Frontend participant List as OfferingsListPage end box rgba(159,122,234,0.4) Backend participant Ctrl as OfferingsController participant Svc as OfferingsService end Admin->>List: Drags a row to a new position (dnd-kit) List->>List: Reorders local row state optimistically List->>Ctrl: PUT reorder with the full ordered id list Ctrl->>Svc: ReorderAsync(orderedIds) Svc->>Svc: Reassign DisplayOrder sequentially to match Svc-->>Ctrl: success Ctrl-->>List: 204 (or revert local state on failure) ``` Text alternative: dragging a row reorders the frontend's local list immediately (perceived responsiveness), then sends the complete new order to the backend, which reassigns every offering's `DisplayOrder` to match in one operation. ## Flow 4: Reorder via Up/Down Buttons (US-09) ```mermaid sequenceDiagram box rgba(246,224,94,0.4) Admin participant Admin as CMS Administrator end box rgba(99,179,237,0.4) Frontend participant List as OfferingsListPage end box rgba(159,122,234,0.4) Backend participant Ctrl as OfferingsController participant Svc as OfferingsService end Admin->>List: Clicks "move up" on a row List->>Ctrl: POST move-up for that offering id Ctrl->>Svc: MoveUpAsync(id) Svc->>Svc: Swap DisplayOrder with the
preceding offering (BR-OFF-03) Svc-->>Ctrl: success Ctrl-->>List: 204, list refetches or reorders locally ``` Text alternative: an explicit per-row button swaps the offering's position with its immediate neighbor — the accessible alternative to drag-and-drop, symmetric for "move down". ## Flow 5: Featured Toggle from the List Row (Functional Design Q5) ```mermaid sequenceDiagram box rgba(246,224,94,0.4) Admin participant Admin as CMS Administrator end box rgba(99,179,237,0.4) Frontend participant List as OfferingsListPage end box rgba(159,122,234,0.4) Backend participant Ctrl as OfferingsController participant Svc as OfferingsService end Admin->>List: Clicks the "featured" star icon on a row List->>Ctrl: PUT update using the row's already-loaded data,
with Featured flipped Ctrl->>Svc: UpdateAsync Note over Svc: Same BR-OFF-01 exclusivity logic as the form path Svc-->>Ctrl: success Ctrl-->>List: 200, list reflects the new featured offering ``` Text alternative: the quick list-row star action is not a separate backend capability — it calls the exact same update endpoint as the full edit form, just pre-filled from data the list already has in memory, so BR-OFF-01's exclusivity rule applies identically no matter which UI path the admin used (resolves Functional Design Q5: both the form toggle and the list-row action work, backed by one shared mechanism).