Adds the Offerings module and retargets the CI/CD pipeline to Api.SlpSoftware
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
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
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
This commit is contained in:
+66
@@ -0,0 +1,66 @@
|
||||
# Domain Entities — Unit: Offerings
|
||||
|
||||
## Entity Relationships
|
||||
|
||||
```mermaid
|
||||
%%{init: {'themeVariables': {'primaryTextColor':'#000000','textColor':'#000000','tertiaryTextColor':'#000000'}}}%%
|
||||
graph TD
|
||||
offering["Offering<br/>(entity)"]
|
||||
public_dto["OfferingDto<br/>(public contract, FR-6)"]
|
||||
admin_dto["OfferingAdminDto<br/>(admin view, FR-7)"]
|
||||
|
||||
offering -->|"projected to (excludes IsDeleted/DeletedAt)"| public_dto
|
||||
offering -->|"projected to (adds DisplayOrder)"| admin_dto
|
||||
|
||||
classDef entity fill:#bee3f8,stroke:#0d47a1,stroke-width:2px,color:#000000,font-weight:bold;
|
||||
classDef dto fill:#fed7aa,stroke:#e65100,stroke-width:2px,color:#000000,font-weight:bold;
|
||||
|
||||
class offering entity;
|
||||
class public_dto,admin_dto dto;
|
||||
```
|
||||
|
||||
Text alternative: the single `Offering` entity projects into two different DTO shapes — the public contract (no internal/administrative fields) and the admin view (adds `DisplayOrder` for the list UI) — blue for the stateful entity, orange for the two value-object projections.
|
||||
|
||||
## Entity Definitions
|
||||
|
||||
### Offering
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `Id` | `Guid` | Yes | System-generated (Application Design Q4 = A). Public contract exposes this as a `string`. |
|
||||
| `Title` | `string` | Yes | Max 100 characters (Functional Design Q3 = A). |
|
||||
| `Description` | `string` | Yes | Max 500 characters. |
|
||||
| `Price` | `string` | Yes | Max 50 characters. Pre-formatted display string, not numeric (FR-5) — e.g. `"€ 300"` or `"Op maat"`. |
|
||||
| `PriceNote` | `string` | Yes | Max 100 characters. |
|
||||
| `Features` | `List<string>` | Yes | Min 1, max 10 items; each item max 200 characters. Ordered — array order is display order. |
|
||||
| `CtaLabel` | `string` | Yes | Max 50 characters. |
|
||||
| `Featured` | `bool` | No (default `false`) | At most one non-deleted `Offering` may have this `true` at any time (US-10, enforced in `IOfferingsService`, not at the database/constraint level — see business-rules.md). |
|
||||
| `DisplayOrder` | `int` | Yes | Determines public array order and admin list order. Unique among non-deleted offerings; not necessarily contiguous after deletions (soft delete does not renumber). |
|
||||
| `IsDeleted` | `bool` | Yes (default `false`) | Soft-delete flag (Application Design Q5 = B). Never exposed on either DTO. |
|
||||
| `DeletedAt` | `DateTimeOffset?` | No | Set when `IsDeleted` becomes `true`. Never exposed on either DTO. |
|
||||
| `CreatedAt` | `DateTimeOffset` | Yes | Set once on creation. Part of the SECURITY-13 audit trail ("when"). |
|
||||
| `UpdatedAt` | `DateTimeOffset` | Yes | Set on every create/update. Same rationale as `CreatedAt`. |
|
||||
| `LastModifiedByUserId` | `Guid` | Yes | The authenticated admin's user id, set on every create/update/delete (NFR Requirements Q3 = A). Closes the "who" half of the SECURITY-13 open item alongside `CreatedAt`/`UpdatedAt`'s "when" — together a minimal audit trail without building a full audit-log table. |
|
||||
|
||||
### OfferingDto (public contract, FR-6)
|
||||
|
||||
| Field | Type | Maps From |
|
||||
|---|---|---|
|
||||
| `id` | `string` | `Offering.Id.ToString()` |
|
||||
| `title` | `string` | `Offering.Title` |
|
||||
| `description` | `string` | `Offering.Description` |
|
||||
| `price` | `string` | `Offering.Price` |
|
||||
| `priceNote` | `string` | `Offering.PriceNote` |
|
||||
| `features` | `string[]` | `Offering.Features` |
|
||||
| `ctaLabel` | `string` | `Offering.CtaLabel` |
|
||||
| `featured` | `bool` | `Offering.Featured` |
|
||||
|
||||
### OfferingAdminDto (admin view, FR-7)
|
||||
|
||||
Same fields as `OfferingDto`, plus:
|
||||
|
||||
| Field | Type | Maps From |
|
||||
|---|---|---|
|
||||
| `displayOrder` | `int` | `Offering.DisplayOrder` |
|
||||
|
||||
`IsDeleted`/`DeletedAt`/`CreatedAt`/`UpdatedAt`/`LastModifiedByUserId` are intentionally not exposed on either DTO — soft-deleted rows are never returned to any caller (repository-level filtering, per services.md), and the audit fields exist for potential future audit tooling, not for display in this unit's admin UI.
|
||||
Reference in New Issue
Block a user