Files
slp-modular-cms/aidlc-docs/features/slpsoftware-api/construction/offerings/functional-design/business-logic-model.md
T
SluijsensandClaude Sonnet 5 cfb06b28b6
Continuous Integration / config (pull_request) Successful in 12s
Continuous Integration / changes (pull_request) Successful in 22s
Continuous Integration / backend-build (pull_request) Successful in 5m53s
Continuous Integration / vulnerability-scan (pull_request) Successful in 5m46s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m54s
Continuous Integration / backend-test (pull_request) Successful in 7m37s
Continuous Integration / frontend-build (pull_request) Successful in 2m14s
Continuous Integration / frontend-test (pull_request) Successful in 4m59s
Continuous Integration / frontend-lint (pull_request) Successful in 2m2s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 7m34s
Continuous Integration / deploy-test (pull_request) Skipped
Adds the Offerings module and retargets the CI/CD pipeline to Api.SlpSoftware
Implements Unit 2 "Offerings" (backend module, admin CRUD UI with
drag-and-drop reordering, public GET /api/v1/offerings endpoint) and
executes the feature's D-15 CI/CD cutover, switching the deploy
pipeline's build/publish target from SlpModularCms.Api to
SlpModularCms.Api.SlpSoftware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWyStNL2ZsjrS7FLd7xvvN
2026-08-02 16:23:09 +02:00

5.5 KiB

Business Logic Model — Unit: Offerings

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)

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)

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)

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<br/>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".

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,<br/>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).