diff --git a/README.md b/README.md index 478029b..f541f69 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,105 @@ # Modelizer -Modelizer is a lightweight database modeling tool developed for teaching the database modeling process (initially for courses in Luxembourg). +Modelizer is a lightweight database modeling tool for teaching and discussing the database modeling process, originally developed for courses in Luxembourg. -- Online version: https://www.modelizer.lu/ -- Download: GitHub Releases -- Docker image: https://hub.docker.com/r/haanlaurent/modelizer +[Use Modelizer online](https://www.modelizer.lu/) · [Download for Windows](https://github.com/haan/modelizer/releases) · [Docker image](https://hub.docker.com/r/haanlaurent/modelizer) -## Run locally (Windows) +## Model in three views -1. Download the latest release from the GitHub Releases page. +| View | Purpose | +| --- | --- | +| **Conceptual** | Describe the domain with classes, attributes, associations, roles, and multiplicities. | +| **Logical** | Define tables and relationships between attributes, using logical names where needed. | +| **Physical** | Specify column types, nullability, uniqueness, auto-increment, and default values. | + +Conceptual models support parallel, reflexive, and associative associations, as well as composite aggregation. Enable **Preferences → Enable composite aggregation** to create and display composite aggregations. + +Modelizer leaves modeling decisions to the learner. It does not validate modeling correctness or automatically generate relationships from associations. + +## Get started + +1. Open Modelizer and choose **File → New**. +2. In conceptual view, add classes and attributes from the **Classes** panel. +3. Connect class handles to create associations, then edit their names, roles, and multiplicities in **Relations**. +4. Switch to logical or physical view to define relationships between attributes or columns and add implementation details. +5. Save an editable `.mdlz` file. Export a PNG when you need an image to share. + +Open **Help** in the application for task-based instructions, troubleshooting, and keyboard shortcuts. The [same guide is available in this repository](src/content/help.md). + +## Save, import, and share + +**Save and reopen models.** Use **File → Save** or **Save As** to keep a `.mdlz` file containing the model, layouts, notes, areas, and annotations. Reopen it with **File → Open** or by dropping one file onto the application. Depending on browser support and file permissions, Save writes back to the chosen file, prompts for a location, or downloads a copy. + +Models are stored in local files, with no server-side model storage. The `*` beside the model name indicates unsaved changes. Editor preferences are remembered separately in the browser. Current saves use file format version 2; version 1 files still open, but older Modelizer versions cannot open version 2 files. + +**Import existing designs.** Import Java Modelizer (`.mod`) or MySQL (`.sql`) files through **File → Import**. Review the result: unsupported types are reported and mapped to Undefined, unsupported Java Modelizer links may be skipped, and composite MySQL foreign keys are ignored. + +**Export an image.** **Export PNG** previews the full current view and lets you choose whether to include notes, areas, annotations, and accent colors. Choose standard or high resolution, a white or transparent background, margins, and a filename. Export settings do not change the model. Keep a `.mdlz` file as your editable copy; PNG is for sharing and presentation. + +## Teach and discuss + +Use **View → Notes** for explanations and **View → Areas** to group related elements. Enable **View → Annotations** to draw with a pen or marker, add text and shapes, or point things out with a temporary laser. Annotations are saved separately for each modeling view; laser effects are never saved or exported. + +Use **View** to adjust diagram content, notation, the background grid, accent colors, and fullscreen display. **Preferences** controls editor behavior and dark mode. PNG exports use light styling while preserving user-selected class, area, and annotation colors. + +## Run locally on Windows + +1. Download the release ZIP from [GitHub Releases](https://github.com/haan/modelizer/releases). 2. Unzip it anywhere on your computer. -3. Double-click `modelizer.bat` -4. Open your browser at http://localhost:8080 +3. Double-click `modelizer.bat` to start the local server and open your browser. +4. If the browser does not open automatically, visit [localhost:8080](http://localhost:8080). -The release includes a tiny local webserver based on miniserve: -https://github.com/svenstaro/miniserve +The release includes a small local webserver based on [miniserve](https://github.com/svenstaro/miniserve). Close the server window when you are finished. ## Run with Docker -Run the latest published image from Docker Hub: -https://hub.docker.com/r/haanlaurent/modelizer +Run the latest published [Docker image](https://hub.docker.com/r/haanlaurent/modelizer): ```bash docker run --rm -p 8080:80 haanlaurent/modelizer:latest ``` -Then open: http://localhost:8080 +Open [localhost:8080](http://localhost:8080). To use a specific release, replace `latest` with its published version tag. -Run a specific version tag: +To build and run the image from this repository: ```bash -docker run --rm -p 8080:80 haanlaurent/modelizer: +docker build -t modelizer:local . +docker run --rm -p 8080:80 modelizer:local ``` -Build and run locally from this repository: +## Development + +Use **Node.js 26.10.0 or a later 26.x release** and npm. The repository pins its development version in [.nvmrc](.nvmrc). + +From the repository root, install dependencies and start the development server: ```bash -docker build -t modelizer:local . -docker run --rm -p 8080:80 modelizer:local +npm ci +npm run dev ``` -## Supported modeling elements - -Modelizer supports: -- different modeling levels: - - conceptual model (CDM) - - logical model (LDM) - - physical model (PDM) -- classes -- associations -- associative associations -- reflexive associations -- composite aggregations (enable in menu first) -- multiplicities -- attributes -- attribute types -- default values -- constraints: Null, Unique, Auto Increment -- import from Java Modelizer files - -## What Modelizer does (and does not do) - -Modelizer is intentionally a teaching tool that simplifies drawing and defining models. -It contains no validation logic and does not generate relationships automatically from associations. -It does not help you make the "right" modeling decisions — you do. - -## Export & storage - -- Export format: PNG -- Models must be downloaded manually (no server-side storage) -- Settings are stored in browser localStorage - -## Teaching annotations - -Enable **Settings > Annotations** to show the annotation toolbar. Use **Pointer** -to interact with the diagram, or choose a drawing tool to mark it. The toolbar -includes pen, highlighter, text, arrows, lines, rectangles, ellipses, ink erasing, -and a temporary laser pointer. **Select annotation** moves, resizes, styles, -duplicates, and deletes individual annotations. Text supports wrapping and an -optional background, padding, and border. - -Hold **Space** and drag to pan while using an annotation tool; use the wheel to -zoom. **Shift** constrains shapes and draws straight highlights. Annotations scale -with the diagram and are saved separately for each model view. The laser is never -saved or exported. - -**Export PNG…** previews the full current view with options for annotations, -notes, areas, accent colors, and resolution. More options offers white or -transparent backgrounds, margins, and an editable filename. Include annotations -appears only for marked views and can include marks hidden on the canvas. -Preview settings do not alter the model; normal saving includes all annotations. Saved models now use file format version 2; -version 1 files still open, but older Modelizer versions cannot open version 2. - -## Appearance - -Use **View > Dark mode** to switch the entire editor between light and dark. -Light is the default; your choice is remembered in this browser independently of -your model files. PNG exports always use light styling. User-selected class, -area, and annotation colors stay unchanged in either theme. +Open the local URL printed by Vite. + +Run lint and unit tests: + +```bash +npm test +``` + +Build and preview the production app: + +```bash +npm run build:ci +npm run preview +``` + +`build:ci` writes the web app to `dist/`. Use `npm run build` when you also want to refresh `bundle/app/dist/` for the Windows release bundle. + +The [examples folder](examples/) contains five conceptual smoke-test models of increasing complexity. Follow the [smoke-test guide](examples/README.txt) for manual checks; the largest model is an intentional readability stress test, not a claim that every layout already renders perfectly. ## Acknowledgments -- ChartDB (interface design inspiration): https://github.com/chartdb/chartdb/ -- Java Modelizer by Bob Fisch: https://modelizer.fisch.lu/ -- miniserve (local webserver used in the release bundle): https://github.com/svenstaro/miniserve +- [Java Modelizer](https://modelizer.fisch.lu/) by Bob Fisch — Modelizer’s predecessor. +- [ChartDB](https://github.com/chartdb/chartdb/) — interface design inspiration. +- [miniserve](https://github.com/svenstaro/miniserve) — the local webserver used in the Windows release bundle. diff --git a/docs/react-flow-12-review.md b/docs/react-flow-12-review.md deleted file mode 100644 index ed44fc9..0000000 --- a/docs/react-flow-12-review.md +++ /dev/null @@ -1,72 +0,0 @@ -# React Flow 12 migration review - -The migration is implemented on `chore/react-flow-12`, based on `main` at -`9de921a`. React Flow 11.11.4 is replaced by `@xyflow/react` 12.12.0. React, -Node, build tooling, and model-file format version 2 remain unchanged. Version 1 -models remain supported. Merging and releasing are separate steps. - -After switching branches, run `npm install` and restart the development server -so the installed dependencies match the branch. - -## Implementation and follow-up fixes - -- Migrate imports, styles, chunking, internal-node geometry, and viewport APIs. -- Keep runtime measurements out of serialization, dirty tracking, and undo. - Preserve explicit area dimensions and gesture-level resize history. -- Wait for export node measurements and asynchronous viewport changes; support - annotation-only exports without waiting for nonexistent nodes. -- Preserve the fixed measurements of derived association helpers so associative - links remain visible after updates and view changes. -- Make sidebar focus exclusive across nodes and edges in all views, and add - focus-button tooltips with keyboard visibility. -- Render composition diamonds in the edge SVG without clipped tips. Composite - the line and diamond before applying opacity to prevent overlap artifacts. - -## Validation on 22 October 2026 - -- `npm run lint`: passed. -- `npm run test:unit`: 541 tests passed in 35 files. The original 514 tests remain. -- `npm run build:ci`: passed. The existing MySQL parser chunk-size warning remains. -- The initial migration comparison against `main`, recorded in commit `f88f7bc`, - covered a 20-class diagram, light/dark rendering, all three views, matching - conceptual PNG preview dimensions, pen undo/redo, and an annotation-only preview. -- Follow-up browser checks confirmed solid composition diamonds with matching - line colors in light and dark themes. -- A temporary browser fixture using the actual model-state hook, node/edge - components, and PNG exporter confirmed the reported associative link renders. - Real generated PNG bytes were saved locally and visually inspected: - conceptual and logical output at 1919 × 1185, physical output at 1919 × 1275, - and annotation-only output at 1734 × 1185. These fixtures included negative - coordinates, text, shapes, ink, and notes/areas omitted from the live canvas. - Content remained unclipped, and the physical default-values footer was visible. - Dark-mode export retained light export styling and annotation colors. -- Personal model files and local review images are not part of the commits. - -## Outstanding manual review - -Browser download-event automation timed out, so completion of a native PNG -download through the production dialog remains unverified. The PNG rendering -itself was verified independently from its generated image bytes. - -Exhaustive keyboard, pointer, touch, area-resize, relationship-control-point, -and annotation-tool checks across all views and themes remain a release review -task. Automated regressions cover these areas in part; they do not establish -complete visual or interaction parity. Browser file-picker automation also -failed for the supplied model; file parsing/opening has automated coverage, -and the model rendered through the local review fixture. - -## Deferred class panel layout - -Discussed with the user and explicitly deferred until after the migration: - -- Align attribute fields using consistent label and input columns. -- Clarify N/UQ/AI controls, their selected states, and explanatory tooltips. -- Reduce uppercase label noise and excessive vertical spacing. -- Move the class color control into the header instead of a separate Options section. -- Consider compact, accessible delete actions in class and attribute headers, - retaining class deletion confirmation. -- Add muted type/key summaries to collapsed attributes. -- Keep the colored class stripe, expandable attributes, and Add attribute placement. - -Start with alignment, spacing, and the color control. These are recorded design -ideas, not changes included in this migration. diff --git a/examples/01-library-basics.mdlz b/examples/01-library-basics.mdlz new file mode 100644 index 0000000..02e4754 --- /dev/null +++ b/examples/01-library-basics.mdlz @@ -0,0 +1,393 @@ +{ + "version": 2, + "modelName": "01 - Library basics", + "nodes": [ + { + "id": "reader", + "type": "class", + "position": { + "x": 0, + "y": 0 + }, + "selected": false, + "data": { + "label": "Reader", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "reader-attr-0", + "name": "name", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "reader-attr-1", + "name": "email", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 0, + "y": 0 + }, + "logical": { + "x": 0, + "y": 0 + }, + "physical": { + "x": 0, + "y": 0 + } + } + } + }, + { + "id": "loan", + "type": "class", + "position": { + "x": 500, + "y": 0 + }, + "selected": false, + "data": { + "label": "Loan", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "loan-attr-0", + "name": "borrowedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "loan-attr-1", + "name": "dueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 500, + "y": 0 + }, + "logical": { + "x": 500, + "y": 0 + }, + "physical": { + "x": 500, + "y": 0 + } + } + } + }, + { + "id": "copy", + "type": "class", + "position": { + "x": 500, + "y": 300 + }, + "selected": false, + "data": { + "label": "BookCopy", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "copy-attr-0", + "name": "barcode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "copy-attr-1", + "name": "condition", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 500, + "y": 300 + }, + "logical": { + "x": 500, + "y": 300 + }, + "physical": { + "x": 500, + "y": 300 + } + } + } + }, + { + "id": "book", + "type": "class", + "position": { + "x": 0, + "y": 300 + }, + "selected": false, + "data": { + "label": "Book", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "book-attr-0", + "name": "title", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "book-attr-1", + "name": "isbn", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 0, + "y": 300 + }, + "logical": { + "x": 0, + "y": 300 + }, + "physical": { + "x": 0, + "y": 300 + } + } + } + } + ], + "edges": [ + { + "id": "edge-0001", + "source": "reader", + "target": "loan", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "borrows", + "type": "association", + "roleA": "borrower", + "roleB": "loans", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0002", + "source": "loan", + "target": "copy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "loans", + "roleB": "copy", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0003", + "source": "book", + "target": "copy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "hasCopies", + "type": "association", + "roleA": "edition", + "roleB": "copies", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + } + ], + "annotations": { + "conceptual": { + "items": [] + }, + "logical": { + "items": [] + }, + "physical": { + "items": [] + } + } +} diff --git a/examples/02-dispatch-border-spacing.mdlz b/examples/02-dispatch-border-spacing.mdlz new file mode 100644 index 0000000..dc31b8f --- /dev/null +++ b/examples/02-dispatch-border-spacing.mdlz @@ -0,0 +1,1128 @@ +{ + "version": 2, + "modelName": "02 - Dispatch hub and border spacing", + "nodes": [ + { + "id": "area-0001", + "type": "area", + "position": { + "x": 430, + "y": 430 + }, + "selected": false, + "data": { + "label": "Dispatch", + "color": "#009688", + "viewSizes": { + "conceptual": { + "width": 330, + "height": 420 + }, + "logical": { + "width": 330, + "height": 420 + }, + "physical": { + "width": 330, + "height": 420 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 430, + "y": 430 + }, + "logical": { + "x": 430, + "y": 430 + }, + "physical": { + "x": 430, + "y": 430 + } + } + }, + "style": { + "width": 330, + "height": 420 + }, + "zIndex": -1, + "width": 330, + "height": 420 + }, + { + "id": "hub", + "type": "class", + "position": { + "x": 500, + "y": 500 + }, + "selected": false, + "data": { + "label": "DispatchCentre", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "hub-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "hub-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 500, + "y": 500 + }, + "logical": { + "x": 500, + "y": 500 + }, + "physical": { + "x": 500, + "y": 500 + } + } + } + }, + { + "id": "sender", + "type": "class", + "position": { + "x": -250, + "y": 230 + }, + "selected": false, + "data": { + "label": "Sender", + "logicalName": "", + "color": "#2196f3", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -250, + "y": 230 + }, + "logical": { + "x": -250, + "y": 230 + }, + "physical": { + "x": -250, + "y": 230 + } + } + } + }, + { + "id": "warehouse", + "type": "class", + "position": { + "x": -195.13428591317845, + "y": 589.7303446835605 + }, + "selected": false, + "data": { + "label": "Warehouse", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "warehouse-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -195.13428591317845, + "y": 589.7303446835605 + }, + "logical": { + "x": -195.13428591317845, + "y": 589.7303446835605 + }, + "physical": { + "x": -195.13428591317845, + "y": 589.7303446835605 + } + }, + "viewPositionsMeta": { + "conceptual": true, + "logical": false, + "physical": false + } + } + }, + { + "id": "carrier", + "type": "class", + "position": { + "x": -250, + "y": 870 + }, + "selected": false, + "data": { + "label": "Carrier", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "carrier-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "carrier-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -250, + "y": 870 + }, + "logical": { + "x": -250, + "y": 870 + }, + "physical": { + "x": -250, + "y": 870 + } + } + } + }, + { + "id": "route", + "type": "class", + "position": { + "x": 1250, + "y": 370 + }, + "selected": false, + "data": { + "label": "Route", + "logicalName": "", + "color": "#ff5722", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1250, + "y": 370 + }, + "logical": { + "x": 1250, + "y": 370 + }, + "physical": { + "x": 1250, + "y": 370 + } + } + } + }, + { + "id": "delivery", + "type": "class", + "position": { + "x": 1250, + "y": 750 + }, + "selected": false, + "data": { + "label": "Delivery", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "delivery-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1250, + "y": 750 + }, + "logical": { + "x": 1250, + "y": 750 + }, + "physical": { + "x": 1250, + "y": 750 + } + } + } + }, + { + "id": "contract", + "type": "class", + "position": { + "x": 240, + "y": -180 + }, + "selected": false, + "data": { + "label": "Contract", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "contract-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "contract-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 240, + "y": -180 + }, + "logical": { + "x": 240, + "y": -180 + }, + "physical": { + "x": 240, + "y": -180 + } + } + } + }, + { + "id": "policy", + "type": "class", + "position": { + "x": 800, + "y": -180 + }, + "selected": false, + "data": { + "label": "Policy", + "logicalName": "", + "color": "#2196f3", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 800, + "y": -180 + }, + "logical": { + "x": 800, + "y": -180 + }, + "physical": { + "x": 800, + "y": -180 + } + } + } + }, + { + "id": "audit", + "type": "class", + "position": { + "x": 240, + "y": 1250 + }, + "selected": false, + "data": { + "label": "AuditEvent", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "audit-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 240, + "y": 1250 + }, + "logical": { + "x": 240, + "y": 1250 + }, + "physical": { + "x": 240, + "y": 1250 + } + } + } + }, + { + "id": "exception", + "type": "class", + "position": { + "x": 800, + "y": 1250 + }, + "selected": false, + "data": { + "label": "Exception", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "exception-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "exception-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 800, + "y": 1250 + }, + "logical": { + "x": 800, + "y": 1250 + }, + "physical": { + "x": 800, + "y": 1250 + } + } + } + }, + { + "id": "note-0012", + "type": "note", + "position": { + "x": -280, + "y": -100 + }, + "selected": false, + "data": { + "label": "Distance regression", + "text": "Move DispatchCentre farther right, then back. Left-border order and separation should stay stable. Repeat with Contract and Policy above the hub.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -280, + "y": -100 + }, + "logical": { + "x": -280, + "y": -100 + }, + "physical": { + "x": -280, + "y": -100 + } + } + } + }, + { + "id": "note-0013", + "type": "note", + "position": { + "x": 1180, + "y": 1100 + }, + "selected": false, + "data": { + "label": "Small versus tall", + "text": "Sender has no attributes. Add attributes to it, then undo. Endpoints must remain on borders without resizing other classes.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1180, + "y": 1100 + }, + "logical": { + "x": 1180, + "y": 1100 + }, + "physical": { + "x": 1180, + "y": 1100 + } + } + } + } + ], + "edges": [ + { + "id": "edge-0002", + "source": "sender", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requests", + "type": "association", + "roleA": "sender", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0003", + "source": "warehouse", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "stocks", + "type": "association", + "roleA": "warehouse", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0004", + "source": "carrier", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "serves", + "type": "association", + "roleA": "carrier", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0005", + "source": "route", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "plans", + "type": "association", + "roleA": "route", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0006", + "source": "delivery", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "dispatches", + "type": "association", + "roleA": "delivery", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0007", + "source": "contract", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "contract", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0008", + "source": "policy", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "restricts", + "type": "association", + "roleA": "policy", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0009", + "source": "audit", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "audit", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0010", + "source": "exception", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "escalates", + "type": "association", + "roleA": "exception", + "roleB": "centre", + "multiplicityA": "0..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0011", + "source": "warehouse", + "target": "hub", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "returnsTo", + "type": "association", + "roleA": "returns", + "roleB": "receivingCentre", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + } + ], + "annotations": { + "conceptual": { + "items": [ + { + "id": "text-0014", + "kind": "text", + "x": 460, + "y": -370, + "text": "02 / all four borders", + "color": "#334155", + "fontSize": 26 + }, + { + "id": "arrow-0015", + "kind": "shape", + "shape": "arrow", + "x1": 30, + "y1": 1100, + "x2": 430, + "y2": 770, + "color": "#dc2626", + "thickness": 2 + } + ] + }, + "logical": { + "items": [] + }, + "physical": { + "items": [] + } + } +} \ No newline at end of file diff --git a/examples/03-university-enrolment.mdlz b/examples/03-university-enrolment.mdlz new file mode 100644 index 0000000..d0fd23c --- /dev/null +++ b/examples/03-university-enrolment.mdlz @@ -0,0 +1,3028 @@ +{ + "version": 2, + "modelName": "03 - University enrolment", + "nodes": [ + { + "id": "area-0001", + "type": "area", + "position": { + "x": -710, + "y": -470 + }, + "selected": false, + "data": { + "label": "People", + "color": "#ffc107", + "viewSizes": { + "conceptual": { + "width": 1530, + "height": 1370 + }, + "logical": { + "width": 1530, + "height": 1370 + }, + "physical": { + "width": 1530, + "height": 1370 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -710, + "y": -470 + }, + "logical": { + "x": -710, + "y": -470 + }, + "physical": { + "x": -710, + "y": -470 + } + } + }, + "width": 1530, + "height": 1370, + "style": { + "width": 1530, + "height": 1370 + }, + "zIndex": -1 + }, + { + "id": "Person", + "type": "class", + "position": { + "x": -650, + "y": -400 + }, + "selected": false, + "data": { + "label": "Person", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Person-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -650, + "y": -400 + }, + "logical": { + "x": -650, + "y": -400 + }, + "physical": { + "x": -650, + "y": -400 + } + } + } + }, + { + "id": "Student", + "type": "class", + "position": { + "x": -170, + "y": -400 + }, + "selected": false, + "data": { + "label": "Student", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Student-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Student-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Student-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -170, + "y": -400 + }, + "logical": { + "x": -170, + "y": -400 + }, + "physical": { + "x": -170, + "y": -400 + } + } + } + }, + { + "id": "Lecturer", + "type": "class", + "position": { + "x": 310, + "y": -400 + }, + "selected": false, + "data": { + "label": "Lecturer", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Lecturer-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Lecturer-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Lecturer-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Lecturer-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 310, + "y": -400 + }, + "logical": { + "x": 310, + "y": -400 + }, + "physical": { + "x": 310, + "y": -400 + } + } + } + }, + { + "id": "Department", + "type": "class", + "position": { + "x": -650, + "y": 250 + }, + "selected": false, + "data": { + "label": "Department", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Department-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Department-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -650, + "y": 250 + }, + "logical": { + "x": -650, + "y": 250 + }, + "physical": { + "x": -650, + "y": 250 + } + } + } + }, + { + "id": "Address", + "type": "class", + "position": { + "x": -170, + "y": 250 + }, + "selected": false, + "data": { + "label": "Address", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Address-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Address-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Address-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -170, + "y": 250 + }, + "logical": { + "x": -170, + "y": 250 + }, + "physical": { + "x": -170, + "y": 250 + } + } + } + }, + { + "id": "EmergencyContact", + "type": "class", + "position": { + "x": 310, + "y": 250 + }, + "selected": false, + "data": { + "label": "EmergencyContact", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "EmergencyContact-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "EmergencyContact-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "EmergencyContact-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "EmergencyContact-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 310, + "y": 250 + }, + "logical": { + "x": 310, + "y": 250 + }, + "physical": { + "x": 310, + "y": 250 + } + } + } + }, + { + "id": "area-0002", + "type": "area", + "position": { + "x": 1090, + "y": -470 + }, + "selected": false, + "data": { + "label": "Teaching", + "color": "#2196f3", + "viewSizes": { + "conceptual": { + "width": 1530, + "height": 1370 + }, + "logical": { + "width": 1530, + "height": 1370 + }, + "physical": { + "width": 1530, + "height": 1370 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1090, + "y": -470 + }, + "logical": { + "x": 1090, + "y": -470 + }, + "physical": { + "x": 1090, + "y": -470 + } + } + }, + "width": 1530, + "height": 1370, + "style": { + "width": 1530, + "height": 1370 + }, + "zIndex": -1 + }, + { + "id": "Course", + "type": "class", + "position": { + "x": 1150, + "y": -400 + }, + "selected": false, + "data": { + "label": "Course", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Course-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Course-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1150, + "y": -400 + }, + "logical": { + "x": 1150, + "y": -400 + }, + "physical": { + "x": 1150, + "y": -400 + } + } + } + }, + { + "id": "Module", + "type": "class", + "position": { + "x": 1630, + "y": -400 + }, + "selected": false, + "data": { + "label": "Module", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Module-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Module-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Module-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1630, + "y": -400 + }, + "logical": { + "x": 1630, + "y": -400 + }, + "physical": { + "x": 1630, + "y": -400 + } + } + } + }, + { + "id": "Session", + "type": "class", + "position": { + "x": 2110, + "y": -400 + }, + "selected": false, + "data": { + "label": "Session", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Session-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Session-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Session-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Session-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2110, + "y": -400 + }, + "logical": { + "x": 2110, + "y": -400 + }, + "physical": { + "x": 2110, + "y": -400 + } + } + } + }, + { + "id": "Room", + "type": "class", + "position": { + "x": 1150, + "y": 250 + }, + "selected": false, + "data": { + "label": "Room", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Room-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Room-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1150, + "y": 250 + }, + "logical": { + "x": 1150, + "y": 250 + }, + "physical": { + "x": 1150, + "y": 250 + } + } + } + }, + { + "id": "Campus", + "type": "class", + "position": { + "x": 1630, + "y": 250 + }, + "selected": false, + "data": { + "label": "Campus", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Campus-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Campus-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Campus-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1630, + "y": 250 + }, + "logical": { + "x": 1630, + "y": 250 + }, + "physical": { + "x": 1630, + "y": 250 + } + } + } + }, + { + "id": "Semester", + "type": "class", + "position": { + "x": 2110, + "y": 250 + }, + "selected": false, + "data": { + "label": "Semester", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Semester-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Semester-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Semester-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Semester-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2110, + "y": 250 + }, + "logical": { + "x": 2110, + "y": 250 + }, + "physical": { + "x": 2110, + "y": 250 + } + } + } + }, + { + "id": "area-0003", + "type": "area", + "position": { + "x": -710, + "y": 1130 + }, + "selected": false, + "data": { + "label": "Assessment", + "color": "#9c27b0", + "viewSizes": { + "conceptual": { + "width": 1530, + "height": 1370 + }, + "logical": { + "width": 1530, + "height": 1370 + }, + "physical": { + "width": 1530, + "height": 1370 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -710, + "y": 1130 + }, + "logical": { + "x": -710, + "y": 1130 + }, + "physical": { + "x": -710, + "y": 1130 + } + } + }, + "width": 1530, + "height": 1370, + "style": { + "width": 1530, + "height": 1370 + }, + "zIndex": -1 + }, + { + "id": "Assessment", + "type": "class", + "position": { + "x": -650, + "y": 1200 + }, + "selected": false, + "data": { + "label": "Assessment", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Assessment-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Assessment-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -650, + "y": 1200 + }, + "logical": { + "x": -650, + "y": 1200 + }, + "physical": { + "x": -650, + "y": 1200 + } + } + } + }, + { + "id": "Submission", + "type": "class", + "position": { + "x": -170, + "y": 1200 + }, + "selected": false, + "data": { + "label": "Submission", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Submission-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Submission-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Submission-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -170, + "y": 1200 + }, + "logical": { + "x": -170, + "y": 1200 + }, + "physical": { + "x": -170, + "y": 1200 + } + } + } + }, + { + "id": "Grade", + "type": "class", + "position": { + "x": 310, + "y": 1200 + }, + "selected": false, + "data": { + "label": "Grade", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Grade-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Grade-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Grade-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Grade-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 310, + "y": 1200 + }, + "logical": { + "x": 310, + "y": 1200 + }, + "physical": { + "x": 310, + "y": 1200 + } + } + } + }, + { + "id": "Qualification", + "type": "class", + "position": { + "x": -650, + "y": 1850 + }, + "selected": false, + "data": { + "label": "Qualification", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Qualification-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Qualification-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -650, + "y": 1850 + }, + "logical": { + "x": -650, + "y": 1850 + }, + "physical": { + "x": -650, + "y": 1850 + } + } + } + }, + { + "id": "Attendance", + "type": "class", + "position": { + "x": -170, + "y": 1850 + }, + "selected": false, + "data": { + "label": "Attendance", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Attendance-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attendance-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attendance-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -170, + "y": 1850 + }, + "logical": { + "x": -170, + "y": 1850 + }, + "physical": { + "x": -170, + "y": 1850 + } + } + } + }, + { + "id": "Enrolment", + "type": "class", + "position": { + "x": 1100, + "y": 1400 + }, + "selected": false, + "data": { + "label": "enrolsIn", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Enrolment-attr-0", + "name": "registeredAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Enrolment-attr-1", + "name": "attempt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Enrolment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1100, + "y": 1400 + }, + "logical": { + "x": 1100, + "y": 1400 + }, + "physical": { + "x": 1100, + "y": 1400 + } + } + } + }, + { + "id": "note-0030", + "type": "note", + "position": { + "x": -1000, + "y": -650 + }, + "selected": false, + "data": { + "label": "Four reflexive corners", + "text": "Person has four reflexive associations. Inspect both roles, both multiplicities and each name; resize one loop, then undo.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1000, + "y": -650 + }, + "logical": { + "x": -1000, + "y": -650 + }, + "physical": { + "x": -1000, + "y": -650 + } + } + } + }, + { + "id": "note-0031", + "type": "note", + "position": { + "x": 1470, + "y": 1400 + }, + "selected": false, + "data": { + "label": "Association class", + "text": "The Enrolment class attaches to enrolsIn. Move Student or Course and verify that the dashed link follows the base association.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1470, + "y": 1400 + }, + "logical": { + "x": 1470, + "y": 1400 + }, + "physical": { + "x": 1470, + "y": 1400 + } + } + } + }, + { + "id": "note-0032", + "type": "note", + "position": { + "x": 2700, + "y": 800 + }, + "selected": false, + "data": { + "label": "Composition", + "text": "Enable composite aggregations in View settings. The Course–Module diamond must remain attached and match its line colour.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2700, + "y": 800 + }, + "logical": { + "x": 2700, + "y": 800 + }, + "physical": { + "x": 2700, + "y": 800 + } + } + } + } + ], + "edges": [ + { + "id": "edge-0004", + "source": "Person", + "target": "Student", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "studiesAs", + "type": "association", + "roleA": "person", + "roleB": "student", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0005", + "source": "Person", + "target": "Lecturer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "teachesAs", + "type": "association", + "roleA": "person", + "roleB": "lecturer", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0006", + "source": "Person", + "target": "Address", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "livesAt", + "type": "association", + "roleA": "person", + "roleB": "address", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0007", + "source": "Person", + "target": "EmergencyContact", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "nominates", + "type": "association", + "roleA": "person", + "roleB": "emergencycontact", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0008", + "source": "Lecturer", + "target": "Department", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "worksIn", + "type": "association", + "roleA": "lecturer", + "roleB": "department", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0009", + "source": "Student", + "target": "Course", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "enrolsIn", + "type": "association", + "roleA": "student", + "roleB": "course", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0010", + "source": "Student", + "target": "Course", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "waitsFor", + "type": "association", + "roleA": "student", + "roleB": "course", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0011", + "source": "Lecturer", + "target": "Course", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "teaches", + "type": "association", + "roleA": "lecturer", + "roleB": "course", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0012", + "source": "Course", + "target": "Module", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "composition", + "roleA": "course", + "roleB": "module", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0013", + "source": "Module", + "target": "Session", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "schedules", + "type": "association", + "roleA": "module", + "roleB": "session", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0014", + "source": "Session", + "target": "Room", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "occupies", + "type": "association", + "roleA": "session", + "roleB": "room", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0015", + "source": "Room", + "target": "Campus", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "locatedOn", + "type": "association", + "roleA": "room", + "roleB": "campus", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0016", + "source": "Session", + "target": "Semester", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "occursDuring", + "type": "association", + "roleA": "session", + "roleB": "semester", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0017", + "source": "Student", + "target": "Submission", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "submits", + "type": "association", + "roleA": "student", + "roleB": "submission", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0018", + "source": "Submission", + "target": "Assessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "answers", + "type": "association", + "roleA": "submission", + "roleB": "assessment", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0019", + "source": "Assessment", + "target": "Grade", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "awards", + "type": "association", + "roleA": "assessment", + "roleB": "grade", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0020", + "source": "Grade", + "target": "Qualification", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contributesTo", + "type": "association", + "roleA": "grade", + "roleB": "qualification", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0021", + "source": "Student", + "target": "Attendance", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "attends", + "type": "association", + "roleA": "student", + "roleB": "attendance", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0022", + "source": "Attendance", + "target": "Session", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "recordsPresenceAt", + "type": "association", + "roleA": "attendance", + "roleB": "session", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0023", + "source": "Lecturer", + "target": "Assessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "marks", + "type": "association", + "roleA": "lecturer", + "roleB": "assessment", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0024", + "source": "Course", + "target": "Assessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "course", + "roleB": "assessment", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "associative-0025", + "source": "Enrolment", + "target": "assoc-edge-edge-0009", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "enrolsIn", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0026", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "mentors", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0027", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesTo", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0028", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "replaces", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0029", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isRelatedTo", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 85, + "loopHeight": 125 + } + } + ], + "annotations": { + "conceptual": { + "items": [ + { + "id": "text-0033", + "kind": "text", + "x": 800, + "y": -650, + "text": "Teaching and assessment / UML review", + "color": "#334155", + "fontSize": 28 + }, + { + "id": "rectangle-0034", + "kind": "shape", + "shape": "rectangle", + "x1": 1050, + "y1": 1300, + "x2": 1350, + "y2": 1660, + "color": "#7c3aed", + "thickness": 2 + }, + { + "id": "ellipse-0035", + "kind": "shape", + "shape": "ellipse", + "x1": -870, + "y1": -600, + "x2": -180, + "y2": 50, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "arrow-0036", + "kind": "shape", + "shape": "arrow", + "x1": 1470, + "y1": 1460, + "x2": 1320, + "y2": 1450, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "line-0037", + "kind": "shape", + "shape": "line", + "x1": 950, + "y1": 1000, + "x2": 2700, + "y2": 1000, + "color": "#94a3b8", + "thickness": 2 + }, + { + "id": "stroke-0038", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": 1120, + "y": -480 + }, + { + "x": 1300, + "y": -470 + }, + { + "x": 1500, + "y": -475 + }, + { + "x": 1700, + "y": -460 + } + ], + "color": "#facc15", + "thickness": 18, + "opacity": 0.35 + }, + { + "id": "stroke-0039", + "kind": "stroke", + "tool": "pen", + "points": [ + { + "x": -1000, + "y": 50 + }, + { + "x": -900, + "y": 120 + }, + { + "x": -800, + "y": 80 + }, + { + "x": -700, + "y": 140 + } + ], + "color": "#2563eb", + "thickness": 3, + "opacity": 1 + }, + { + "id": "text-0040", + "kind": "text", + "x": 1000, + "y": 2300, + "text": "Évaluation / Prüfung / 評価", + "color": "#334155", + "fontSize": 18, + "width": 300, + "padding": 12, + "background": "#fef3c7", + "border": true + } + ] + }, + "logical": { + "items": [] + }, + "physical": { + "items": [] + } + } +} diff --git a/examples/04-commerce-operations.mdlz b/examples/04-commerce-operations.mdlz new file mode 100644 index 0000000..8246051 --- /dev/null +++ b/examples/04-commerce-operations.mdlz @@ -0,0 +1,5446 @@ +{ + "version": 2, + "modelName": "04 - Commerce operations", + "nodes": [ + { + "id": "Customer", + "type": "class", + "position": { + "x": -700, + "y": -450 + }, + "selected": false, + "data": { + "label": "Customer", + "logicalName": "", + "color": "#009688", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -700, + "y": -450 + }, + "logical": { + "x": -700, + "y": -450 + }, + "physical": { + "x": -700, + "y": -450 + } + } + } + }, + { + "id": "Order", + "type": "class", + "position": { + "x": -240, + "y": -450 + }, + "selected": false, + "data": { + "label": "Order", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Order-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -240, + "y": -450 + }, + "logical": { + "x": -240, + "y": -450 + }, + "physical": { + "x": -240, + "y": -450 + } + } + } + }, + { + "id": "OrderLine", + "type": "class", + "position": { + "x": 220, + "y": -450 + }, + "selected": false, + "data": { + "label": "OrderLine", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "OrderLine-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "OrderLine-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 220, + "y": -450 + }, + "logical": { + "x": 220, + "y": -450 + }, + "physical": { + "x": 220, + "y": -450 + } + } + } + }, + { + "id": "Product", + "type": "class", + "position": { + "x": 680, + "y": -450 + }, + "selected": false, + "data": { + "label": "Product", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Product-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 680, + "y": -450 + }, + "logical": { + "x": 680, + "y": -450 + }, + "physical": { + "x": 680, + "y": -450 + } + } + } + }, + { + "id": "Catalogue", + "type": "class", + "position": { + "x": 1140, + "y": -450 + }, + "selected": false, + "data": { + "label": "Catalogue", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Catalogue-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Catalogue-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Catalogue-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Catalogue-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": -450 + }, + "logical": { + "x": 1140, + "y": -450 + }, + "physical": { + "x": 1140, + "y": -450 + } + } + } + }, + { + "id": "Price", + "type": "class", + "position": { + "x": 1600, + "y": -450 + }, + "selected": false, + "data": { + "label": "Price", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Price-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1600, + "y": -450 + }, + "logical": { + "x": 1600, + "y": -450 + }, + "physical": { + "x": 1600, + "y": -450 + } + } + } + }, + { + "id": "Promotion", + "type": "class", + "position": { + "x": -700, + "y": -10 + }, + "selected": false, + "data": { + "label": "Promotion", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Promotion-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -700, + "y": -10 + }, + "logical": { + "x": -700, + "y": -10 + }, + "physical": { + "x": -700, + "y": -10 + } + } + } + }, + { + "id": "Basket", + "type": "class", + "position": { + "x": -240, + "y": -10 + }, + "selected": false, + "data": { + "label": "Basket", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Basket-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -240, + "y": -10 + }, + "logical": { + "x": -240, + "y": -10 + }, + "physical": { + "x": -240, + "y": -10 + } + } + } + }, + { + "id": "Reservation", + "type": "class", + "position": { + "x": 220, + "y": -10 + }, + "selected": false, + "data": { + "label": "Reservation", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Reservation-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 220, + "y": -10 + }, + "logical": { + "x": 220, + "y": -10 + }, + "physical": { + "x": 220, + "y": -10 + } + } + } + }, + { + "id": "Subscription", + "type": "class", + "position": { + "x": 680, + "y": -10 + }, + "selected": false, + "data": { + "label": "Subscription", + "logicalName": "", + "color": "#009688", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 680, + "y": -10 + }, + "logical": { + "x": 680, + "y": -10 + }, + "physical": { + "x": 680, + "y": -10 + } + } + } + }, + { + "id": "Channel", + "type": "class", + "position": { + "x": 1140, + "y": -10 + }, + "selected": false, + "data": { + "label": "Channel", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Channel-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": -10 + }, + "logical": { + "x": 1140, + "y": -10 + }, + "physical": { + "x": 1140, + "y": -10 + } + } + } + }, + { + "id": "Offer", + "type": "class", + "position": { + "x": 1600, + "y": -10 + }, + "selected": false, + "data": { + "label": "Offer", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Offer-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Offer-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1600, + "y": -10 + }, + "logical": { + "x": 1600, + "y": -10 + }, + "physical": { + "x": 1600, + "y": -10 + } + } + } + }, + { + "id": "Warehouse", + "type": "class", + "position": { + "x": -700, + "y": 430 + }, + "selected": false, + "data": { + "label": "Warehouse", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Warehouse-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -700, + "y": 430 + }, + "logical": { + "x": -700, + "y": 430 + }, + "physical": { + "x": -700, + "y": 430 + } + } + } + }, + { + "id": "Inventory", + "type": "class", + "position": { + "x": -240, + "y": 430 + }, + "selected": false, + "data": { + "label": "Inventory", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Inventory-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inventory-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inventory-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inventory-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -240, + "y": 430 + }, + "logical": { + "x": -240, + "y": 430 + }, + "physical": { + "x": -240, + "y": 430 + } + } + } + }, + { + "id": "StockMovement", + "type": "class", + "position": { + "x": 220, + "y": 430 + }, + "selected": false, + "data": { + "label": "StockMovement", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "StockMovement-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "StockMovement-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "StockMovement-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "StockMovement-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "StockMovement-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 220, + "y": 430 + }, + "logical": { + "x": 220, + "y": 430 + }, + "physical": { + "x": 220, + "y": 430 + } + } + } + }, + { + "id": "Shipment", + "type": "class", + "position": { + "x": 680, + "y": 430 + }, + "selected": false, + "data": { + "label": "Shipment", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Shipment-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 680, + "y": 430 + }, + "logical": { + "x": 680, + "y": 430 + }, + "physical": { + "x": 680, + "y": 430 + } + } + } + }, + { + "id": "Parcel", + "type": "class", + "position": { + "x": 1140, + "y": 430 + }, + "selected": false, + "data": { + "label": "Parcel", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Parcel-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": 430 + }, + "logical": { + "x": 1140, + "y": 430 + }, + "physical": { + "x": 1140, + "y": 430 + } + } + } + }, + { + "id": "Carrier", + "type": "class", + "position": { + "x": 1600, + "y": 430 + }, + "selected": false, + "data": { + "label": "Carrier", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Carrier-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1600, + "y": 430 + }, + "logical": { + "x": 1600, + "y": 430 + }, + "physical": { + "x": 1600, + "y": 430 + } + } + } + }, + { + "id": "Delivery", + "type": "class", + "position": { + "x": -700, + "y": 870 + }, + "selected": false, + "data": { + "label": "Delivery", + "logicalName": "", + "color": "#2196f3", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -700, + "y": 870 + }, + "logical": { + "x": -700, + "y": 870 + }, + "physical": { + "x": -700, + "y": 870 + } + } + } + }, + { + "id": "Route", + "type": "class", + "position": { + "x": -240, + "y": 870 + }, + "selected": false, + "data": { + "label": "Route", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Route-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -240, + "y": 870 + }, + "logical": { + "x": -240, + "y": 870 + }, + "physical": { + "x": -240, + "y": 870 + } + } + } + }, + { + "id": "Location", + "type": "class", + "position": { + "x": 220, + "y": 870 + }, + "selected": false, + "data": { + "label": "Location", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Location-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Location-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 220, + "y": 870 + }, + "logical": { + "x": 220, + "y": 870 + }, + "physical": { + "x": 220, + "y": 870 + } + } + } + }, + { + "id": "Return", + "type": "class", + "position": { + "x": 680, + "y": 870 + }, + "selected": false, + "data": { + "label": "Return", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Return-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 680, + "y": 870 + }, + "logical": { + "x": 680, + "y": 870 + }, + "physical": { + "x": 680, + "y": 870 + } + } + } + }, + { + "id": "Inspection", + "type": "class", + "position": { + "x": 1140, + "y": 870 + }, + "selected": false, + "data": { + "label": "Inspection", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Inspection-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": 870 + }, + "logical": { + "x": 1140, + "y": 870 + }, + "physical": { + "x": 1140, + "y": 870 + } + } + } + }, + { + "id": "HandlingUnit", + "type": "class", + "position": { + "x": 1600, + "y": 870 + }, + "selected": false, + "data": { + "label": "HandlingUnit", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "HandlingUnit-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "HandlingUnit-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "HandlingUnit-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "HandlingUnit-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "HandlingUnit-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1600, + "y": 870 + }, + "logical": { + "x": 1600, + "y": 870 + }, + "physical": { + "x": 1600, + "y": 870 + } + } + } + }, + { + "id": "Invoice", + "type": "class", + "position": { + "x": -700, + "y": 1310 + }, + "selected": false, + "data": { + "label": "Invoice", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Invoice-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -700, + "y": 1310 + }, + "logical": { + "x": -700, + "y": 1310 + }, + "physical": { + "x": -700, + "y": 1310 + } + } + } + }, + { + "id": "InvoiceLine", + "type": "class", + "position": { + "x": -240, + "y": 1310 + }, + "selected": false, + "data": { + "label": "InvoiceLine", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "InvoiceLine-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "InvoiceLine-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -240, + "y": 1310 + }, + "logical": { + "x": -240, + "y": 1310 + }, + "physical": { + "x": -240, + "y": 1310 + } + } + } + }, + { + "id": "Payment", + "type": "class", + "position": { + "x": 220, + "y": 1310 + }, + "selected": false, + "data": { + "label": "Payment", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Payment-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payment-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 220, + "y": 1310 + }, + "logical": { + "x": 220, + "y": 1310 + }, + "physical": { + "x": 220, + "y": 1310 + } + } + } + }, + { + "id": "Refund", + "type": "class", + "position": { + "x": 680, + "y": 1310 + }, + "selected": false, + "data": { + "label": "Refund", + "logicalName": "", + "color": "#ffc107", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 680, + "y": 1310 + }, + "logical": { + "x": 680, + "y": 1310 + }, + "physical": { + "x": 680, + "y": 1310 + } + } + } + }, + { + "id": "Ledger", + "type": "class", + "position": { + "x": 1140, + "y": 1310 + }, + "selected": false, + "data": { + "label": "Ledger", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Ledger-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": 1310 + }, + "logical": { + "x": 1140, + "y": 1310 + }, + "physical": { + "x": 1140, + "y": 1310 + } + } + } + }, + { + "id": "Fulfilment", + "type": "class", + "position": { + "x": 2200, + "y": 1200 + }, + "selected": false, + "data": { + "label": "fulfilledBy", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Fulfilment-attr-0", + "name": "allocatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Fulfilment-attr-1", + "name": "quantity", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2200, + "y": 1200 + }, + "logical": { + "x": 2200, + "y": 1200 + }, + "physical": { + "x": 2200, + "y": 1200 + } + } + } + }, + { + "id": "PriceValidity", + "type": "class", + "position": { + "x": 2200, + "y": 1570 + }, + "selected": false, + "data": { + "label": "pricedAt", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "PriceValidity-attr-0", + "name": "fromDate", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "PriceValidity-attr-1", + "name": "toDate", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2200, + "y": 1570 + }, + "logical": { + "x": 2200, + "y": 1570 + }, + "physical": { + "x": 2200, + "y": 1570 + } + } + } + }, + { + "id": "RefundDecision", + "type": "class", + "position": { + "x": 2200, + "y": 1950 + }, + "selected": false, + "data": { + "label": "reversedBy", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "RefundDecision-attr-0", + "name": "reason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RefundDecision-attr-1", + "name": "authorisedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2200, + "y": 1950 + }, + "logical": { + "x": 2200, + "y": 1950 + }, + "physical": { + "x": 2200, + "y": 1950 + } + } + } + }, + { + "id": "area-0065", + "type": "area", + "position": { + "x": -780, + "y": -540 + }, + "selected": false, + "data": { + "label": "Sales", + "color": "#009688", + "viewSizes": { + "conceptual": { + "width": 890, + "height": 2250 + }, + "logical": { + "width": 890, + "height": 2250 + }, + "physical": { + "width": 890, + "height": 2250 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -780, + "y": -540 + }, + "logical": { + "x": -780, + "y": -540 + }, + "physical": { + "x": -780, + "y": -540 + } + } + }, + "width": 890, + "height": 2250, + "style": { + "width": 890, + "height": 2250 + }, + "zIndex": -1 + }, + { + "id": "note-0066", + "type": "note", + "position": { + "x": -1050, + "y": 2300 + }, + "selected": false, + "data": { + "label": "Review 1", + "text": "Compare two, three and four parallel connections. Keep every role and multiplicity visible.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1050, + "y": 2300 + }, + "logical": { + "x": -1050, + "y": 2300 + }, + "physical": { + "x": -1050, + "y": 2300 + } + } + } + }, + { + "id": "area-0070", + "type": "area", + "position": { + "x": 140, + "y": -540 + }, + "selected": false, + "data": { + "label": "Fulfilment", + "color": "#2196f3", + "viewSizes": { + "conceptual": { + "width": 890, + "height": 2250 + }, + "logical": { + "width": 890, + "height": 2250 + }, + "physical": { + "width": 890, + "height": 2250 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 140, + "y": -540 + }, + "logical": { + "x": 140, + "y": -540 + }, + "physical": { + "x": 140, + "y": -540 + } + } + }, + "width": 890, + "height": 2250, + "style": { + "width": 890, + "height": 2250 + }, + "zIndex": -1 + }, + { + "id": "note-0071", + "type": "note", + "position": { + "x": 350, + "y": 2300 + }, + "selected": false, + "data": { + "label": "Review 2", + "text": "Inspect dense crossings and dashed association-class attachments after dragging.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 350, + "y": 2300 + }, + "logical": { + "x": 350, + "y": 2300 + }, + "physical": { + "x": 350, + "y": 2300 + } + } + } + }, + { + "id": "area-0075", + "type": "area", + "position": { + "x": 1060, + "y": -540 + }, + "selected": false, + "data": { + "label": "Finance", + "color": "#ffc107", + "viewSizes": { + "conceptual": { + "width": 890, + "height": 2250 + }, + "logical": { + "width": 890, + "height": 2250 + }, + "physical": { + "width": 890, + "height": 2250 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1060, + "y": -540 + }, + "logical": { + "x": 1060, + "y": -540 + }, + "physical": { + "x": 1060, + "y": -540 + } + } + }, + "width": 890, + "height": 2250, + "style": { + "width": 890, + "height": 2250 + }, + "zIndex": -1 + }, + { + "id": "note-0076", + "type": "note", + "position": { + "x": 1750, + "y": 2300 + }, + "selected": false, + "data": { + "label": "Review 3", + "text": "Try hiding notes and areas, then export with both included.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1750, + "y": 2300 + }, + "logical": { + "x": 1750, + "y": 2300 + }, + "physical": { + "x": 1750, + "y": 2300 + } + } + } + }, + { + "id": "area-0080", + "type": "area", + "position": { + "x": -850, + "y": 800 + }, + "selected": false, + "data": { + "label": "Cross-domain audit boundary", + "color": "#94a3b8", + "viewSizes": { + "conceptual": { + "width": 3100, + "height": 360 + }, + "logical": { + "width": 3100, + "height": 360 + }, + "physical": { + "width": 3100, + "height": 360 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -850, + "y": 800 + }, + "logical": { + "x": -850, + "y": 800 + }, + "physical": { + "x": -850, + "y": 800 + } + } + }, + "width": 3100, + "height": 360, + "style": { + "width": 3100, + "height": 360 + }, + "zIndex": -1 + } + ], + "edges": [ + { + "id": "edge-0001", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "composition", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 5 + } + }, + { + "id": "edge-0002", + "source": "Customer", + "target": "Basket", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0003", + "source": "Order", + "target": "OrderLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0004", + "source": "OrderLine", + "target": "Product", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0005", + "source": "OrderLine", + "target": "Subscription", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0006", + "source": "Product", + "target": "Catalogue", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0007", + "source": "Catalogue", + "target": "Price", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0008", + "source": "Catalogue", + "target": "Offer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0009", + "source": "Price", + "target": "Promotion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0010", + "source": "Promotion", + "target": "Basket", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0011", + "source": "Promotion", + "target": "Inventory", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0012", + "source": "Basket", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "composition", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0013", + "source": "Reservation", + "target": "Subscription", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0014", + "source": "Reservation", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0015", + "source": "Subscription", + "target": "Channel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0016", + "source": "Channel", + "target": "Offer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0017", + "source": "Channel", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0018", + "source": "Offer", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0019", + "source": "Warehouse", + "target": "Inventory", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0020", + "source": "Warehouse", + "target": "Route", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0021", + "source": "Inventory", + "target": "StockMovement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0022", + "source": "StockMovement", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "composition", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0023", + "source": "StockMovement", + "target": "Return", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0024", + "source": "Shipment", + "target": "Parcel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0025", + "source": "Parcel", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0026", + "source": "Parcel", + "target": "HandlingUnit", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0027", + "source": "Carrier", + "target": "Delivery", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0028", + "source": "Delivery", + "target": "Route", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0029", + "source": "Delivery", + "target": "InvoiceLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0030", + "source": "Route", + "target": "Location", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0031", + "source": "Location", + "target": "Return", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0032", + "source": "Location", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0033", + "source": "Return", + "target": "Inspection", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "composition", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0034", + "source": "Inspection", + "target": "HandlingUnit", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0035", + "source": "Inspection", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0036", + "source": "HandlingUnit", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0037", + "source": "Invoice", + "target": "InvoiceLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0038", + "source": "Invoice", + "target": "OrderLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0039", + "source": "InvoiceLine", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0040", + "source": "Payment", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0041", + "source": "Payment", + "target": "Catalogue", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0042", + "source": "Refund", + "target": "Ledger", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0043", + "source": "Ledger", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "contains", + "type": "composition", + "roleA": "sourceRecord", + "roleB": "relatedRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0044", + "source": "Ledger", + "target": "Promotion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0045", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "places", + "type": "association", + "roleA": "buyer", + "roleB": "orders", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 5 + } + }, + { + "id": "edge-0046", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "approves", + "type": "association", + "roleA": "approver", + "roleB": "orders", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 5 + } + }, + { + "id": "edge-0047", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "cancels", + "type": "association", + "roleA": "requester", + "roleB": "orders", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 3, + "parallelCount": 5 + } + }, + { + "id": "edge-0048", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "receives", + "type": "association", + "roleA": "recipient", + "roleB": "orders", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 4, + "parallelCount": 5 + } + }, + { + "id": "edge-0049", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "replaces", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0050", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "splitsInto", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0051", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "mergesWith", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0052", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "dependsOn", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0053", + "source": "Warehouse", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supplies", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0054", + "source": "Warehouse", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "backsUp", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0055", + "source": "Warehouse", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "replenishes", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0056", + "source": "Warehouse", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isManagedBy", + "type": "association", + "roleA": "parent", + "roleB": "child", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 85, + "loopHeight": 125 + } + }, + { + "id": "edge-0057", + "source": "Order", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "fulfilledBy", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "associative-0058", + "source": "Fulfilment", + "target": "assoc-edge-edge-0057", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "fulfilledBy", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0059", + "source": "Product", + "target": "Price", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "pricedAt", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "associative-0060", + "source": "PriceValidity", + "target": "assoc-edge-edge-0059", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "pricedAt", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0061", + "source": "Payment", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reversedBy", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "associative-0062", + "source": "RefundDecision", + "target": "assoc-edge-edge-0061", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reversedBy", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0063", + "source": "Return", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "adjusts", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": 2100, + "y": 1100 + }, + { + "x": 2100, + "y": 2050 + }, + { + "x": 800, + "y": 2050 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0064", + "source": "Inventory", + "target": "Ledger", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "valuedBy", + "type": "association", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": -950, + "y": 800 + }, + { + "x": -950, + "y": 2200 + }, + { + "x": 1500, + "y": 2200 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + } + ], + "annotations": { + "conceptual": { + "items": [ + { + "id": "text-0067", + "kind": "text", + "x": -650, + "y": -650, + "text": "A / Sales", + "color": "#334155", + "fontSize": 26 + }, + { + "id": "arrow-0068", + "kind": "shape", + "shape": "arrow", + "x1": -600, + "y1": 2220, + "x2": -500, + "y2": 1860, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "stroke-0069", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": -600, + "y": -590 + }, + { + "x": -300, + "y": -580 + }, + { + "x": 100, + "y": -590 + } + ], + "color": "#facc15", + "thickness": 15, + "opacity": 0.3 + }, + { + "id": "text-0072", + "kind": "text", + "x": 250, + "y": -650, + "text": "B / Operations", + "color": "#334155", + "fontSize": 26 + }, + { + "id": "arrow-0073", + "kind": "shape", + "shape": "arrow", + "x1": 300, + "y1": 2220, + "x2": 400, + "y2": 1860, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "stroke-0074", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": 300, + "y": -590 + }, + { + "x": 600, + "y": -580 + }, + { + "x": 1000, + "y": -590 + } + ], + "color": "#facc15", + "thickness": 15, + "opacity": 0.3 + }, + { + "id": "text-0077", + "kind": "text", + "x": 1150, + "y": -650, + "text": "C / Accounting", + "color": "#334155", + "fontSize": 26 + }, + { + "id": "arrow-0078", + "kind": "shape", + "shape": "arrow", + "x1": 1200, + "y1": 2220, + "x2": 1300, + "y2": 1860, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "stroke-0079", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": 1200, + "y": -590 + }, + { + "x": 1500, + "y": -580 + }, + { + "x": 1900, + "y": -590 + } + ], + "color": "#facc15", + "thickness": 15, + "opacity": 0.3 + }, + { + "id": "ellipse-0081", + "kind": "shape", + "shape": "ellipse", + "x1": -900, + "y1": -700, + "x2": -200, + "y2": -180, + "color": "#dc2626", + "thickness": 2 + }, + { + "id": "text-0082", + "kind": "text", + "x": 1900, + "y": -350, + "text": "Manual routes are intentional. Preserve their control points.", + "color": "#334155", + "fontSize": 18, + "width": 340, + "padding": 12, + "background": "#e0f2fe", + "border": true + } + ] + }, + "logical": { + "items": [] + }, + "physical": { + "items": [] + } + } +} diff --git a/examples/05-global-platform-frontier.mdlz b/examples/05-global-platform-frontier.mdlz new file mode 100644 index 0000000..2339a7f --- /dev/null +++ b/examples/05-global-platform-frontier.mdlz @@ -0,0 +1,21748 @@ +{ + "version": 2, + "modelName": "05 - Global platform readability frontier", + "nodes": [ + { + "id": "area-0001", + "type": "area", + "position": { + "x": -2400, + "y": -1800 + }, + "selected": false, + "data": { + "label": "1 / Identity", + "color": "#009688", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2400, + "y": -1800 + }, + "logical": { + "x": -2400, + "y": -1800 + }, + "physical": { + "x": -2400, + "y": -1800 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Person", + "type": "class", + "position": { + "x": -2320, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Person", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Person-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Person-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": -1650 + }, + "logical": { + "x": -2320, + "y": -1650 + }, + "physical": { + "x": -2320, + "y": -1650 + } + } + } + }, + { + "id": "Organisation", + "type": "class", + "position": { + "x": -1840, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Organisation", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Organisation-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": -1650 + }, + "logical": { + "x": -1840, + "y": -1650 + }, + "physical": { + "x": -1840, + "y": -1650 + } + } + } + }, + { + "id": "Account", + "type": "class", + "position": { + "x": -1360, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Account", + "logicalName": "", + "color": "#009688", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": -1650 + }, + "logical": { + "x": -1360, + "y": -1650 + }, + "physical": { + "x": -1360, + "y": -1650 + } + } + } + }, + { + "id": "Membership", + "type": "class", + "position": { + "x": -880, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Membership", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Membership-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Membership-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": -1650 + }, + "logical": { + "x": -880, + "y": -1650 + }, + "physical": { + "x": -880, + "y": -1650 + } + } + } + }, + { + "id": "Role", + "type": "class", + "position": { + "x": -2320, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Role", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Role-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Role-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Role-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": -1130 + }, + "logical": { + "x": -2320, + "y": -1130 + }, + "physical": { + "x": -2320, + "y": -1130 + } + } + } + }, + { + "id": "Permission", + "type": "class", + "position": { + "x": -1840, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Permission", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Permission-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Permission-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": -1130 + }, + "logical": { + "x": -1840, + "y": -1130 + }, + "physical": { + "x": -1840, + "y": -1130 + } + } + } + }, + { + "id": "Credential", + "type": "class", + "position": { + "x": -1360, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Credential", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Credential-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Credential-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": -1130 + }, + "logical": { + "x": -1360, + "y": -1130 + }, + "physical": { + "x": -1360, + "y": -1130 + } + } + } + }, + { + "id": "Consent", + "type": "class", + "position": { + "x": -880, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Consent", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Consent-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Consent-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": -1130 + }, + "logical": { + "x": -880, + "y": -1130 + }, + "physical": { + "x": -880, + "y": -1130 + } + } + } + }, + { + "id": "Address", + "type": "class", + "position": { + "x": -2320, + "y": -610 + }, + "selected": false, + "data": { + "label": "Address", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Address-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Address-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Address-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Address-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": -610 + }, + "logical": { + "x": -2320, + "y": -610 + }, + "physical": { + "x": -2320, + "y": -610 + } + } + } + }, + { + "id": "ContactPoint", + "type": "class", + "position": { + "x": -1840, + "y": -610 + }, + "selected": false, + "data": { + "label": "ContactPoint", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "ContactPoint-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "ContactPoint-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": -610 + }, + "logical": { + "x": -1840, + "y": -610 + }, + "physical": { + "x": -1840, + "y": -610 + } + } + } + }, + { + "id": "Device", + "type": "class", + "position": { + "x": -1360, + "y": -610 + }, + "selected": false, + "data": { + "label": "Device", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Device-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Device-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Device-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Device-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Device-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": -610 + }, + "logical": { + "x": -1360, + "y": -610 + }, + "physical": { + "x": -1360, + "y": -610 + } + } + } + }, + { + "id": "Session", + "type": "class", + "position": { + "x": -880, + "y": -610 + }, + "selected": false, + "data": { + "label": "SessionWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#009688", + "attributes": [ + { + "id": "Session-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": -610 + }, + "logical": { + "x": -880, + "y": -610 + }, + "physical": { + "x": -880, + "y": -610 + } + } + } + }, + { + "id": "note-0031", + "type": "note", + "position": { + "x": -2330, + "y": 120 + }, + "selected": false, + "data": { + "label": "Identity: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2330, + "y": 120 + }, + "logical": { + "x": -2330, + "y": 120 + }, + "physical": { + "x": -2330, + "y": 120 + } + } + } + }, + { + "id": "note-0032", + "type": "note", + "position": { + "x": -1940, + "y": 120 + }, + "selected": false, + "data": { + "label": "Identity: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1940, + "y": 120 + }, + "logical": { + "x": -1940, + "y": 120 + }, + "physical": { + "x": -1940, + "y": 120 + } + } + } + }, + { + "id": "area-0038", + "type": "area", + "position": { + "x": -120, + "y": -1800 + }, + "selected": false, + "data": { + "label": "2 / Commerce", + "color": "#2196f3", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -120, + "y": -1800 + }, + "logical": { + "x": -120, + "y": -1800 + }, + "physical": { + "x": -120, + "y": -1800 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Customer", + "type": "class", + "position": { + "x": -40, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Customer", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Customer-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Customer-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": -1650 + }, + "logical": { + "x": -40, + "y": -1650 + }, + "physical": { + "x": -40, + "y": -1650 + } + } + } + }, + { + "id": "Order", + "type": "class", + "position": { + "x": 440, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Order", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Order-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": -1650 + }, + "logical": { + "x": 440, + "y": -1650 + }, + "physical": { + "x": 440, + "y": -1650 + } + } + } + }, + { + "id": "OrderLine", + "type": "class", + "position": { + "x": 920, + "y": -1650 + }, + "selected": false, + "data": { + "label": "OrderLine", + "logicalName": "", + "color": "#2196f3", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": -1650 + }, + "logical": { + "x": 920, + "y": -1650 + }, + "physical": { + "x": 920, + "y": -1650 + } + } + } + }, + { + "id": "Product", + "type": "class", + "position": { + "x": 1400, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Product", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Product-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Product-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": -1650 + }, + "logical": { + "x": 1400, + "y": -1650 + }, + "physical": { + "x": 1400, + "y": -1650 + } + } + } + }, + { + "id": "Catalogue", + "type": "class", + "position": { + "x": -40, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Catalogue", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Catalogue-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Catalogue-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Catalogue-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": -1130 + }, + "logical": { + "x": -40, + "y": -1130 + }, + "physical": { + "x": -40, + "y": -1130 + } + } + } + }, + { + "id": "Price", + "type": "class", + "position": { + "x": 440, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Price", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Price-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Price-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": -1130 + }, + "logical": { + "x": 440, + "y": -1130 + }, + "physical": { + "x": 440, + "y": -1130 + } + } + } + }, + { + "id": "Promotion", + "type": "class", + "position": { + "x": 920, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Promotion", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Promotion-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Promotion-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": -1130 + }, + "logical": { + "x": 920, + "y": -1130 + }, + "physical": { + "x": 920, + "y": -1130 + } + } + } + }, + { + "id": "Basket", + "type": "class", + "position": { + "x": 1400, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Basket", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Basket-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Basket-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": -1130 + }, + "logical": { + "x": 1400, + "y": -1130 + }, + "physical": { + "x": 1400, + "y": -1130 + } + } + } + }, + { + "id": "Reservation", + "type": "class", + "position": { + "x": -40, + "y": -610 + }, + "selected": false, + "data": { + "label": "Reservation", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Reservation-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Reservation-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": -610 + }, + "logical": { + "x": -40, + "y": -610 + }, + "physical": { + "x": -40, + "y": -610 + } + } + } + }, + { + "id": "Subscription", + "type": "class", + "position": { + "x": 440, + "y": -610 + }, + "selected": false, + "data": { + "label": "Subscription", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Subscription-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Subscription-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": -610 + }, + "logical": { + "x": 440, + "y": -610 + }, + "physical": { + "x": 440, + "y": -610 + } + } + } + }, + { + "id": "Channel", + "type": "class", + "position": { + "x": 920, + "y": -610 + }, + "selected": false, + "data": { + "label": "Channel", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Channel-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Channel-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Channel-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Channel-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Channel-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": -610 + }, + "logical": { + "x": 920, + "y": -610 + }, + "physical": { + "x": 920, + "y": -610 + } + } + } + }, + { + "id": "Offer", + "type": "class", + "position": { + "x": 1400, + "y": -610 + }, + "selected": false, + "data": { + "label": "OfferWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#2196f3", + "attributes": [ + { + "id": "Offer-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": -610 + }, + "logical": { + "x": 1400, + "y": -610 + }, + "physical": { + "x": 1400, + "y": -610 + } + } + } + }, + { + "id": "note-0068", + "type": "note", + "position": { + "x": -50, + "y": 120 + }, + "selected": false, + "data": { + "label": "Commerce: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -50, + "y": 120 + }, + "logical": { + "x": -50, + "y": 120 + }, + "physical": { + "x": -50, + "y": 120 + } + } + } + }, + { + "id": "note-0069", + "type": "note", + "position": { + "x": 340, + "y": 120 + }, + "selected": false, + "data": { + "label": "Commerce: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 340, + "y": 120 + }, + "logical": { + "x": 340, + "y": 120 + }, + "physical": { + "x": 340, + "y": 120 + } + } + } + }, + { + "id": "area-0075", + "type": "area", + "position": { + "x": 2160, + "y": -1800 + }, + "selected": false, + "data": { + "label": "3 / Fulfilment", + "color": "#ffc107", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2160, + "y": -1800 + }, + "logical": { + "x": 2160, + "y": -1800 + }, + "physical": { + "x": 2160, + "y": -1800 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Warehouse", + "type": "class", + "position": { + "x": 2240, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Warehouse", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Warehouse-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Warehouse-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": -1650 + }, + "logical": { + "x": 2240, + "y": -1650 + }, + "physical": { + "x": 2240, + "y": -1650 + } + } + } + }, + { + "id": "Inventory", + "type": "class", + "position": { + "x": 2720, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Inventory", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Inventory-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": -1650 + }, + "logical": { + "x": 2720, + "y": -1650 + }, + "physical": { + "x": 2720, + "y": -1650 + } + } + } + }, + { + "id": "StockMovement", + "type": "class", + "position": { + "x": 3200, + "y": -1650 + }, + "selected": false, + "data": { + "label": "StockMovement", + "logicalName": "", + "color": "#ffc107", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": -1650 + }, + "logical": { + "x": 3200, + "y": -1650 + }, + "physical": { + "x": 3200, + "y": -1650 + } + } + } + }, + { + "id": "Shipment", + "type": "class", + "position": { + "x": 3680, + "y": -1650 + }, + "selected": false, + "data": { + "label": "Shipment", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Shipment-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Shipment-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": -1650 + }, + "logical": { + "x": 3680, + "y": -1650 + }, + "physical": { + "x": 3680, + "y": -1650 + } + } + } + }, + { + "id": "Parcel", + "type": "class", + "position": { + "x": 2240, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Parcel", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Parcel-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Parcel-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": -1130 + }, + "logical": { + "x": 2240, + "y": -1130 + }, + "physical": { + "x": 2240, + "y": -1130 + } + } + } + }, + { + "id": "Carrier", + "type": "class", + "position": { + "x": 2720, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Carrier", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Carrier-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Carrier-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": -1130 + }, + "logical": { + "x": 2720, + "y": -1130 + }, + "physical": { + "x": 2720, + "y": -1130 + } + } + } + }, + { + "id": "Delivery", + "type": "class", + "position": { + "x": 3200, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Delivery", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Delivery-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Delivery-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": -1130 + }, + "logical": { + "x": 3200, + "y": -1130 + }, + "physical": { + "x": 3200, + "y": -1130 + } + } + } + }, + { + "id": "Route", + "type": "class", + "position": { + "x": 3680, + "y": -1130 + }, + "selected": false, + "data": { + "label": "Route", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Route-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Route-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": -1130 + }, + "logical": { + "x": 3680, + "y": -1130 + }, + "physical": { + "x": 3680, + "y": -1130 + } + } + } + }, + { + "id": "Location", + "type": "class", + "position": { + "x": 2240, + "y": -610 + }, + "selected": false, + "data": { + "label": "Location", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Location-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Location-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Location-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Location-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": -610 + }, + "logical": { + "x": 2240, + "y": -610 + }, + "physical": { + "x": 2240, + "y": -610 + } + } + } + }, + { + "id": "Return", + "type": "class", + "position": { + "x": 2720, + "y": -610 + }, + "selected": false, + "data": { + "label": "Return", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Return-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Return-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": -610 + }, + "logical": { + "x": 2720, + "y": -610 + }, + "physical": { + "x": 2720, + "y": -610 + } + } + } + }, + { + "id": "Inspection", + "type": "class", + "position": { + "x": 3200, + "y": -610 + }, + "selected": false, + "data": { + "label": "Inspection", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "Inspection-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Inspection-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": -610 + }, + "logical": { + "x": 3200, + "y": -610 + }, + "physical": { + "x": 3200, + "y": -610 + } + } + } + }, + { + "id": "HandlingUnit", + "type": "class", + "position": { + "x": 3680, + "y": -610 + }, + "selected": false, + "data": { + "label": "HandlingUnitWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#ffc107", + "attributes": [ + { + "id": "HandlingUnit-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": -610 + }, + "logical": { + "x": 3680, + "y": -610 + }, + "physical": { + "x": 3680, + "y": -610 + } + } + } + }, + { + "id": "note-0105", + "type": "note", + "position": { + "x": 2230, + "y": 120 + }, + "selected": false, + "data": { + "label": "Fulfilment: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2230, + "y": 120 + }, + "logical": { + "x": 2230, + "y": 120 + }, + "physical": { + "x": 2230, + "y": 120 + } + } + } + }, + { + "id": "note-0106", + "type": "note", + "position": { + "x": 2620, + "y": 120 + }, + "selected": false, + "data": { + "label": "Fulfilment: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2620, + "y": 120 + }, + "logical": { + "x": 2620, + "y": 120 + }, + "physical": { + "x": 2620, + "y": 120 + } + } + } + }, + { + "id": "area-0112", + "type": "area", + "position": { + "x": -2400, + "y": 780 + }, + "selected": false, + "data": { + "label": "4 / Finance", + "color": "#9c27b0", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2400, + "y": 780 + }, + "logical": { + "x": -2400, + "y": 780 + }, + "physical": { + "x": -2400, + "y": 780 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Invoice", + "type": "class", + "position": { + "x": -2320, + "y": 930 + }, + "selected": false, + "data": { + "label": "Invoice", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Invoice-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Invoice-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": 930 + }, + "logical": { + "x": -2320, + "y": 930 + }, + "physical": { + "x": -2320, + "y": 930 + } + } + } + }, + { + "id": "InvoiceLine", + "type": "class", + "position": { + "x": -1840, + "y": 930 + }, + "selected": false, + "data": { + "label": "InvoiceLine", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "InvoiceLine-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": 930 + }, + "logical": { + "x": -1840, + "y": 930 + }, + "physical": { + "x": -1840, + "y": 930 + } + } + } + }, + { + "id": "Payment", + "type": "class", + "position": { + "x": -1360, + "y": 930 + }, + "selected": false, + "data": { + "label": "Payment", + "logicalName": "", + "color": "#9c27b0", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": 930 + }, + "logical": { + "x": -1360, + "y": 930 + }, + "physical": { + "x": -1360, + "y": 930 + } + } + } + }, + { + "id": "Refund", + "type": "class", + "position": { + "x": -880, + "y": 930 + }, + "selected": false, + "data": { + "label": "Refund", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Refund-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Refund-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": 930 + }, + "logical": { + "x": -880, + "y": 930 + }, + "physical": { + "x": -880, + "y": 930 + } + } + } + }, + { + "id": "Ledger", + "type": "class", + "position": { + "x": -2320, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Ledger", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Ledger-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Ledger-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Ledger-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": 1450 + }, + "logical": { + "x": -2320, + "y": 1450 + }, + "physical": { + "x": -2320, + "y": 1450 + } + } + } + }, + { + "id": "LedgerEntry", + "type": "class", + "position": { + "x": -1840, + "y": 1450 + }, + "selected": false, + "data": { + "label": "LedgerEntry", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "LedgerEntry-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LedgerEntry-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": 1450 + }, + "logical": { + "x": -1840, + "y": 1450 + }, + "physical": { + "x": -1840, + "y": 1450 + } + } + } + }, + { + "id": "TaxRule", + "type": "class", + "position": { + "x": -1360, + "y": 1450 + }, + "selected": false, + "data": { + "label": "TaxRule", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "TaxRule-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "TaxRule-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": 1450 + }, + "logical": { + "x": -1360, + "y": 1450 + }, + "physical": { + "x": -1360, + "y": 1450 + } + } + } + }, + { + "id": "Currency", + "type": "class", + "position": { + "x": -880, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Currency", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Currency-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Currency-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": 1450 + }, + "logical": { + "x": -880, + "y": 1450 + }, + "physical": { + "x": -880, + "y": 1450 + } + } + } + }, + { + "id": "Settlement", + "type": "class", + "position": { + "x": -2320, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Settlement", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Settlement-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Settlement-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Settlement-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Settlement-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2320, + "y": 1970 + }, + "logical": { + "x": -2320, + "y": 1970 + }, + "physical": { + "x": -2320, + "y": 1970 + } + } + } + }, + { + "id": "Payout", + "type": "class", + "position": { + "x": -1840, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Payout", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Payout-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Payout-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1840, + "y": 1970 + }, + "logical": { + "x": -1840, + "y": 1970 + }, + "physical": { + "x": -1840, + "y": 1970 + } + } + } + }, + { + "id": "Dispute", + "type": "class", + "position": { + "x": -1360, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Dispute", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "Dispute-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dispute-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dispute-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dispute-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dispute-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1360, + "y": 1970 + }, + "logical": { + "x": -1360, + "y": 1970 + }, + "physical": { + "x": -1360, + "y": 1970 + } + } + } + }, + { + "id": "ExchangeRate", + "type": "class", + "position": { + "x": -880, + "y": 1970 + }, + "selected": false, + "data": { + "label": "ExchangeRateWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "ExchangeRate-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -880, + "y": 1970 + }, + "logical": { + "x": -880, + "y": 1970 + }, + "physical": { + "x": -880, + "y": 1970 + } + } + } + }, + { + "id": "note-0142", + "type": "note", + "position": { + "x": -2330, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Finance: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2330, + "y": 2700 + }, + "logical": { + "x": -2330, + "y": 2700 + }, + "physical": { + "x": -2330, + "y": 2700 + } + } + } + }, + { + "id": "note-0143", + "type": "note", + "position": { + "x": -1940, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Finance: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1940, + "y": 2700 + }, + "logical": { + "x": -1940, + "y": 2700 + }, + "physical": { + "x": -1940, + "y": 2700 + } + } + } + }, + { + "id": "area-0149", + "type": "area", + "position": { + "x": -120, + "y": 780 + }, + "selected": false, + "data": { + "label": "5 / Trust", + "color": "#ff5722", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -120, + "y": 780 + }, + "logical": { + "x": -120, + "y": 780 + }, + "physical": { + "x": -120, + "y": 780 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Policy", + "type": "class", + "position": { + "x": -40, + "y": 930 + }, + "selected": false, + "data": { + "label": "Policy", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Policy-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Policy-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": 930 + }, + "logical": { + "x": -40, + "y": 930 + }, + "physical": { + "x": -40, + "y": 930 + } + } + } + }, + { + "id": "PolicyVersion", + "type": "class", + "position": { + "x": 440, + "y": 930 + }, + "selected": false, + "data": { + "label": "PolicyVersion", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "PolicyVersion-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": 930 + }, + "logical": { + "x": 440, + "y": 930 + }, + "physical": { + "x": 440, + "y": 930 + } + } + } + }, + { + "id": "RiskAssessment", + "type": "class", + "position": { + "x": 920, + "y": 930 + }, + "selected": false, + "data": { + "label": "RiskAssessment", + "logicalName": "", + "color": "#ff5722", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": 930 + }, + "logical": { + "x": 920, + "y": 930 + }, + "physical": { + "x": 920, + "y": 930 + } + } + } + }, + { + "id": "Approval", + "type": "class", + "position": { + "x": 1400, + "y": 930 + }, + "selected": false, + "data": { + "label": "Approval", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Approval-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Approval-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": 930 + }, + "logical": { + "x": 1400, + "y": 930 + }, + "physical": { + "x": 1400, + "y": 930 + } + } + } + }, + { + "id": "Case", + "type": "class", + "position": { + "x": -40, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Case", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Case-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Case-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Case-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": 1450 + }, + "logical": { + "x": -40, + "y": 1450 + }, + "physical": { + "x": -40, + "y": 1450 + } + } + } + }, + { + "id": "Evidence", + "type": "class", + "position": { + "x": 440, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Evidence", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Evidence-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Evidence-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": 1450 + }, + "logical": { + "x": 440, + "y": 1450 + }, + "physical": { + "x": 440, + "y": 1450 + } + } + } + }, + { + "id": "AuditEvent", + "type": "class", + "position": { + "x": 920, + "y": 1450 + }, + "selected": false, + "data": { + "label": "AuditEvent", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "AuditEvent-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AuditEvent-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": 1450 + }, + "logical": { + "x": 920, + "y": 1450 + }, + "physical": { + "x": 920, + "y": 1450 + } + } + } + }, + { + "id": "RetentionRule", + "type": "class", + "position": { + "x": 1400, + "y": 1450 + }, + "selected": false, + "data": { + "label": "RetentionRule", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "RetentionRule-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "RetentionRule-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": 1450 + }, + "logical": { + "x": 1400, + "y": 1450 + }, + "physical": { + "x": 1400, + "y": 1450 + } + } + } + }, + { + "id": "Jurisdiction", + "type": "class", + "position": { + "x": -40, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Jurisdiction", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Jurisdiction-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Jurisdiction-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Jurisdiction-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Jurisdiction-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -40, + "y": 1970 + }, + "logical": { + "x": -40, + "y": 1970 + }, + "physical": { + "x": -40, + "y": 1970 + } + } + } + }, + { + "id": "LegalBasis", + "type": "class", + "position": { + "x": 440, + "y": 1970 + }, + "selected": false, + "data": { + "label": "LegalBasis", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "LegalBasis-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "LegalBasis-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 440, + "y": 1970 + }, + "logical": { + "x": 440, + "y": 1970 + }, + "physical": { + "x": 440, + "y": 1970 + } + } + } + }, + { + "id": "Control", + "type": "class", + "position": { + "x": 920, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Control", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Control-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Control-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Control-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Control-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Control-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 920, + "y": 1970 + }, + "logical": { + "x": 920, + "y": 1970 + }, + "physical": { + "x": 920, + "y": 1970 + } + } + } + }, + { + "id": "Exception", + "type": "class", + "position": { + "x": 1400, + "y": 1970 + }, + "selected": false, + "data": { + "label": "ExceptionWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#ff5722", + "attributes": [ + { + "id": "Exception-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1400, + "y": 1970 + }, + "logical": { + "x": 1400, + "y": 1970 + }, + "physical": { + "x": 1400, + "y": 1970 + } + } + } + }, + { + "id": "note-0179", + "type": "note", + "position": { + "x": -50, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Trust: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -50, + "y": 2700 + }, + "logical": { + "x": -50, + "y": 2700 + }, + "physical": { + "x": -50, + "y": 2700 + } + } + } + }, + { + "id": "note-0180", + "type": "note", + "position": { + "x": 340, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Trust: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 340, + "y": 2700 + }, + "logical": { + "x": 340, + "y": 2700 + }, + "physical": { + "x": 340, + "y": 2700 + } + } + } + }, + { + "id": "area-0186", + "type": "area", + "position": { + "x": 2160, + "y": 780 + }, + "selected": false, + "data": { + "label": "6 / Analytics", + "color": "#607d8b", + "viewSizes": { + "conceptual": { + "width": 2080, + "height": 1870 + }, + "logical": { + "width": 2080, + "height": 1870 + }, + "physical": { + "width": 2080, + "height": 1870 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2160, + "y": 780 + }, + "logical": { + "x": 2160, + "y": 780 + }, + "physical": { + "x": 2160, + "y": 780 + } + } + }, + "width": 2080, + "height": 1870, + "style": { + "width": 2080, + "height": 1870 + }, + "zIndex": -1 + }, + { + "id": "Event", + "type": "class", + "position": { + "x": 2240, + "y": 930 + }, + "selected": false, + "data": { + "label": "Event", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Event-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-16", + "name": "lastReviewedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Event-attr-17", + "name": "reviewDueAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": 930 + }, + "logical": { + "x": 2240, + "y": 930 + }, + "physical": { + "x": 2240, + "y": 930 + } + } + } + }, + { + "id": "Metric", + "type": "class", + "position": { + "x": 2720, + "y": 930 + }, + "selected": false, + "data": { + "label": "Metric", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Metric-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": 930 + }, + "logical": { + "x": 2720, + "y": 930 + }, + "physical": { + "x": 2720, + "y": 930 + } + } + } + }, + { + "id": "Observation", + "type": "class", + "position": { + "x": 3200, + "y": 930 + }, + "selected": false, + "data": { + "label": "Observation", + "logicalName": "", + "color": "#607d8b", + "attributes": [], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": 930 + }, + "logical": { + "x": 3200, + "y": 930 + }, + "physical": { + "x": 3200, + "y": 930 + } + } + } + }, + { + "id": "Dataset", + "type": "class", + "position": { + "x": 3680, + "y": 930 + }, + "selected": false, + "data": { + "label": "Dataset", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Dataset-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dataset-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": 930 + }, + "logical": { + "x": 3680, + "y": 930 + }, + "physical": { + "x": 3680, + "y": 930 + } + } + } + }, + { + "id": "Report", + "type": "class", + "position": { + "x": 2240, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Report", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Report-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Report-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Report-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": 1450 + }, + "logical": { + "x": 2240, + "y": 1450 + }, + "physical": { + "x": 2240, + "y": 1450 + } + } + } + }, + { + "id": "Dashboard", + "type": "class", + "position": { + "x": 2720, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Dashboard", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Dashboard-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Dashboard-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": 1450 + }, + "logical": { + "x": 2720, + "y": 1450 + }, + "physical": { + "x": 2720, + "y": 1450 + } + } + } + }, + { + "id": "Pipeline", + "type": "class", + "position": { + "x": 3200, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Pipeline", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Pipeline-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Pipeline-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": 1450 + }, + "logical": { + "x": 3200, + "y": 1450 + }, + "physical": { + "x": 3200, + "y": 1450 + } + } + } + }, + { + "id": "Transformation", + "type": "class", + "position": { + "x": 3680, + "y": 1450 + }, + "selected": false, + "data": { + "label": "Transformation", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Transformation-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Transformation-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": 1450 + }, + "logical": { + "x": 3680, + "y": 1450 + }, + "physical": { + "x": 3680, + "y": 1450 + } + } + } + }, + { + "id": "Experiment", + "type": "class", + "position": { + "x": 2240, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Experiment", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Experiment-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Experiment-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Experiment-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Experiment-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2240, + "y": 1970 + }, + "logical": { + "x": 2240, + "y": 1970 + }, + "physical": { + "x": 2240, + "y": 1970 + } + } + } + }, + { + "id": "Cohort", + "type": "class", + "position": { + "x": 2720, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Cohort", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Cohort-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-5", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-6", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-7", + "name": "referenceCode", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-8", + "name": "description", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-9", + "name": "revision", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-10", + "name": "sourceSystem", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-11", + "name": "retentionPolicy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-12", + "name": "classification", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-13", + "name": "verifiedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-14", + "name": "externalReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Cohort-attr-15", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2720, + "y": 1970 + }, + "logical": { + "x": 2720, + "y": 1970 + }, + "physical": { + "x": 2720, + "y": 1970 + } + } + } + }, + { + "id": "Attribution", + "type": "class", + "position": { + "x": 3200, + "y": 1970 + }, + "selected": false, + "data": { + "label": "Attribution", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "Attribution-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attribution-attr-1", + "name": "displayName", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attribution-attr-2", + "name": "status", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attribution-attr-3", + "name": "createdAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "Attribution-attr-4", + "name": "updatedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3200, + "y": 1970 + }, + "logical": { + "x": 3200, + "y": 1970 + }, + "physical": { + "x": 3200, + "y": 1970 + } + } + } + }, + { + "id": "QualityRule", + "type": "class", + "position": { + "x": 3680, + "y": 1970 + }, + "selected": false, + "data": { + "label": "QualityRuleWithJurisdictionAndEffectivePeriod", + "logicalName": "", + "color": "#607d8b", + "attributes": [ + { + "id": "QualityRule-attr-0", + "name": "identifier", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3680, + "y": 1970 + }, + "logical": { + "x": 3680, + "y": 1970 + }, + "physical": { + "x": 3680, + "y": 1970 + } + } + } + }, + { + "id": "note-0216", + "type": "note", + "position": { + "x": 2230, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Analytics: local smoke check", + "text": "Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2230, + "y": 2700 + }, + "logical": { + "x": 2230, + "y": 2700 + }, + "physical": { + "x": 2230, + "y": 2700 + } + } + } + }, + { + "id": "note-0217", + "type": "note", + "position": { + "x": 2620, + "y": 2700 + }, + "selected": false, + "data": { + "label": "Analytics: long note", + "text": "This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 2620, + "y": 2700 + }, + "logical": { + "x": 2620, + "y": 2700 + }, + "physical": { + "x": 2620, + "y": 2700 + } + } + } + }, + { + "id": "AssociationRecord1", + "type": "class", + "position": { + "x": -1140, + "y": -110 + }, + "selected": false, + "data": { + "label": "exercisesRole", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord1-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord1-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord1-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord1-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1140, + "y": -110 + }, + "logical": { + "x": -1140, + "y": -110 + }, + "physical": { + "x": -1140, + "y": -110 + } + } + } + }, + { + "id": "AssociationRecord2", + "type": "class", + "position": { + "x": 1140, + "y": -110 + }, + "selected": false, + "data": { + "label": "placesOrder", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord2-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord2-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord2-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord2-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": -110 + }, + "logical": { + "x": 1140, + "y": -110 + }, + "physical": { + "x": 1140, + "y": -110 + } + } + } + }, + { + "id": "AssociationRecord3", + "type": "class", + "position": { + "x": 3420, + "y": -110 + }, + "selected": false, + "data": { + "label": "transportedBy", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord3-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord3-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord3-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord3-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3420, + "y": -110 + }, + "logical": { + "x": 3420, + "y": -110 + }, + "physical": { + "x": 3420, + "y": -110 + } + } + } + }, + { + "id": "AssociationRecord4", + "type": "class", + "position": { + "x": -1140, + "y": 2470 + }, + "selected": false, + "data": { + "label": "assessedUnder", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord4-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord4-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord4-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord4-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -1140, + "y": 2470 + }, + "logical": { + "x": -1140, + "y": 2470 + }, + "physical": { + "x": -1140, + "y": 2470 + } + } + } + }, + { + "id": "AssociationRecord5", + "type": "class", + "position": { + "x": 1140, + "y": 2470 + }, + "selected": false, + "data": { + "label": "supportedBy", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord5-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord5-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord5-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord5-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 1140, + "y": 2470 + }, + "logical": { + "x": 1140, + "y": 2470 + }, + "physical": { + "x": 1140, + "y": 2470 + } + } + } + }, + { + "id": "AssociationRecord6", + "type": "class", + "position": { + "x": 3420, + "y": 2470 + }, + "selected": false, + "data": { + "label": "producedBy", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "AssociationRecord6-attr-0", + "name": "effectiveFrom", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord6-attr-1", + "name": "effectiveUntil", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord6-attr-2", + "name": "decisionReason", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "AssociationRecord6-attr-3", + "name": "evidenceReference", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 3420, + "y": 2470 + }, + "logical": { + "x": 3420, + "y": 2470 + }, + "physical": { + "x": 3420, + "y": 2470 + } + } + } + }, + { + "id": "DelegationEvidence", + "type": "class", + "position": { + "x": -2980, + "y": -1200 + }, + "selected": false, + "data": { + "label": "delegatesAuthorityWithinJurisdiction", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "DelegationEvidence-attr-0", + "name": "authorisedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "DelegationEvidence-attr-1", + "name": "expiresAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "DelegationEvidence-attr-2", + "name": "jurisdiction", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2980, + "y": -1200 + }, + "logical": { + "x": -2980, + "y": -1200 + }, + "physical": { + "x": -2980, + "y": -1200 + } + } + } + }, + { + "id": "PolicyLineageEvidence", + "type": "class", + "position": { + "x": -620, + "y": 1380 + }, + "selected": false, + "data": { + "label": "delegatesAuthorityWithinJurisdiction", + "logicalName": "", + "color": "#9c27b0", + "attributes": [ + { + "id": "PolicyLineageEvidence-attr-0", + "name": "signedBy", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + }, + { + "id": "PolicyLineageEvidence-attr-1", + "name": "signedAt", + "logicalName": "", + "type": "", + "typeParams": { + "maxLength": "", + "precision": "", + "scale": "", + "enumValues": "" + }, + "defaultValue": "", + "nullable": false, + "unique": false, + "autoIncrement": false, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + } + } + ], + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -620, + "y": 1380 + }, + "logical": { + "x": -620, + "y": 1380 + }, + "physical": { + "x": -620, + "y": 1380 + } + } + } + }, + { + "id": "area-0361", + "type": "area", + "position": { + "x": -2600, + "y": -550 + }, + "selected": false, + "data": { + "label": "Cross-border retention jurisdiction", + "color": "#94a3b8", + "viewSizes": { + "conceptual": { + "width": 6800, + "height": 520 + }, + "logical": { + "width": 6800, + "height": 520 + }, + "physical": { + "width": 6800, + "height": 520 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2600, + "y": -550 + }, + "logical": { + "x": -2600, + "y": -550 + }, + "physical": { + "x": -2600, + "y": -550 + } + } + }, + "width": 6800, + "height": 520, + "style": { + "width": 6800, + "height": 520 + }, + "zIndex": -1 + }, + { + "id": "area-0362", + "type": "area", + "position": { + "x": -2600, + "y": 290 + }, + "selected": false, + "data": { + "label": "Shared audit and reconciliation corridor", + "color": "#a855f7", + "viewSizes": { + "conceptual": { + "width": 6800, + "height": 350 + }, + "logical": { + "width": 6800, + "height": 350 + }, + "physical": { + "width": 6800, + "height": 350 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2600, + "y": 290 + }, + "logical": { + "x": -2600, + "y": 290 + }, + "physical": { + "x": -2600, + "y": 290 + } + } + }, + "width": 6800, + "height": 350, + "style": { + "width": 6800, + "height": 350 + }, + "zIndex": -1 + }, + { + "id": "area-0363", + "type": "area", + "position": { + "x": -2500, + "y": -300 + }, + "selected": false, + "data": { + "label": "Overlapping consent / legal-basis review", + "color": "#eab308", + "viewSizes": { + "conceptual": { + "width": 750, + "height": 1050 + }, + "logical": { + "width": 750, + "height": 1050 + }, + "physical": { + "width": 750, + "height": 1050 + } + }, + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -2500, + "y": -300 + }, + "logical": { + "x": -2500, + "y": -300 + }, + "physical": { + "x": -2500, + "y": -300 + } + } + }, + "width": 750, + "height": 1050, + "style": { + "width": 750, + "height": 1050 + }, + "zIndex": -1 + }, + { + "id": "note-0364", + "type": "note", + "position": { + "x": -3100, + "y": -2100 + }, + "selected": false, + "data": { + "label": "READABILITY FRONTIER — keep this difficult", + "text": "This is an end-goal fixture, not a claim of current visual correctness. Preserve all connections and complete labels. At useful local zoom, every line should be traceable and every annotation readable.\n\nPerson intentionally has EIGHT reflexive associations: this exceeds the current four-loop creation limit. Nested loop sizes are explicit. The file remains valid v2.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -3100, + "y": -2100 + }, + "logical": { + "x": -3100, + "y": -2100 + }, + "physical": { + "x": -3100, + "y": -2100 + } + } + } + }, + { + "id": "note-0365", + "type": "note", + "position": { + "x": 4200, + "y": -1750 + }, + "selected": false, + "data": { + "label": "Long-label acceptance target", + "text": "Do not pass by truncating names, hiding roles, removing multiplicities, dropping edges, shrinking text or deleting notes. Compare light and dark canvas; PNG exports currently use a light canvas.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 4200, + "y": -1750 + }, + "logical": { + "x": 4200, + "y": -1750 + }, + "physical": { + "x": 4200, + "y": -1750 + } + } + } + }, + { + "id": "note-0366", + "type": "note", + "position": { + "x": -3100, + "y": 3000 + }, + "selected": false, + "data": { + "label": "Negative-coordinate export", + "text": "Export the entire diagram including annotations, notes and areas. The notes and annotations outside the class envelope must remain present and unclipped.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": -3100, + "y": 3000 + }, + "logical": { + "x": -3100, + "y": 3000 + }, + "physical": { + "x": -3100, + "y": 3000 + } + } + } + }, + { + "id": "note-0367", + "type": "note", + "position": { + "x": 4200, + "y": 3100 + }, + "selected": false, + "data": { + "label": "Manual and transient smoke tests", + "text": "Edit one manual route; undo once. Draw and erase one stroke; undo once. Use the laser, save and reopen: laser trails must never be saved. The fixture deliberately contains no persistent laser stroke.", + "visibility": { + "conceptual": true, + "logical": false, + "physical": false + }, + "viewPositions": { + "conceptual": { + "x": 4200, + "y": 3100 + }, + "logical": { + "x": 4200, + "y": 3100 + }, + "physical": { + "x": 4200, + "y": 3100 + } + } + } + } + ], + "edges": [ + { + "id": "edge-0002", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 12 + } + }, + { + "id": "edge-0003", + "source": "Person", + "target": "Role", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 3 + } + }, + { + "id": "edge-0004", + "source": "Organisation", + "target": "Account", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0005", + "source": "Organisation", + "target": "Permission", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0006", + "source": "Account", + "target": "Membership", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0007", + "source": "Account", + "target": "Credential", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0008", + "source": "Account", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0009", + "source": "Membership", + "target": "Role", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0010", + "source": "Membership", + "target": "Consent", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0011", + "source": "Role", + "target": "Permission", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0012", + "source": "Role", + "target": "Address", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0013", + "source": "Role", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 3 + } + }, + { + "id": "edge-0014", + "source": "Permission", + "target": "Credential", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0015", + "source": "Permission", + "target": "ContactPoint", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0016", + "source": "Credential", + "target": "Consent", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0017", + "source": "Credential", + "target": "Device", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0018", + "source": "Credential", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0019", + "source": "Consent", + "target": "Address", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0020", + "source": "Consent", + "target": "Session", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0021", + "source": "Address", + "target": "ContactPoint", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0022", + "source": "Address", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0023", + "source": "Address", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0024", + "source": "ContactPoint", + "target": "Device", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0025", + "source": "ContactPoint", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0026", + "source": "Device", + "target": "Session", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0027", + "source": "Device", + "target": "Account", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0028", + "source": "Device", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0029", + "source": "Session", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0030", + "source": "Session", + "target": "Membership", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0039", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0040", + "source": "Customer", + "target": "Catalogue", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0041", + "source": "Order", + "target": "OrderLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0042", + "source": "Order", + "target": "Price", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0043", + "source": "OrderLine", + "target": "Product", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0044", + "source": "OrderLine", + "target": "Promotion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0045", + "source": "OrderLine", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0046", + "source": "Product", + "target": "Catalogue", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0047", + "source": "Product", + "target": "Basket", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0048", + "source": "Catalogue", + "target": "Price", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0049", + "source": "Catalogue", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0050", + "source": "Catalogue", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0051", + "source": "Price", + "target": "Promotion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0052", + "source": "Price", + "target": "Subscription", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0053", + "source": "Promotion", + "target": "Basket", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0054", + "source": "Promotion", + "target": "Channel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0055", + "source": "Promotion", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0056", + "source": "Basket", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0057", + "source": "Basket", + "target": "Offer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0058", + "source": "Reservation", + "target": "Subscription", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0059", + "source": "Reservation", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 8 + } + }, + { + "id": "edge-0060", + "source": "Reservation", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 8 + } + }, + { + "id": "edge-0061", + "source": "Subscription", + "target": "Channel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0062", + "source": "Subscription", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0063", + "source": "Channel", + "target": "Offer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0064", + "source": "Channel", + "target": "OrderLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0065", + "source": "Channel", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0066", + "source": "Offer", + "target": "Customer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0067", + "source": "Offer", + "target": "Product", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0076", + "source": "Warehouse", + "target": "Inventory", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0077", + "source": "Warehouse", + "target": "Parcel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0078", + "source": "Inventory", + "target": "StockMovement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0079", + "source": "Inventory", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0080", + "source": "StockMovement", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0081", + "source": "StockMovement", + "target": "Delivery", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0082", + "source": "StockMovement", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0083", + "source": "Shipment", + "target": "Parcel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0084", + "source": "Shipment", + "target": "Route", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0085", + "source": "Parcel", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0086", + "source": "Parcel", + "target": "Location", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0087", + "source": "Parcel", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0088", + "source": "Carrier", + "target": "Delivery", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0089", + "source": "Carrier", + "target": "Return", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0090", + "source": "Delivery", + "target": "Route", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0091", + "source": "Delivery", + "target": "Inspection", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0092", + "source": "Delivery", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0093", + "source": "Route", + "target": "Location", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0094", + "source": "Route", + "target": "HandlingUnit", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0095", + "source": "Location", + "target": "Return", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0096", + "source": "Location", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0097", + "source": "Location", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0098", + "source": "Return", + "target": "Inspection", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0099", + "source": "Return", + "target": "Inventory", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0100", + "source": "Inspection", + "target": "HandlingUnit", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0101", + "source": "Inspection", + "target": "StockMovement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0102", + "source": "Inspection", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0103", + "source": "HandlingUnit", + "target": "Warehouse", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0104", + "source": "HandlingUnit", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0113", + "source": "Invoice", + "target": "InvoiceLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0114", + "source": "Invoice", + "target": "Ledger", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0115", + "source": "InvoiceLine", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0116", + "source": "InvoiceLine", + "target": "LedgerEntry", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0117", + "source": "Payment", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0118", + "source": "Payment", + "target": "TaxRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0119", + "source": "Payment", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 5 + } + }, + { + "id": "edge-0120", + "source": "Refund", + "target": "Ledger", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0121", + "source": "Refund", + "target": "Currency", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0122", + "source": "Ledger", + "target": "LedgerEntry", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0123", + "source": "Ledger", + "target": "Settlement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0124", + "source": "Ledger", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0125", + "source": "LedgerEntry", + "target": "TaxRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0126", + "source": "LedgerEntry", + "target": "Payout", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0127", + "source": "TaxRule", + "target": "Currency", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0128", + "source": "TaxRule", + "target": "Dispute", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0129", + "source": "TaxRule", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0130", + "source": "Currency", + "target": "Settlement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0131", + "source": "Currency", + "target": "ExchangeRate", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0132", + "source": "Settlement", + "target": "Payout", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0133", + "source": "Settlement", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0134", + "source": "Settlement", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0135", + "source": "Payout", + "target": "Dispute", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0136", + "source": "Payout", + "target": "InvoiceLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0137", + "source": "Dispute", + "target": "ExchangeRate", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0138", + "source": "Dispute", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0139", + "source": "Dispute", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0140", + "source": "ExchangeRate", + "target": "Invoice", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0141", + "source": "ExchangeRate", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0150", + "source": "Policy", + "target": "PolicyVersion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0151", + "source": "Policy", + "target": "Case", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0152", + "source": "PolicyVersion", + "target": "RiskAssessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0153", + "source": "PolicyVersion", + "target": "Evidence", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0154", + "source": "RiskAssessment", + "target": "Approval", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0155", + "source": "RiskAssessment", + "target": "AuditEvent", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0156", + "source": "RiskAssessment", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0157", + "source": "Approval", + "target": "Case", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0158", + "source": "Approval", + "target": "RetentionRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0159", + "source": "Case", + "target": "Evidence", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 3 + } + }, + { + "id": "edge-0160", + "source": "Case", + "target": "Jurisdiction", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0161", + "source": "Case", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0162", + "source": "Evidence", + "target": "AuditEvent", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0163", + "source": "Evidence", + "target": "LegalBasis", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0164", + "source": "AuditEvent", + "target": "RetentionRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0165", + "source": "AuditEvent", + "target": "Control", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0166", + "source": "AuditEvent", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0167", + "source": "RetentionRule", + "target": "Jurisdiction", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0168", + "source": "RetentionRule", + "target": "Exception", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0169", + "source": "Jurisdiction", + "target": "LegalBasis", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0170", + "source": "Jurisdiction", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0171", + "source": "Jurisdiction", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0172", + "source": "LegalBasis", + "target": "Control", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0173", + "source": "LegalBasis", + "target": "PolicyVersion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0174", + "source": "Control", + "target": "Exception", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0175", + "source": "Control", + "target": "RiskAssessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0176", + "source": "Control", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0177", + "source": "Exception", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0178", + "source": "Exception", + "target": "Approval", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0187", + "source": "Event", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0188", + "source": "Event", + "target": "Report", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0189", + "source": "Metric", + "target": "Observation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0190", + "source": "Metric", + "target": "Dashboard", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0191", + "source": "Observation", + "target": "Dataset", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0192", + "source": "Observation", + "target": "Pipeline", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0193", + "source": "Observation", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0194", + "source": "Dataset", + "target": "Report", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0195", + "source": "Dataset", + "target": "Transformation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0196", + "source": "Report", + "target": "Dashboard", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0197", + "source": "Report", + "target": "Experiment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0198", + "source": "Report", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0199", + "source": "Dashboard", + "target": "Pipeline", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0200", + "source": "Dashboard", + "target": "Cohort", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0201", + "source": "Pipeline", + "target": "Transformation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "owns", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0202", + "source": "Pipeline", + "target": "Attribution", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "1..*", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0203", + "source": "Pipeline", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0204", + "source": "Transformation", + "target": "Experiment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "governs", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0205", + "source": "Transformation", + "target": "QualityRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0206", + "source": "Experiment", + "target": "Cohort", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "records", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0207", + "source": "Experiment", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0208", + "source": "Experiment", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0209", + "source": "Cohort", + "target": "Attribution", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "requires", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0210", + "source": "Cohort", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isApplicableWithinEffectivePeriod", + "type": "association", + "roleA": "authorisedPartyAtTimeOfDecision", + "roleB": "recordsApplicableInThisJurisdiction", + "multiplicityA": "0..1", + "multiplicityB": "1..1", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0211", + "source": "Attribution", + "target": "QualityRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supersedes", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0212", + "source": "Attribution", + "target": "Observation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "1..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0213", + "source": "Attribution", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reportsTo", + "type": "association", + "roleA": "reportingRecord", + "roleB": "domainOwner", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0214", + "source": "QualityRule", + "target": "Event", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "validates", + "type": "association", + "roleA": "responsibleParty", + "roleB": "applicableRecords", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0215", + "source": "QualityRule", + "target": "Dataset", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "references", + "type": "association", + "roleA": "origin", + "roleB": "references", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0223", + "source": "Person", + "target": "Product", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0224", + "source": "Organisation", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0225", + "source": "Account", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0226", + "source": "Membership", + "target": "Promotion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0227", + "source": "Role", + "target": "Offer", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0228", + "source": "Permission", + "target": "Catalogue", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0229", + "source": "Credential", + "target": "Subscription", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0230", + "source": "Consent", + "target": "OrderLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": -260, + "y": -1300 + }, + { + "x": -260, + "y": 220 + }, + { + "x": 780, + "y": 220 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0231", + "source": "Customer", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0232", + "source": "Order", + "target": "Location", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0233", + "source": "OrderLine", + "target": "Inventory", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0234", + "source": "Product", + "target": "Delivery", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0235", + "source": "Catalogue", + "target": "HandlingUnit", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0236", + "source": "Price", + "target": "Parcel", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0237", + "source": "Promotion", + "target": "Return", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0238", + "source": "Basket", + "target": "StockMovement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": 2020, + "y": -1300 + }, + { + "x": 2020, + "y": 220 + }, + { + "x": 3060, + "y": 220 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0239", + "source": "Warehouse", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0240", + "source": "Inventory", + "target": "Settlement", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0241", + "source": "StockMovement", + "target": "InvoiceLine", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0242", + "source": "Shipment", + "target": "TaxRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0243", + "source": "Parcel", + "target": "ExchangeRate", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0244", + "source": "Carrier", + "target": "Ledger", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0245", + "source": "Delivery", + "target": "Payout", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0246", + "source": "Route", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": 4300, + "y": -1300 + }, + { + "x": 4300, + "y": 2800 + }, + { + "x": -1500, + "y": 2800 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0247", + "source": "Invoice", + "target": "Approval", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0248", + "source": "InvoiceLine", + "target": "Jurisdiction", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0249", + "source": "Payment", + "target": "PolicyVersion", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0250", + "source": "Refund", + "target": "AuditEvent", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0251", + "source": "Ledger", + "target": "Exception", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0252", + "source": "LedgerEntry", + "target": "Case", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0253", + "source": "TaxRule", + "target": "LegalBasis", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0254", + "source": "Currency", + "target": "RiskAssessment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": -260, + "y": 1280 + }, + { + "x": -260, + "y": 2800 + }, + { + "x": 780, + "y": 2800 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0255", + "source": "Policy", + "target": "Dataset", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0256", + "source": "PolicyVersion", + "target": "Experiment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0257", + "source": "RiskAssessment", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0258", + "source": "Approval", + "target": "Pipeline", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0259", + "source": "Case", + "target": "QualityRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0260", + "source": "Evidence", + "target": "Report", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0261", + "source": "AuditEvent", + "target": "Cohort", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0262", + "source": "RetentionRule", + "target": "Observation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": 2020, + "y": 1280 + }, + { + "x": 2020, + "y": 2800 + }, + { + "x": 3060, + "y": 2800 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0263", + "source": "Event", + "target": "Membership", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0264", + "source": "Metric", + "target": "Address", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0265", + "source": "Observation", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0266", + "source": "Dataset", + "target": "Credential", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0267", + "source": "Report", + "target": "Session", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0268", + "source": "Dashboard", + "target": "Role", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0269", + "source": "Pipeline", + "target": "ContactPoint", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAuthorisedByPolicyVersion", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0270", + "source": "Transformation", + "target": "Account", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isReconciledAgainst", + "type": "association", + "roleA": "requestingDomainRecord", + "roleB": "crossDomainReference", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "manual", + "controlPoints": [ + { + "x": 4300, + "y": 1280 + }, + { + "x": 4300, + "y": 220 + }, + { + "x": -1500, + "y": 220 + } + ], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0271", + "source": "Organisation", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 12 + } + }, + { + "id": "edge-0272", + "source": "Consent", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0273", + "source": "OrderLine", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0274", + "source": "Subscription", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0275", + "source": "Parcel", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0276", + "source": "HandlingUnit", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0277", + "source": "TaxRule", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0278", + "source": "PolicyVersion", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0279", + "source": "Jurisdiction", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0280", + "source": "Dataset", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0281", + "source": "Attribution", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0282", + "source": "Permission", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0283", + "source": "Customer", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0284", + "source": "Basket", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0285", + "source": "StockMovement", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0286", + "source": "Return", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0287", + "source": "Ledger", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0288", + "source": "ExchangeRate", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0289", + "source": "AuditEvent", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0290", + "source": "Metric", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0291", + "source": "Experiment", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "dataSubjectRepresentedByAuthorisedDelegate", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0292", + "source": "Membership", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableForCrossBorderDataProcessing", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 2 + } + }, + { + "id": "edge-0293", + "source": "Device", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0294", + "source": "Price", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isAccountableFor", + "type": "association", + "roleA": "subject", + "roleB": "accountablePerson", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0295", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "belongsTo", + "type": "association", + "roleA": "personInCapacity1", + "roleB": "organisationInCapacity1", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 12 + } + }, + { + "id": "edge-0296", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "worksFor", + "type": "association", + "roleA": "personInCapacity2", + "roleB": "organisationInCapacity2", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 3, + "parallelCount": 12 + } + }, + { + "id": "edge-0297", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "represents", + "type": "association", + "roleA": "personInCapacity3", + "roleB": "organisationInCapacity3", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 4, + "parallelCount": 12 + } + }, + { + "id": "edge-0298", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsSharesIn", + "type": "association", + "roleA": "personInCapacity4", + "roleB": "organisationInCapacity4", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 5, + "parallelCount": 12 + } + }, + { + "id": "edge-0299", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "audits", + "type": "association", + "roleA": "personInCapacity5", + "roleB": "organisationInCapacity5", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 6, + "parallelCount": 12 + } + }, + { + "id": "edge-0300", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "approves", + "type": "association", + "roleA": "personInCapacity6", + "roleB": "organisationInCapacity6", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 7, + "parallelCount": 12 + } + }, + { + "id": "edge-0301", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityTo", + "type": "association", + "roleA": "personInCapacity7", + "roleB": "organisationInCapacity7", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 8, + "parallelCount": 12 + } + }, + { + "id": "edge-0302", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "receivesNotificationsFrom", + "type": "association", + "roleA": "personInCapacity8", + "roleB": "organisationInCapacity8", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 9, + "parallelCount": 12 + } + }, + { + "id": "edge-0303", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isLegallyResponsibleFor", + "type": "association", + "roleA": "personInCapacity9", + "roleB": "organisationInCapacity9", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 10, + "parallelCount": 12 + } + }, + { + "id": "edge-0304", + "source": "Person", + "target": "Organisation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "actsAsBeneficialOwnerOf", + "type": "association", + "roleA": "personInCapacity10", + "roleB": "organisationInCapacity10", + "multiplicityA": "0..*", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 11, + "parallelCount": 12 + } + }, + { + "id": "edge-0305", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy1", + "type": "association", + "roleA": "customerRole1", + "roleB": "reservationRole1", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 8 + } + }, + { + "id": "edge-0306", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy2", + "type": "association", + "roleA": "customerRole2", + "roleB": "reservationRole2", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 3, + "parallelCount": 8 + } + }, + { + "id": "edge-0307", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy3", + "type": "association", + "roleA": "customerRole3", + "roleB": "reservationRole3", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 4, + "parallelCount": 8 + } + }, + { + "id": "edge-0308", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy4", + "type": "association", + "roleA": "customerRole4", + "roleB": "reservationRole4", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 5, + "parallelCount": 8 + } + }, + { + "id": "edge-0309", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy5", + "type": "association", + "roleA": "customerRole5", + "roleB": "reservationRole5", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 6, + "parallelCount": 8 + } + }, + { + "id": "edge-0310", + "source": "Customer", + "target": "Reservation", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "reservationPolicy6", + "type": "association", + "roleA": "customerRole6", + "roleB": "reservationRole6", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 7, + "parallelCount": 8 + } + }, + { + "id": "edge-0311", + "source": "Invoice", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "settlementStage1", + "type": "association", + "roleA": "invoice", + "roleB": "payments", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 5 + } + }, + { + "id": "edge-0312", + "source": "Invoice", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "settlementStage2", + "type": "association", + "roleA": "invoice", + "roleB": "payments", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 5 + } + }, + { + "id": "edge-0313", + "source": "Invoice", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "settlementStage3", + "type": "association", + "roleA": "invoice", + "roleB": "payments", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "straight", + "controlPoints": [], + "parallelIndex": 3, + "parallelCount": 5 + } + }, + { + "id": "edge-0314", + "source": "Invoice", + "target": "Payment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "settlementStage4", + "type": "association", + "roleA": "invoice", + "roleB": "payments", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 4, + "parallelCount": 5 + } + }, + { + "id": "edge-0315", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 8, + "reflexiveSide": "left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0316", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isSupersededByApprovedRevision", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 8, + "reflexiveSide": "right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0317", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isDerivedFromAuditedSource", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 8, + "reflexiveSide": "lower-right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0318", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isTemporarilySubstitutedBy", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 8, + "reflexiveSide": "lower-left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0319", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdictionDuringExceptionalCircumstances", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 4, + "reflexiveCount": 8, + "reflexiveSide": "left", + "loopWidth": 340, + "loopHeight": 350 + } + }, + { + "id": "edge-0320", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isSupersededByApprovedRevisionDuringExceptionalCircumstances", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 5, + "reflexiveCount": 8, + "reflexiveSide": "right", + "loopWidth": 340, + "loopHeight": 350 + } + }, + { + "id": "edge-0321", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isDerivedFromAuditedSourceDuringExceptionalCircumstances", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 6, + "reflexiveCount": 8, + "reflexiveSide": "lower-right", + "loopWidth": 340, + "loopHeight": 350 + } + }, + { + "id": "edge-0322", + "source": "Person", + "target": "Person", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isTemporarilySubstitutedByDuringExceptionalCircumstances", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 7, + "reflexiveCount": 8, + "reflexiveSide": "lower-left", + "loopWidth": 340, + "loopHeight": 350 + } + }, + { + "id": "edge-0323", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0324", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isSupersededByApprovedRevision", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0325", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isDerivedFromAuditedSource", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0326", + "source": "Order", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isTemporarilySubstitutedBy", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0327", + "source": "Policy", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0328", + "source": "Policy", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isSupersededByApprovedRevision", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0329", + "source": "Policy", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isDerivedFromAuditedSource", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0330", + "source": "Policy", + "target": "Policy", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isTemporarilySubstitutedBy", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0331", + "source": "Metric", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 0, + "reflexiveCount": 4, + "reflexiveSide": "left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0332", + "source": "Metric", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isSupersededByApprovedRevision", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 1, + "reflexiveCount": 4, + "reflexiveSide": "right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0333", + "source": "Metric", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isDerivedFromAuditedSource", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 2, + "reflexiveCount": 4, + "reflexiveSide": "lower-right", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0334", + "source": "Metric", + "target": "Metric", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "reflexiveAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "isTemporarilySubstitutedBy", + "type": "association", + "roleA": "previouslyAuthorisedResponsibleParty", + "roleB": "subsequentlyDelegatedResponsibleParty", + "multiplicityA": "0..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "reflexiveIndex": 3, + "reflexiveCount": 4, + "reflexiveSide": "lower-left", + "loopWidth": 190, + "loopHeight": 210 + } + }, + { + "id": "edge-0335", + "source": "Person", + "target": "Membership", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0336", + "source": "Role", + "target": "Permission", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0337", + "source": "Customer", + "target": "Product", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0338", + "source": "Catalogue", + "target": "Price", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0339", + "source": "Warehouse", + "target": "Shipment", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0340", + "source": "Parcel", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0341", + "source": "Invoice", + "target": "Refund", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0342", + "source": "Ledger", + "target": "LedgerEntry", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0343", + "source": "Policy", + "target": "Approval", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0344", + "source": "Case", + "target": "Evidence", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 3 + } + }, + { + "id": "edge-0345", + "source": "Event", + "target": "Dataset", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "ownsLifecycleOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "edge-0346", + "source": "Report", + "target": "Dashboard", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "composition", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "containsVersionOf", + "type": "composition", + "roleA": "owner", + "roleB": "member", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "edge-0347", + "source": "Person", + "target": "Role", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "exercisesRole", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 3 + } + }, + { + "id": "associative-0348", + "source": "AssociationRecord1", + "target": "assoc-edge-edge-0347", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "exercisesRole", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0349", + "source": "Customer", + "target": "Order", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "placesOrder", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "associative-0350", + "source": "AssociationRecord2", + "target": "assoc-edge-edge-0349", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "placesOrder", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0351", + "source": "Shipment", + "target": "Carrier", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "transportedBy", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "associative-0352", + "source": "AssociationRecord3", + "target": "assoc-edge-edge-0351", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "transportedBy", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0353", + "source": "Invoice", + "target": "TaxRule", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "assessedUnder", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 1, + "parallelCount": 2 + } + }, + { + "id": "associative-0354", + "source": "AssociationRecord4", + "target": "assoc-edge-edge-0353", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "assessedUnder", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0355", + "source": "Case", + "target": "Evidence", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supportedBy", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 2, + "parallelCount": 3 + } + }, + { + "id": "associative-0356", + "source": "AssociationRecord5", + "target": "assoc-edge-edge-0355", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "supportedBy", + "type": "associative", + "autoName": true + } + }, + { + "id": "edge-0357", + "source": "Dataset", + "target": "Pipeline", + "sourceHandle": "right-source", + "targetHandle": "left-target", + "type": "association", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "producedBy", + "type": "association", + "roleA": "subject", + "roleB": "governingRecord", + "multiplicityA": "1..1", + "multiplicityB": "0..*", + "lineStyle": "orthogonal", + "controlPoints": [], + "parallelIndex": 0, + "parallelCount": 1 + } + }, + { + "id": "associative-0358", + "source": "AssociationRecord6", + "target": "assoc-edge-edge-0357", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "producedBy", + "type": "associative", + "autoName": true + } + }, + { + "id": "associative-0359", + "source": "DelegationEvidence", + "target": "assoc-edge-edge-0315", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "associative", + "autoName": true + } + }, + { + "id": "associative-0360", + "source": "PolicyLineageEvidence", + "target": "assoc-edge-edge-0327", + "sourceHandle": "top-source", + "targetHandle": "association-target", + "type": "associativeAssociation", + "selected": false, + "interactionWidth": 20, + "data": { + "name": "delegatesAuthorityWithinJurisdiction", + "type": "associative", + "autoName": true + } + } + ], + "annotations": { + "conceptual": { + "items": [ + { + "id": "text-0033", + "kind": "text", + "x": -2330, + "y": -1885, + "text": "1 / IDENTITY — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0034", + "kind": "shape", + "shape": "rectangle", + "x1": -2370, + "y1": -1710, + "x2": -1950, + "y2": -1180, + "color": "#009688", + "thickness": 1 + }, + { + "id": "arrow-0035", + "kind": "shape", + "shape": "arrow", + "x1": -1140, + "y1": 100, + "x2": -1150, + "y2": -180, + "color": "#009688", + "thickness": 2 + }, + { + "id": "stroke-0036", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": -2340, + "y": -1835 + }, + { + "x": -1980, + "y": -1820 + }, + { + "x": -1600, + "y": -1830 + }, + { + "x": -1160, + "y": -1815 + } + ], + "color": "#009688", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0037", + "kind": "text", + "x": -1400, + "y": 170, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0070", + "kind": "text", + "x": -50, + "y": -1885, + "text": "2 / COMMERCE — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0071", + "kind": "shape", + "shape": "rectangle", + "x1": -90, + "y1": -1710, + "x2": 330, + "y2": -1180, + "color": "#2196f3", + "thickness": 1 + }, + { + "id": "arrow-0072", + "kind": "shape", + "shape": "arrow", + "x1": 1140, + "y1": 100, + "x2": 1130, + "y2": -180, + "color": "#2196f3", + "thickness": 2 + }, + { + "id": "stroke-0073", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": -60, + "y": -1835 + }, + { + "x": 300, + "y": -1820 + }, + { + "x": 680, + "y": -1830 + }, + { + "x": 1120, + "y": -1815 + } + ], + "color": "#2196f3", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0074", + "kind": "text", + "x": 880, + "y": 170, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0107", + "kind": "text", + "x": 2230, + "y": -1885, + "text": "3 / FULFILMENT — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0108", + "kind": "shape", + "shape": "rectangle", + "x1": 2190, + "y1": -1710, + "x2": 2610, + "y2": -1180, + "color": "#ffc107", + "thickness": 1 + }, + { + "id": "arrow-0109", + "kind": "shape", + "shape": "arrow", + "x1": 3420, + "y1": 100, + "x2": 3410, + "y2": -180, + "color": "#ffc107", + "thickness": 2 + }, + { + "id": "stroke-0110", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": 2220, + "y": -1835 + }, + { + "x": 2580, + "y": -1820 + }, + { + "x": 2960, + "y": -1830 + }, + { + "x": 3400, + "y": -1815 + } + ], + "color": "#ffc107", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0111", + "kind": "text", + "x": 3160, + "y": 170, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0144", + "kind": "text", + "x": -2330, + "y": 695, + "text": "4 / FINANCE — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0145", + "kind": "shape", + "shape": "rectangle", + "x1": -2370, + "y1": 870, + "x2": -1950, + "y2": 1400, + "color": "#9c27b0", + "thickness": 1 + }, + { + "id": "arrow-0146", + "kind": "shape", + "shape": "arrow", + "x1": -1140, + "y1": 2680, + "x2": -1150, + "y2": 2400, + "color": "#9c27b0", + "thickness": 2 + }, + { + "id": "stroke-0147", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": -2340, + "y": 745 + }, + { + "x": -1980, + "y": 760 + }, + { + "x": -1600, + "y": 750 + }, + { + "x": -1160, + "y": 765 + } + ], + "color": "#9c27b0", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0148", + "kind": "text", + "x": -1400, + "y": 2750, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0181", + "kind": "text", + "x": -50, + "y": 695, + "text": "5 / TRUST — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0182", + "kind": "shape", + "shape": "rectangle", + "x1": -90, + "y1": 870, + "x2": 330, + "y2": 1400, + "color": "#ff5722", + "thickness": 1 + }, + { + "id": "arrow-0183", + "kind": "shape", + "shape": "arrow", + "x1": 1140, + "y1": 2680, + "x2": 1130, + "y2": 2400, + "color": "#ff5722", + "thickness": 2 + }, + { + "id": "stroke-0184", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": -60, + "y": 745 + }, + { + "x": 300, + "y": 760 + }, + { + "x": 680, + "y": 750 + }, + { + "x": 1120, + "y": 765 + } + ], + "color": "#ff5722", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0185", + "kind": "text", + "x": 880, + "y": 2750, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0218", + "kind": "text", + "x": 2230, + "y": 695, + "text": "6 / ANALYTICS — readability target", + "color": "#334155", + "fontSize": 30 + }, + { + "id": "rectangle-0219", + "kind": "shape", + "shape": "rectangle", + "x1": 2190, + "y1": 870, + "x2": 2610, + "y2": 1400, + "color": "#607d8b", + "thickness": 1 + }, + { + "id": "arrow-0220", + "kind": "shape", + "shape": "arrow", + "x1": 3420, + "y1": 2680, + "x2": 3410, + "y2": 2400, + "color": "#607d8b", + "thickness": 2 + }, + { + "id": "stroke-0221", + "kind": "stroke", + "tool": "marker", + "points": [ + { + "x": 2220, + "y": 745 + }, + { + "x": 2580, + "y": 760 + }, + { + "x": 2960, + "y": 750 + }, + { + "x": 3400, + "y": 765 + } + ], + "color": "#607d8b", + "thickness": 28, + "opacity": 0.18 + }, + { + "id": "text-0222", + "kind": "text", + "x": 3160, + "y": 2750, + "text": "Zoom in to assess labels; fit view is for navigation.", + "color": "#334155", + "fontSize": 18, + "width": 420, + "padding": 10, + "background": "#f8fafc", + "border": true + }, + { + "id": "text-0368", + "kind": "text", + "x": -2400, + "y": -2140, + "text": "05 / GLOBAL PLATFORM — ASPIRATIONAL READABILITY TARGET", + "color": "#334155", + "fontSize": 38 + }, + { + "id": "text-0369", + "kind": "text", + "x": 4200, + "y": -1100, + "text": "Long text: authorisation across multiple jurisdictions\nÉchéance / Gültigkeit / 有効期間\nKeep full text legible at a useful local zoom.", + "color": "#334155", + "fontSize": 20, + "width": 430, + "padding": 16, + "background": "#fef3c7", + "border": true + }, + { + "id": "ellipse-0370", + "kind": "shape", + "shape": "ellipse", + "x1": -2850, + "y1": -2050, + "x2": -1900, + "y2": -1100, + "color": "#ef4444", + "thickness": 3 + }, + { + "id": "line-0371", + "kind": "shape", + "shape": "line", + "x1": -2700, + "y1": 500, + "x2": 4240, + "y2": 500, + "color": "#64748b", + "thickness": 1 + }, + { + "id": "arrow-0372", + "kind": "shape", + "shape": "arrow", + "x1": 4300, + "y1": -600, + "x2": 3750, + "y2": -280, + "color": "#dc2626", + "thickness": 4 + }, + { + "id": "stroke-0373", + "kind": "stroke", + "tool": "pen", + "points": [ + { + "x": -2750, + "y": 400 + }, + { + "x": -2000, + "y": 280 + }, + { + "x": -800, + "y": 430 + }, + { + "x": 400, + "y": 260 + }, + { + "x": 1700, + "y": 400 + }, + { + "x": 2900, + "y": 280 + }, + { + "x": 4200, + "y": 430 + } + ], + "color": "#ef4444", + "thickness": 3, + "opacity": 1 + }, + { + "id": "stroke-0374", + "kind": "stroke", + "tool": "pen", + "points": [ + { + "x": -2340, + "y": -1600 + }, + { + "x": -2200, + "y": -1590 + }, + { + "x": -2080, + "y": -1580 + } + ], + "color": "#ffffff", + "thickness": 4, + "opacity": 1 + }, + { + "id": "stroke-0375", + "kind": "stroke", + "tool": "pen", + "points": [ + { + "x": 4200, + "y": 2700 + }, + { + "x": 4270, + "y": 2630 + }, + { + "x": 4320, + "y": 2720 + }, + { + "x": 4410, + "y": 2610 + } + ], + "color": "#2563eb", + "thickness": 2, + "linear": true, + "opacity": 1 + } + ] + }, + "logical": { + "items": [] + }, + "physical": { + "items": [] + } + } +} diff --git a/examples/README.txt b/examples/README.txt new file mode 100644 index 0000000..00b79ed --- /dev/null +++ b/examples/README.txt @@ -0,0 +1,111 @@ +CONCEPTUAL SMOKE MODELS + +Open the .mdlz files with File > Open. These are ordinary version-2 Modelizer +files, not imports or screenshots. Only conceptual visibility is enabled. +Show notes, areas and annotations through View; enable composite aggregation +through Preferences > Enable composite aggregation, or accept the opening prompt. +These preferences belong to the application, not the +model file. Test with the operations compartment both on and off. + +01-library-basics.mdlz + 4 classes / 3 connections. Establish a clean baseline: class titles, + attributes, names, roles, multiplicities and horizontal/vertical routing. + +02-dispatch-border-spacing.mdlz + 10 classes / 10 connections. DispatchCentre has neighbours on all four sides, + including a parallel pair and classes with no attributes. Move the hub far + right and back; move it vertically too. On a fixed border, connection order + and separation should stay stable as distance changes. Move a neighbour past + another and verify that the endpoint order follows their new positions. + +03-university-enrolment.mdlz + 18 classes / 26 connections. Parallel enrolment links, four reflexive corners + on Person, an association class, composition, three domains, notes and all + four annotation shapes. Move Student/Course: the dashed association-class + connector must meet the base line. Resize a reflexive loop and undo once. + +04-commerce-operations.mdlz + 32 classes / 64 connections. Five parallel lanes including composition, eight reflexive loops, + three association classes, manual routes, straight routes and overlapping + areas. Check crowded borders, long paths through other domains, route edits, + and selection/focus when switching between classes and associations. + +05-global-platform-frontier.mdlz + 80 classes / 312 connections / 16 notes / 9 areas / 38 annotations. + A deliberately difficult END-GOAL fixture, not a current visual pass. + + Six domains, high-degree hubs, large parallel groups, long names and roles, + minimum-height and attribute-heavy classes, all four reflexive corners, + nested loops, compositions, association classes attached to ordinary and + reflexive associations, straight/manual/orthogonal mixtures, negative + coordinates, overlapping areas, pale marks, pen/marker strokes, text boxes, + Unicode, arrows, lines, rectangles and ellipses. + + Person intentionally has EIGHT reflexive associations, exceeding the current + four-loop creation limit. The v2 loader retains them. This fixture must not + be simplified merely to make the current renderer look successful. + + Inspect Identity's Person/Organisation group, Commerce's Customer/Reservation + group, Finance's Invoice/Payment group, and the central cross-domain audit + corridor first. The local notes and annotations identify review targets. + The whole diagram is large: fit view is for navigation; judge text at a useful + local zoom (for example 100%). Requiring every label to be readable on one + fitted laptop screen is not the acceptance criterion. + +REPEATABLE PASS + +1. Open each file. Check that the class/edge/annotation counts match manifest.json + and that opening alone does not mark it dirty. No missing-edge errors. +2. Pan/zoom and use keyboard focus. At 100%, inspect complete association names, + both roles and both multiplicities, not just the lines. Try light and dark. +3. Drag classes farther apart while keeping the attachment side unchanged. + Check stable endpoint ordering and spacing on all four borders. Add/remove + attributes, then undo; endpoints must stay on the current class boundary. +4. Select an association, edit a manual route, resize a loop and undo each + completed gesture once. Dashed attachment points must follow their base path. +5. Toggle notes/areas/annotations and the composite aggregation feature. Content + must return intact. Annotations must align during zoom and pan. +6. Edit text and erase a pen stroke; undo. Use the laser, save and reopen: laser + trails must never persist. No laser data is deliberately stored in fixtures. +7. Export PNG at both resolutions with notes, areas and annotations included, + even after hiding them on the canvas. Inspect negative-coordinate content, + outer labels, arrowheads, pale marks, text boxes and image pixel dimensions. + Try white and transparent backgrounds: association names should have no + white rectangles, and crossing association lines should have gaps behind + the text. Check the same names while panning/zooming and after renaming. +8. Save As a working copy outside examples/, reopen it and compare content. + Keep these generated baselines unchanged for repeatable comparisons. + +END-GOAL READABILITY + +Every class remains identifiable; every connection can be traced unambiguously; +names, roles and multiplicities retain their complete text; dashed links meet +their base association; loops and compositions remain understandable; notes, +areas and annotations help orientation. Do not count truncation, tiny text, +hidden labels, dropped edges or deletion of difficult content as a pass. + +Examples 01-04 are progressively harder regression cases. Record failures in 05 +as concrete future layout goals, with the class/edge IDs and a screenshot. +Automated loading/geometry checks do not establish visual readability. + +REMAINING REVIEW AND DEFERRED IDEAS + +Browser and PNG comparisons for the latest UI/routing changes remain outstanding +because browser automation was unavailable. Native PNG download completion and +full-app file-picker interaction also remain unverified; automated loading, +saving and geometry tests do not replace those checks. Before release, exercise +keyboard, pointer, touch, area resizing, control points and annotation tools in +all three views and both themes. + +Fainter grid dots and lighter class borders/shadows were discussed and deferred; +they are not approved changes. Preserve the optional empty operations compartment. +Reflexive loops do not automatically avoid neighbouring labels or nodes; long +roles/names and crowded borders can still require manual placement or loop resizing. +The extreme fixture above records the readability goal, not a completed result. + +REGENERATION + +From the repository root: node examples/generate.mjs +This deterministically rewrites these five fixtures and manifest.json. No random +IDs, timestamps, external services or dependencies beyond the application are +used. Future edits should update the generator and regenerate the fixtures. diff --git a/examples/generate.mjs b/examples/generate.mjs new file mode 100644 index 0000000..8f368ff --- /dev/null +++ b/examples/generate.mjs @@ -0,0 +1,306 @@ +// Reproducible conceptual smoke fixtures. Run: node examples/generate.mjs +import { mkdirSync, writeFileSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import { normalizeAttributes } from '../src/attributes.js' +import { normalizeEdges } from '../src/model/edgeUtils.js' +import { normalizeAnnotations } from '../src/hooks/useAnnotations.js' +import { parseModelFile } from '../src/model/modelOpening.js' + +const directory = fileURLToPath(new URL('.', import.meta.url)) +mkdirSync(directory, { recursive: true }) +const visibility = { conceptual: true, logical: false, physical: false } +const colors = ['#009688', '#2196f3', '#ffc107', '#9c27b0', '#ff5722', '#607d8b'] +const views = value => Object.fromEntries(['conceptual', 'logical', 'physical'].map(view => [view, { ...value }])) +const attributeNames = ['identifier', 'displayName', 'status', 'createdAt', 'updatedAt', 'effectiveFrom', 'effectiveUntil', 'referenceCode', 'description', 'revision', 'sourceSystem', 'retentionPolicy', 'classification', 'verifiedAt', 'externalReference', 'jurisdiction', 'lastReviewedBy', 'reviewDueAt'] +const manifests = [] + +function model(name) { + const result = { version: 2, modelName: name, nodes: [], edges: [], annotations: { conceptual: { items: [] }, logical: { items: [] }, physical: { items: [] } } } + let counter = 0 + const next = prefix => `${prefix}-${String(++counter).padStart(4, '0')}` + function base(id, type, x, y, data) { + const position = { x, y } + const node = { id, type, position, selected: false, data: { ...data, visibility: { ...visibility }, viewPositions: views(position) } } + result.nodes.push(node) + return id + } + const api = { + result, + cls(id, label, x, y, attrs = [], color = colors[0]) { + const names = typeof attrs === 'number' ? attributeNames.slice(0, attrs) : attrs + return base(id, 'class', x, y, { label, logicalName: '', color, + attributes: normalizeAttributes(id, names).map(a => ({ ...a, visibility: { ...visibility } })) }) + }, + area(label, x, y, width, height, color = colors[0]) { + const id = base(next('area'), 'area', x, y, { label, color, viewSizes: views({ width, height }) }) + Object.assign(result.nodes.at(-1), { width, height, style: { width, height }, zIndex: -1 }) + return id + }, + note(label, text, x, y) { return base(next('note'), 'note', x, y, { label, text }) }, + edge(source, target, name, options = {}) { + const { id = next('edge'), type = 'association', ...data } = options + if (source === target && type !== 'reflexiveAssociation') throw new Error(`Use a reflexive edge for ${source}`) + const entry = { id, source, target, sourceHandle: 'right-source', targetHandle: 'left-target', + type, selected: false, interactionWidth: 20, + data: { name, type: type === 'composition' ? 'composition' : 'association', + roleA: 'owner', roleB: 'member', multiplicityA: '1..1', multiplicityB: '0..*', + lineStyle: 'orthogonal', controlPoints: [], ...data } } + result.edges.push(entry) + return id + }, + loop(source, name, index, long = false) { + return api.edge(source, source, name, { type: 'reflexiveAssociation', + reflexiveSide: ['left', 'right', 'lower-right', 'lower-left'][index % 4], + reflexiveIndex: index, loopWidth: (long ? 190 : 85) + Math.floor(index / 4) * 150, + loopHeight: (long ? 210 : 125) + Math.floor(index / 4) * 140, + roleA: long ? 'previouslyAuthorisedResponsibleParty' : 'parent', + roleB: long ? 'subsequentlyDelegatedResponsibleParty' : 'child', multiplicityA: '0..1' }) + }, + associative(id, baseId, x, y, attrs = ['effectiveFrom', 'effectiveUntil']) { + const association = result.edges.find(e => e.id === baseId) + api.cls(id, association.data.name, x, y, attrs, colors[3]) + result.edges.push({ id: next('associative'), source: id, target: `assoc-edge-${baseId}`, + sourceHandle: 'top-source', targetHandle: 'association-target', type: 'associativeAssociation', + selected: false, interactionWidth: 20, data: { name: association.data.name, type: 'associative', autoName: true } }) + }, + text(text, x, y, options = {}) { + result.annotations.conceptual.items.push({ id: next('text'), kind: 'text', x, y, text, fontSize: 18, color: '#334155', ...options }) + }, + shape(shape, x1, y1, x2, y2, options = {}) { + result.annotations.conceptual.items.push({ id: next(shape), kind: 'shape', shape, x1, y1, x2, y2, thickness: 2, color: '#dc2626', ...options }) + }, + stroke(points, options = {}) { + result.annotations.conceptual.items.push({ id: next('stroke'), kind: 'stroke', tool: 'pen', points: points.map(([x, y]) => ({ x, y })), thickness: 3, color: '#2563eb', opacity: 1, ...options }) + }, + save(file, purpose) { + result.edges = normalizeEdges(result.edges) + result.annotations = normalizeAnnotations(result.annotations) + // A loadable model, not an arbitrary JSON drawing or a different schema. + parseModelFile(JSON.stringify(result)) + const serialized = `${JSON.stringify(result, null, 2)}\n` + writeFileSync(`${directory}${file}`, serialized) + manifests.push({ file, name, purpose, classes: result.nodes.filter(n => n.type === 'class').length, + associations: result.edges.filter(e => e.type === 'association').length, + compositions: result.edges.filter(e => e.type === 'composition').length, + reflexive: result.edges.filter(e => e.type === 'reflexiveAssociation').length, + associative: result.edges.filter(e => e.type === 'associativeAssociation').length, + edges: result.edges.length, notes: result.nodes.filter(n => n.type === 'note').length, + areas: result.nodes.filter(n => n.type === 'area').length, + annotations: result.annotations.conceptual.items.length }) + Object.assign(manifests.at(-1), { + largestParallelGroup: Math.max(0, ...result.edges.map(e => e.data?.parallelCount ?? 0)), + mostReflexiveOnOneClass: Math.max(0, ...result.edges.map(e => e.data?.reflexiveCount ?? 0)), + }) + }, + } + return api +} + +// 01: a small baseline that fits on a normal canvas at a useful zoom. +{ + const m = model('01 - Library basics') + m.cls('reader', 'Reader', 0, 0, ['name', 'email'], colors[2]) + m.cls('loan', 'Loan', 500, 0, ['borrowedAt', 'dueAt'], colors[0]) + m.cls('copy', 'BookCopy', 500, 300, ['barcode', 'condition'], colors[1]) + m.cls('book', 'Book', 0, 300, ['title', 'isbn'], colors[3]) + m.edge('reader', 'loan', 'borrows', { roleA: 'borrower', roleB: 'loans' }) + m.edge('loan', 'copy', 'records', { roleA: 'loans', roleB: 'copy', multiplicityA: '0..*', multiplicityB: '1..1' }) + m.edge('book', 'copy', 'hasCopies', { roleA: 'edition', roleB: 'copies' }) + m.save('01-library-basics.mdlz', 'Baseline names, attributes, multiplicities and orthogonal routes.') +} + +// 02: three left neighbours, two right, two above, two below and a parallel pair. +{ + const m = model('02 - Dispatch hub and border spacing') + m.area('Dispatch', 430, 430, 330, 420, colors[0]) + m.cls('hub', 'DispatchCentre', 500, 500, 10, colors[0]) + const neighbours = [ + ['sender', 'Sender', -250, 230], ['warehouse', 'Warehouse', -250, 550], ['carrier', 'Carrier', -250, 870], + ['route', 'Route', 1250, 370], ['delivery', 'Delivery', 1250, 750], + ['contract', 'Contract', 240, -180], ['policy', 'Policy', 800, -180], + ['audit', 'AuditEvent', 240, 1250], ['exception', 'Exception', 800, 1250], + ] + neighbours.forEach(([id, label, x, y], i) => { + m.cls(id, label, x, y, i % 3, colors[(i + 1) % colors.length]) + m.edge(id, 'hub', ['requests', 'stocks', 'serves', 'plans', 'dispatches', 'governs', 'restricts', 'records', 'escalates'][i], + { roleA: id, roleB: 'centre', multiplicityA: '0..*', multiplicityB: '1..1' }) + }) + m.edge('warehouse', 'hub', 'returnsTo', { roleA: 'returns', roleB: 'receivingCentre' }) + m.note('Distance regression', 'Move DispatchCentre farther right, then back. Left-border order and separation should stay stable. Repeat with Contract and Policy above the hub.', -280, -100) + m.note('Small versus tall', 'Sender has no attributes. Add attributes to it, then undo. Endpoints must remain on borders without resizing other classes.', 1180, 1100) + m.text('02 / all four borders', 460, -370, { fontSize: 26 }) + m.shape('arrow', 30, 1100, 430, 770) + m.save('02-dispatch-border-spacing.mdlz', 'Stable all-side allocation, empty/tall classes, parallel plus other neighbours, negative coordinates.') +} + +// 03: a meaningful domain with parallel links, four loops and association classes. +{ + const m = model('03 - University enrolment') + const zones = [ + ['People', -650, -400, colors[2], ['Person', 'Student', 'Lecturer', 'Department', 'Address', 'EmergencyContact']], + ['Teaching', 1150, -400, colors[1], ['Course', 'Module', 'Session', 'Room', 'Campus', 'Semester']], + ['Assessment', -650, 1200, colors[3], ['Assessment', 'Submission', 'Grade', 'Qualification', 'Attendance']], + ] + zones.forEach(([label, x, y, color, names]) => { + m.area(label, x - 60, y - 70, 1530, 1370, color) + names.forEach((name, i) => m.cls(name, name, x + (i % 3) * 480, y + Math.floor(i / 3) * 650, i === 0 ? 7 : 2 + i % 3, color)) + }) + const links = [['Person','Student','studiesAs'],['Person','Lecturer','teachesAs'],['Person','Address','livesAt'], + ['Person','EmergencyContact','nominates'],['Lecturer','Department','worksIn'],['Student','Course','enrolsIn'], + ['Student','Course','waitsFor'],['Lecturer','Course','teaches'],['Course','Module','contains'], + ['Module','Session','schedules'],['Session','Room','occupies'],['Room','Campus','locatedOn'], + ['Session','Semester','occursDuring'],['Student','Submission','submits'],['Submission','Assessment','answers'], + ['Assessment','Grade','awards'],['Grade','Qualification','contributesTo'],['Student','Attendance','attends'], + ['Attendance','Session','recordsPresenceAt'],['Lecturer','Assessment','marks'],['Course','Assessment','requires']] + let enrolment + links.forEach(([a,b,name]) => { + const id = m.edge(a,b,name, { roleA: a.toLowerCase(), roleB: b.toLowerCase(), ...(name === 'contains' ? { type: 'composition' } : {}) }) + if (name === 'enrolsIn') enrolment = id + }) + m.associative('Enrolment', enrolment, 1100, 1400, ['registeredAt', 'attempt', 'status']) + ;['mentors','delegatesTo','replaces','isRelatedTo'].forEach((name, i) => m.loop('Person', name, i)) + m.note('Four reflexive corners', 'Person has four reflexive associations. Inspect both roles, both multiplicities and each name; resize one loop, then undo.', -1000, -650) + m.note('Association class', 'The Enrolment class attaches to enrolsIn. Move Student or Course and verify that the dashed link follows the base association.', 1470, 1400) + m.note('Composition', 'Enable composite aggregations in View settings. The Course–Module diamond must remain attached and match its line colour.', 2700, 800) + m.text('Teaching and assessment / UML review', 800, -650, { fontSize: 28 }) + m.shape('rectangle', 1050, 1300, 1350, 1660, { color: '#7c3aed' }) + m.shape('ellipse', -870, -600, -180, 50) + m.shape('arrow', 1470, 1460, 1320, 1450) + m.shape('line', 950, 1000, 2700, 1000, { color: '#94a3b8' }) + m.stroke([[1120,-480],[1300,-470],[1500,-475],[1700,-460]], { tool: 'marker', color: '#facc15', thickness: 18, opacity: 0.35 }) + m.stroke([[-1000,50],[-900,120],[-800,80],[-700,140]]) + m.text('Évaluation / Prüfung / 評価', 1000, 2300, { width: 300, padding: 12, border: true, background: '#fef3c7' }) + m.save('03-university-enrolment.mdlz', 'Parallel associations, four reflexive corners, association class, composition and every annotation shape.') +} + +const domains = [ + ['Identity', ['Person','Organisation','Account','Membership','Role','Permission','Credential','Consent','Address','ContactPoint','Device','Session']], + ['Commerce', ['Customer','Order','OrderLine','Product','Catalogue','Price','Promotion','Basket','Reservation','Subscription','Channel','Offer']], + ['Fulfilment', ['Warehouse','Inventory','StockMovement','Shipment','Parcel','Carrier','Delivery','Route','Location','Return','Inspection','HandlingUnit']], + ['Finance', ['Invoice','InvoiceLine','Payment','Refund','Ledger','LedgerEntry','TaxRule','Currency','Settlement','Payout','Dispute','ExchangeRate']], + ['Trust', ['Policy','PolicyVersion','RiskAssessment','Approval','Case','Evidence','AuditEvent','RetentionRule','Jurisdiction','LegalBasis','Control','Exception']], + ['Analytics', ['Event','Metric','Observation','Dataset','Report','Dashboard','Pipeline','Transformation','Experiment','Cohort','Attribution','QualityRule']], +] + +// 04: medium production-style graph with a mix of deliberate routing choices. +{ + const m = model('04 - Commerce operations') + const names = [...domains[1][1], ...domains[2][1], ...domains[3][1].slice(0, 5)] + names.forEach((name, i) => m.cls(name, name, (i % 6) * 460 - 700, Math.floor(i / 6) * 440 - 450, i % 9, colors[Math.floor(i / 10)])) + for(let i=0; i { + const x=-2400+(d%3)*2280, y=-1800+Math.floor(d/3)*2580 + origins.push({x,y}) + m.area(`${d+1} / ${label}`,x,y,2080,1870,colors[d]) + names.forEach((name,i) => { + named.push(name) + m.cls(name, i===11 ? `${name}WithJurisdictionAndEffectivePeriod` : name, + x+80+(i%4)*480,y+150+Math.floor(i/4)*520, + [18,1,0,7,3,12,2,9,4,16,5,1][i],colors[d]) + }) + for(let i=0;i<12;i++) { + m.edge(names[i],names[(i+1)%12],['owns','governs','records','requires','supersedes','validates'][i%6], + {roleA:'responsibleParty',roleB:'applicableRecords'}) + m.edge(names[i],names[(i+4)%12],i%3===0?'isApplicableWithinEffectivePeriod':'references', + {roleA:i%3===0?'authorisedPartyAtTimeOfDecision':'origin',roleB:i%3===0?'recordsApplicableInThisJurisdiction':'references', + multiplicityA:i%2?'0..1':'1..*',multiplicityB:i%3?'0..*':'1..1', + ...(i===4?{lineStyle:'straight'}:{})}) + if(i>0 && i%2===0) m.edge(names[i],names[0],'reportsTo',{roleA:'reportingRecord',roleB:'domainOwner'}) + } + m.note(`${label}: local smoke check`,'Inspect all endpoint text at 100% zoom. Move the first class outward by 800px and back. Automatic slots should keep their order and spacing on each unchanged border.',x+70,y+1920) + m.note(`${label}: long note`,'This domain intentionally mixes minimum-height and attribute-heavy classes.\n\nA good result keeps full names, multiplicities and both endpoint roles legible. Crossings should be traceable; route editing and undo must preserve every connection.\n\nUnicode: café, Straße, Ångström, 日本語.',x+460,y+1920) + m.text(`${d+1} / ${label.toUpperCase()} — readability target`,x+70,y-85,{fontSize:30}) + m.shape('rectangle',x+30,y+90,x+450,y+620,{color:colors[d],thickness:1}) + m.shape('arrow',x+1260,y+1900,x+1250,y+1620,{color:colors[d]}) + m.stroke([[x+60,y-35],[x+420,y-20],[x+800,y-30],[x+1240,y-15]],{tool:'marker',color:colors[d],opacity:0.18,thickness:28}) + m.text('Zoom in to assess labels; fit view is for navigation.',x+1000,y+1970,{width:420,padding:10,background:'#f8fafc',border:true}) + }) + // Cross-domain fan-in/out, long diagonals, and routes through domain corridors. + for(let d=0;d<6;d++) for(let i=0;i<8;i++) { + const a=domains[d][1][i], b=domains[(d+1)%6][1][(i*5+3)%12] + m.edge(a,b,i%2?'isReconciledAgainst':'isAuthorisedByPolicyVersion',{ + roleA:'requestingDomainRecord',roleB:'crossDomainReference',multiplicityA:'0..*',multiplicityB:'0..*', + ...(i===7?{lineStyle:'manual',controlPoints:[{x:origins[d].x+2140,y:origins[d].y+500},{x:origins[d].x+2140,y:origins[(d+1)%6].y+2020},{x:origins[(d+1)%6].x+900,y:origins[(d+1)%6].y+2020}]}:{})}) + } + for(let i=0;i<24;i++) m.edge(named[(i*7)%72] === 'Person' ? 'Organisation' : named[(i*7)%72],'Person',`isAccountableFor${i%3?'':'CrossBorderDataProcessing'}`,{ + roleA:i%4?'subject':'dataSubjectRepresentedByAuthorisedDelegate',roleB:'accountablePerson', + ...(i%8===0?{lineStyle:'straight'}:{})}) + // Ten additional parallel connections between a tall and a small class; six vertically; + // mixed styles coexist with a separate all-orthogonal group. + for(let i=0;i<10;i++) m.edge('Person','Organisation', + ['belongsTo','worksFor','represents','ownsSharesIn','audits','approves','delegatesAuthorityTo','receivesNotificationsFrom','isLegallyResponsibleFor','actsAsBeneficialOwnerOf'][i], + {roleA:`personInCapacity${i+1}`,roleB:`organisationInCapacity${i+1}`,multiplicityA:i%2?'0..*':'1..1'}) + for(let i=0;i<6;i++) m.edge('Customer','Reservation',`reservationPolicy${i+1}`,{roleA:`customerRole${i+1}`,roleB:`reservationRole${i+1}`}) + for(let i=0;i<4;i++) m.edge('Invoice','Payment',`settlementStage${i+1}`,{lineStyle:i===2?'straight':'orthogonal',roleA:'invoice',roleB:'payments'}) + const loopBases=[] + for(const [id,count] of [['Person',8],['Order',4],['Policy',4],['Metric',4]]) { + for(let i=0;i=4?'DuringExceptionalCircumstances':''),i,true)) + } + for(let d=0;d<6;d++) { + m.edge(domains[d][1][0],domains[d][1][3],'ownsLifecycleOf',{type:'composition'}) + m.edge(domains[d][1][4],domains[d][1][5],'containsVersionOf',{type:'composition'}) + } + const bases=[['Person','Role','exercisesRole'],['Customer','Order','placesOrder'],['Shipment','Carrier','transportedBy'], + ['Invoice','TaxRule','assessedUnder'],['Case','Evidence','supportedBy'],['Dataset','Pipeline','producedBy']] + bases.forEach(([a,b,name],i)=>{ + const id=m.edge(a,b,name,{roleA:'subject',roleB:'governingRecord'}) + m.associative(`AssociationRecord${i+1}`,id,origins[i].x+1260,origins[i].y+1690, + ['effectiveFrom','effectiveUntil','decisionReason','evidenceReference']) + }) + m.associative('DelegationEvidence',loopBases[0],origins[0].x-580,origins[0].y+600,['authorisedAt','expiresAt','jurisdiction']) + m.associative('PolicyLineageEvidence',loopBases[12],origins[4].x-500,origins[4].y+600,['signedBy','signedAt']) + m.area('Cross-border retention jurisdiction',-2600,-550,6800,520,'#94a3b8') + m.area('Shared audit and reconciliation corridor',-2600,290,6800,350,'#a855f7') + m.area('Overlapping consent / legal-basis review',-2500,-300,750,1050,'#eab308') + m.note('READABILITY FRONTIER — keep this difficult', + 'This is an end-goal fixture, not a claim of current visual correctness. Preserve all connections and complete labels. At useful local zoom, every line should be traceable and every annotation readable.\n\nPerson intentionally has EIGHT reflexive associations: this exceeds the current four-loop creation limit. Nested loop sizes are explicit. The file remains valid v2.',-3100,-2100) + m.note('Long-label acceptance target','Do not pass by truncating names, hiding roles, removing multiplicities, dropping edges, shrinking text or deleting notes. Compare light and dark canvas; PNG exports currently use a light canvas.',4200,-1750) + m.note('Negative-coordinate export','Export the entire diagram including annotations, notes and areas. The notes and annotations outside the class envelope must remain present and unclipped.',-3100,3000) + m.note('Manual and transient smoke tests','Edit one manual route; undo once. Draw and erase one stroke; undo once. Use the laser, save and reopen: laser trails must never be saved. The fixture deliberately contains no persistent laser stroke.',4200,3100) + m.text('05 / GLOBAL PLATFORM — ASPIRATIONAL READABILITY TARGET',-2400,-2140,{fontSize:38}) + m.text('Long text: authorisation across multiple jurisdictions\nÉchéance / Gültigkeit / 有効期間\nKeep full text legible at a useful local zoom.',4200,-1100,{fontSize:20,width:430,padding:16,border:true,background:'#fef3c7'}) + m.shape('ellipse',-2850,-2050,-1900,-1100,{color:'#ef4444',thickness:3}) + m.shape('line',-2700,500,4240,500,{color:'#64748b',thickness:1}) + m.shape('arrow',4300,-600,3750,-280,{color:'#dc2626',thickness:4}) + m.stroke([[-2750,400],[-2000,280],[-800,430],[400,260],[1700,400],[2900,280],[4200,430]],{color:'#ef4444',thickness:3}) + m.stroke([[-2340,-1600],[-2200,-1590],[-2080,-1580]],{color:'#ffffff',thickness:4}) + m.stroke([[4200,2700],[4270,2630],[4320,2720],[4410,2610]],{color:'#2563eb',thickness:2,linear:true}) + m.save('05-global-platform-frontier.mdlz','Aspirational extreme: large graph, twelve parallel links in the busiest pair, eight loops on one class, long labels, all annotation types, overlapping domains and mixed routing.') +} + +writeFileSync(`${directory}manifest.json`, `${JSON.stringify(manifests,null,2)}\n`) +process.stdout.write(`${manifests.map(m=>`${m.file}: ${m.classes} classes, ${m.edges} edges, ${m.notes} notes, ${m.areas} areas, ${m.annotations} annotations`).join('\n')}\n`) diff --git a/examples/manifest.json b/examples/manifest.json new file mode 100644 index 0000000..d6311c9 --- /dev/null +++ b/examples/manifest.json @@ -0,0 +1,82 @@ +[ + { + "file": "01-library-basics.mdlz", + "name": "01 - Library basics", + "purpose": "Baseline names, attributes, multiplicities and orthogonal routes.", + "classes": 4, + "associations": 3, + "compositions": 0, + "reflexive": 0, + "associative": 0, + "edges": 3, + "notes": 0, + "areas": 0, + "annotations": 0, + "largestParallelGroup": 1, + "mostReflexiveOnOneClass": 0 + }, + { + "file": "02-dispatch-border-spacing.mdlz", + "name": "02 - Dispatch hub and border spacing", + "purpose": "Stable all-side allocation, empty/tall classes, parallel plus other neighbours, negative coordinates.", + "classes": 10, + "associations": 10, + "compositions": 0, + "reflexive": 0, + "associative": 0, + "edges": 10, + "notes": 2, + "areas": 1, + "annotations": 2, + "largestParallelGroup": 2, + "mostReflexiveOnOneClass": 0 + }, + { + "file": "03-university-enrolment.mdlz", + "name": "03 - University enrolment", + "purpose": "Parallel associations, four reflexive corners, association class, composition and every annotation shape.", + "classes": 18, + "associations": 20, + "compositions": 1, + "reflexive": 4, + "associative": 1, + "edges": 26, + "notes": 3, + "areas": 3, + "annotations": 8, + "largestParallelGroup": 2, + "mostReflexiveOnOneClass": 4 + }, + { + "file": "04-commerce-operations.mdlz", + "name": "04 - Commerce operations", + "purpose": "Dense mixed routing, five parallel lanes including composition, eight loops, three association classes and overlapping areas.", + "classes": 32, + "associations": 48, + "compositions": 5, + "reflexive": 8, + "associative": 3, + "edges": 64, + "notes": 3, + "areas": 4, + "annotations": 11, + "largestParallelGroup": 5, + "mostReflexiveOnOneClass": 4 + }, + { + "file": "05-global-platform-frontier.mdlz", + "name": "05 - Global platform readability frontier", + "purpose": "Aspirational extreme: large graph, twelve parallel links in the busiest pair, eight loops on one class, long labels, all annotation types, overlapping domains and mixed routing.", + "classes": 80, + "associations": 272, + "compositions": 12, + "reflexive": 20, + "associative": 8, + "edges": 312, + "notes": 16, + "areas": 9, + "annotations": 38, + "largestParallelGroup": 12, + "mostReflexiveOnOneClass": 8 + } +] diff --git a/public/fonts/sora/OFL.txt b/public/fonts/sora/OFL.txt new file mode 100644 index 0000000..f1d9d6a --- /dev/null +++ b/public/fonts/sora/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2019 The Sora Project Authors (https://github.com/sora-xor/sora-font) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/sora/README.txt b/public/fonts/sora/README.txt new file mode 100644 index 0000000..92360f4 --- /dev/null +++ b/public/fonts/sora/README.txt @@ -0,0 +1,7 @@ +Sora by The Sora Project Authors. +Source: https://github.com/sora-xor/sora-font +Font: fonts/woff2/Sora[wght].woff2 (unmodified variable font, weights 100-800) +Downloaded: 2026-10-23 +License: SIL Open Font License 1.1; see OFL.txt in this directory. + +Bundled locally for the Modelizer wordmark, using weight 550. diff --git a/public/fonts/sora/Sora-Variable.woff2 b/public/fonts/sora/Sora-Variable.woff2 new file mode 100644 index 0000000..ec8ecca Binary files /dev/null and b/public/fonts/sora/Sora-Variable.woff2 differ diff --git a/src/App.jsx b/src/App.jsx index c166dea..4dffba9 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,3 +1,5 @@ +import FileErrorDialog from './components/dialogs/FileErrorDialog.jsx' +import ModelContentDialog from './components/dialogs/ModelContentDialog.jsx' import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { ReactFlow, @@ -6,8 +8,8 @@ import { ConnectionLineType, Controls, } from '@xyflow/react' -import * as Toast from '@radix-ui/react-toast' import { edgeTypes, nodeTypes } from './flowTypes.js' +import AssociationLabelMask from './components/flow/labels/AssociationLabelMask.jsx' import { ConfirmDiscardDialog, DeleteDialog, @@ -182,14 +184,10 @@ function App() { open: false, count: 0, }) - const [hiddenContentToast, setHiddenContentToast] = useState({ - open: false, - title: '', - description: '', - }) - const [fileError, setFileError] = useState({ open: false, message: '', sequence: 0 }) - const onFileError = useCallback((message) => { - setFileError((previous) => ({ open: true, message, sequence: previous.sequence + 1 })) + const [hiddenContentReport, setHiddenContentReport] = useState(null) + const [fileError, setFileError] = useState({ open: false, message: '' }) + const onFileError = useCallback((message, details = {}) => { + setFileError({ open: true, message, ...details }) }, []) const resizeState = useRef(null) const deleteActionRef = useRef(null) @@ -234,38 +232,13 @@ function App() { setImportWarningDialog({ open: true, count }) }, []) - const onHiddenContent = useCallback( - ({ hiddenNotes, hiddenAreas, hiddenCompositions, hiddenAnnotations }) => { - const parts = [] - if (hiddenNotes) { - parts.push('Notes') - } - if (hiddenAreas) { - parts.push('Areas') - } - if (hiddenCompositions) { - parts.push('Composite aggregations') - } - if (hiddenAnnotations) { - parts.push('Annotations') - } - if (parts.length === 0) { - return - } - const subject = - parts.length <= 2 - ? parts.join(' and ') - : `${parts.slice(0, -1).join(', ')}, and ${parts.at(-1)}` - const verb = 'are' - const pronoun = 'them' - setHiddenContentToast({ - open: true, - title: 'Hidden content', - description: `This file contains ${subject}, but ${subject} ${verb} disabled in Settings. Enable ${subject} to view ${pronoun}.`, - }) - }, - [], - ) + const onHiddenContent = useCallback(report => setHiddenContentReport(report), []) + const onRevealContent = useCallback(category => { + if (category === 'notes') setShowNotes(true) + if (category === 'areas') setShowAreas(true) + if (category === 'compositions') setShowCompositionAggregation(true) + if (category === 'annotations') { setShowAnnotations(true); setAnnotationsVisible(true) } + }, []) useEffect(() => { writeStoredBool(STORAGE_KEYS.showBackground, showBackground) @@ -333,12 +306,6 @@ function App() { } }, []) - const onHiddenContentToastOpenChange = useCallback((open) => { - if (!open) { - setHiddenContentToast((current) => ({ ...current, open: false })) - } - }, []) - const resetViewport = useCallback(() => { if (!reactFlowInstance) { return @@ -431,6 +398,8 @@ function App() { selectedId, selectedItem, updateSelected: onSelectedAnnotationChange, + beginStyleEdit: onAnnotationStyleEditStart, + endStyleEdit: onAnnotationStyleEditEnd, onSelectItem: onSelectAnnotation, onItemPointerDown: onAnnotationItemPointerDown, onDeleteSelected: onDeleteSelectedAnnotation, @@ -721,10 +690,12 @@ function App() { showAreas, showCompositionAggregation, showAnnotations, + annotationsVisible, onHiddenContent, onImportWarning, onLoadAnnotations, onNewModelCreated: () => { + setHiddenContentReport(null) setActiveView(VIEW_CONCEPTUAL) resetViewport() onLoadAnnotations(null) @@ -892,7 +863,7 @@ function App() { ) return ( - + <>
{isFileOver && (
@@ -1053,10 +1024,11 @@ function App() { maxZoom={3} defaultEdgeOptions={{ interactionWidth: 20 }} > +
- {showBackground ? : null} + {showBackground ? : null} {showAnnotations ? ( <> {annotationsVisible && { setAnnotationsVisible(true); onSetAnnotationTool(tool) }} selectedItem={selectedItem} onSelectedChange={onSelectedAnnotationChange} + onStyleEditStart={onAnnotationStyleEditStart} + onStyleEditEnd={onAnnotationStyleEditEnd} onDeleteSelected={onDeleteSelectedAnnotation} onDuplicateSelected={onDuplicateSelectedAnnotation} canUndo={canUndo} @@ -1143,53 +1117,16 @@ function App() { count={importWarningDialog.count} onOpenChange={onImportWarningOpenChange} /> - - - - {hiddenContentToast.title} - - - {hiddenContentToast.description} - - - setFileError((current) => ({ ...current, open }))} - className="toast-root" - type="foreground" - data-no-export="true" - > - Could not open model - {fileError.message} - Dismiss - - setHiddenContentReport(null)} + onReveal={onRevealContent} /> + setFileError(current => ({ ...current, open }))} />
- + ) } diff --git a/src/__tests__/annotationIntegration.test.jsx b/src/__tests__/annotationIntegration.test.jsx index 367bc31..8fcf0ec 100644 --- a/src/__tests__/annotationIntegration.test.jsx +++ b/src/__tests__/annotationIntegration.test.jsx @@ -109,10 +109,10 @@ describe('annotation editor integration', () => { expect(screen.queryByRole('dialog')).not.toBeInTheDocument() }) - it('remembers accent colors from the export dialog without a duplicate Settings control', async () => { + it('remembers accent colors from the export dialog without a duplicate Preferences control', async () => { const user = userEvent.setup() render() - await user.click(screen.getByRole('menuitem', { name: 'Settings', exact: true })) + await user.click(screen.getByRole('menuitem', { name: 'Preferences', exact: true })) expect(screen.queryByRole('menuitemcheckbox', { name: 'Accent colors in PNG exports' })).not.toBeInTheDocument() await user.keyboard('{Escape}') await user.click(screen.getByRole('menuitem', { name: 'File', exact: true })) diff --git a/src/__tests__/classCreationHistory.test.jsx b/src/__tests__/classCreationHistory.test.jsx new file mode 100644 index 0000000..a17dd79 --- /dev/null +++ b/src/__tests__/classCreationHistory.test.jsx @@ -0,0 +1,36 @@ +import { cleanup, render, screen, waitFor } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { afterEach, beforeEach, expect, it, vi } from 'vitest' +import App from '../App.jsx' + +beforeEach(() => { + vi.stubGlobal('__APP_VERSION__', 'test') + vi.stubGlobal('DOMMatrixReadOnly', class { m22 = 1 }) + localStorage.clear() + Element.prototype.hasPointerCapture = vi.fn(() => false) + Element.prototype.setPointerCapture = vi.fn() + Element.prototype.releasePointerCapture = vi.fn() + Element.prototype.scrollIntoView = vi.fn() +}) +afterEach(() => { cleanup(); vi.unstubAllGlobals(); localStorage.clear() }) + +it.each(['conceptual', 'logical', 'physical'])('undoes class/table creation in %s once after automatic name editing', async view => { + const user = userEvent.setup() + const { container } = render() + if (view !== 'conceptual') await user.click(screen.getByRole('button', { name: view === 'logical' ? 'Logical' : 'Physical', exact: true })) + const count = () => container.querySelectorAll('.react-flow__node').length + const originalCount = count() + await user.click(screen.getByRole('button', { name: view === 'conceptual' ? 'Add class' : 'Add table', exact: true })) + const name = await screen.findByPlaceholderText(view === 'conceptual' ? 'Class name' : 'Table name') + await waitFor(() => expect(name).toHaveFocus()) + await user.keyboard('{Enter}') + expect(count()).toBe(originalCount + 1) + await user.click(screen.getByRole('menuitem', { name: 'Edit', exact: true })) + await user.click(screen.getByRole('menuitem', { name: /^Undo/ })) + await waitFor(() => expect(count()).toBe(originalCount)) + expect(screen.queryByLabelText('Unsaved changes')).not.toBeInTheDocument() + await user.click(screen.getByRole('menuitem', { name: 'Edit', exact: true })) + expect(screen.getByRole('menuitem', { name: /^Undo/ })).toHaveAttribute('aria-disabled', 'true') + await user.click(screen.getByRole('menuitem', { name: /^Redo/ })) + await waitFor(() => expect(count()).toBe(originalCount + 1)) +}) diff --git a/src/__tests__/themeIntegration.test.jsx b/src/__tests__/themeIntegration.test.jsx index 89e1c50..6ed3715 100644 --- a/src/__tests__/themeIntegration.test.jsx +++ b/src/__tests__/themeIntegration.test.jsx @@ -29,7 +29,7 @@ describe('editor theme control', () => { const nodeCount = container.querySelectorAll('.react-flow__node').length const viewport = container.querySelector('.react-flow__viewport') const transform = viewport.style.transform - const view = screen.getByRole('menuitem', { name: 'View', exact: true }) + const view = screen.getByRole('menuitem', { name: 'Preferences', exact: true }) view.focus() await user.keyboard('{ArrowDown}') const toggle = await screen.findByRole('menuitemcheckbox', { name: 'Dark mode' }) @@ -59,7 +59,7 @@ describe('editor theme control', () => { await user.clear(name) await user.paste('Theme regression model') await user.keyboard('{Enter}') - await user.click(screen.getByRole('menuitem', { name: 'View', exact: true })) + await user.click(screen.getByRole('menuitem', { name: 'Preferences', exact: true })) await user.click(screen.getByRole('menuitemcheckbox', { name: 'Dark mode' })) expect(screen.getByText('Theme regression model')).toBeInTheDocument() expect(screen.getByText('*', { exact: true })).toBeInTheDocument() @@ -79,16 +79,16 @@ describe('consistent menu preferences', () => { const user = userEvent.setup() render() const preferences = [ - ['Settings', 'Composite aggregation', 'showCompositionAggregation'], - ['Settings', 'Operations compartment', 'showConceptualOperationsCompartment'], - ['Settings', 'Notes', 'showNotes'], - ['Settings', 'Areas', 'showAreas'], - ['Settings', 'Annotations', 'showAnnotations'], - ['Settings', 'Confirmation dialogs', 'confirmDelete'], + ['Preferences', 'Enable composite aggregation', 'showCompositionAggregation'], + ['View', 'Operations compartment', 'showConceptualOperationsCompartment'], + ['View', 'Notes', 'showNotes'], + ['View', 'Areas', 'showAreas'], + ['View', 'Annotations', 'showAnnotations'], + ['Preferences', 'Confirm before deleting', 'confirmDelete'], ['View', 'Background grid', 'showBackground'], ['View', 'Accent colors', 'showAccentColors'], ['View', 'Fullscreen', 'showFullscreen'], - ['View', 'View-specific settings only', 'viewSpecificSettingsOnly'], + ['Preferences', 'Only show fields for current view', 'viewSpecificSettingsOnly'], ] for (const [menu, label, key] of preferences) { const trigger = screen.getByRole('menuitem', { name: menu, exact: true }) @@ -110,7 +110,7 @@ describe('consistent menu preferences', () => { render() async function openConstraints() { await user.click(screen.getByRole('menuitem', { name: 'View', exact: true })) - screen.getByRole('menuitem', { name: 'Constraints', exact: true }).focus() + screen.getByRole('menuitem', { name: 'Nullability notation', exact: true }).focus() await user.keyboard('{ArrowRight}') await screen.findByRole('menuitemradio', { name: 'Null', exact: true }) } diff --git a/src/components/annotations/AnnotationLayer.jsx b/src/components/annotations/AnnotationLayer.jsx index 7f4cecd..59680c3 100644 --- a/src/components/annotations/AnnotationLayer.jsx +++ b/src/components/annotations/AnnotationLayer.jsx @@ -26,19 +26,14 @@ function getCursorForTool(activeTool, penSettings, markerSettings, eraserSetting function forwardWheelToReactFlow(e) { const overlay = e.currentTarget const sourceEvent = e.nativeEvent - if (!overlay || sourceEvent.__annotationWheelForwarded) { + if (!overlay || sourceEvent.__annotationWheelForwarded || sourceEvent.target?.closest?.('textarea')) { return } - // Temporarily opting the overlay out of hit-testing lets the browser resolve - // the React Flow element underneath. The style is restored before this handler - // returns, so the mutation is scoped to one synchronous event dispatch. - const previousPointerEvents = overlay.style.pointerEvents - overlay.style.pointerEvents = 'none' - const target = document.elementFromPoint(sourceEvent.clientX, sourceEvent.clientY) - overlay.style.pointerEvents = previousPointerEvents - - if (!target || overlay.contains(target)) { + // Hit targets opt into pointer events independently of the overlay. Forward + // directly to this canvas's zoom pane instead of hit-testing through them. + const target = overlay.closest('.react-flow')?.querySelector('.react-flow__renderer') + if (!target) { return } diff --git a/src/components/annotations/AnnotationToolbox.jsx b/src/components/annotations/AnnotationToolbox.jsx index cd7705c..16469ba 100644 --- a/src/components/annotations/AnnotationToolbox.jsx +++ b/src/components/annotations/AnnotationToolbox.jsx @@ -1,4 +1,4 @@ -import { forwardRef, useState } from 'react' +import { forwardRef, useCallback, useEffect, useRef, useState } from 'react' import { Panel } from '@xyflow/react' import * as AlertDialog from '@radix-ui/react-alert-dialog' import * as Popover from '@radix-ui/react-popover' @@ -73,10 +73,35 @@ function FlyoutContent({ children, label }) { } -function Slider({ label, min, max, step = 1, value, displayValue = value, onChange }) { +function Slider({ label, min, max, step = 1, value, displayValue = value, onChange, onGestureStart, onGestureEnd }) { + const editing = useRef(false) + const begin = () => { + if (editing.current) return + editing.current = true + onGestureStart?.() + } + const end = useCallback(() => { + if (!editing.current) return + editing.current = false + onGestureEnd?.() + }, [onGestureEnd]) + useEffect(() => { + window.addEventListener('pointerup', end) + window.addEventListener('pointercancel', end) + window.addEventListener('blur', end) + return () => { + window.removeEventListener('pointerup', end) + window.removeEventListener('pointercancel', end) + window.removeEventListener('blur', end) + end() + } + }, [end]) return } @@ -122,6 +147,7 @@ export default function AnnotationToolbox({ activeTool, onSetTool, penSettings, onPenSettingsChange, markerSettings, onMarkerSettingsChange, textSettings, onTextSettingsChange, eraserSettings, onEraserSettingsChange, onClearView, selectedItem, onSelectedChange, onDeleteSelected, onDuplicateSelected, + onStyleEditStart, onStyleEditEnd, canUndo, canRedo, onUndo, onRedo, annotationsVisible = true, onToggleVisibility, onExportPng, }) { const [isClearDialogOpen, setIsClearDialogOpen] = useState(false) @@ -134,6 +160,7 @@ export default function AnnotationToolbox({ const canStyle = isText || isMarker || activeTool === 'pen' || isShape || (activeTool === 'select' && selectedItem) const settings = activeTool === 'select' && selectedItem ? selectedItem : isText ? textSettings : isMarker ? markerSettings : penSettings const change = activeTool === 'select' && selectedItem ? onSelectedChange : isText ? onTextSettingsChange : isMarker ? onMarkerSettingsChange : onPenSettingsChange + const sliderGesture = { onGestureStart: onStyleEditStart, onGestureEnd: onStyleEditEnd } const optionLabel = isText ? 'Text options' : isMarker ? 'Marker options' : activeTool === 'pen' ? 'Pen options' : isShape ? 'Shape options' : 'Annotation options' const selectedShape = isShape ? activeTool : lastShape const action = (callback) => { setActionsOpen(false); callback?.() } @@ -201,12 +228,12 @@ export default function AnnotationToolbox({ : canStyle ? <> change({ color })} /> {isText ? <> - change({ fontSize })} /> + change({ fontSize })} /> change({ width: checked ? 220 : undefined })} /> - {settings.width && change({ width })} />} + {settings.width && change({ width })} />} change({ background: checked ? '#ffffff' : '', ...(checked && !settings.padding ? { padding: 6 } : {}) })} /> {settings.background && } - change({ padding })} /> + change({ padding })} /> change({ border })} /> : <>
@@ -217,8 +244,8 @@ export default function AnnotationToolbox({ )}
- change({ thickness })} /> - {isMarker && change({ opacity: opacity / 100 })} />} + change({ thickness })} /> + {isMarker && change({ opacity: opacity / 100 })} />} } : null} diff --git a/src/components/annotations/__tests__/AnnotationLayer.test.jsx b/src/components/annotations/__tests__/AnnotationLayer.test.jsx index 99971c6..ae844ad 100644 --- a/src/components/annotations/__tests__/AnnotationLayer.test.jsx +++ b/src/components/annotations/__tests__/AnnotationLayer.test.jsx @@ -198,68 +198,21 @@ describe('AnnotationLayer', () => { expect(onCommitText).toHaveBeenCalledWith('New annotation') }) - it('forwards wheel events to the element below the annotation overlay', () => { - const underlying = document.createElement('div') - const onWheel = vi.fn() - underlying.addEventListener('wheel', onWheel) - document.body.appendChild(underlying) - const originalElementFromPoint = document.elementFromPoint - Object.defineProperty(document, 'elementFromPoint', { - configurable: true, - value: vi.fn(() => underlying), - }) - - try { - const { container } = renderLayer() - const overlay = container.querySelector('.react-flow__annotation-layer') - - fireEvent.wheel(overlay, { clientX: 10, clientY: 20, deltaY: 120 }) - - expect(onWheel).toHaveBeenCalledTimes(1) - const forwardedEvent = onWheel.mock.calls[0][0] - expect(forwardedEvent.deltaY).toBe(120) - expect(forwardedEvent.__annotationWheelForwarded).toBe(true) - } finally { - Object.defineProperty(document, 'elementFromPoint', { - configurable: true, - value: originalElementFromPoint, - }) - underlying.remove() - } - }) - it('does not re-forward wheel events that already came through the annotation overlay', () => { - const originalElementFromPoint = document.elementFromPoint - const elementFromPoint = vi.fn() - Object.defineProperty(document, 'elementFromPoint', { - configurable: true, - value: elementFromPoint, - }) - - try { - const { container } = renderLayer() - const overlay = container.querySelector('.react-flow__annotation-layer') - const wheelEvent = new WheelEvent('wheel', { - bubbles: true, - cancelable: true, - clientX: 10, - clientY: 20, - deltaY: 120, - }) - Object.defineProperty(wheelEvent, '__annotationWheelForwarded', { - value: true, - }) - - overlay.dispatchEvent(wheelEvent) - - expect(elementFromPoint).not.toHaveBeenCalled() - } finally { - Object.defineProperty(document, 'elementFromPoint', { - configurable: true, - value: originalElementFromPoint, - }) - } - }) + it('forwards wheels over selectable text to its own canvas with modifiers intact', () => { + const {container}=renderLayer({activeTool:'select'}); + container.classList.add('react-flow'); + const renderer=document.createElement('div');renderer.className='react-flow__renderer';container.appendChild(renderer); + const onWheel=vi.fn();renderer.addEventListener('wheel',onWheel); + const hit=container.querySelector('[data-annotation-hit-target]'); + fireEvent.wheel(hit,{clientX:130,clientY:90,deltaY:120,deltaX:5,ctrlKey:true}); + expect(onWheel).toHaveBeenCalledTimes(1); + expect(onWheel.mock.calls[0][0]).toMatchObject({deltaY:120,deltaX:5,ctrlKey:true,clientX:130,clientY:90,__annotationWheelForwarded:true}); + const forwarded=new WheelEvent('wheel',{bubbles:true,deltaY:120}); + Object.defineProperty(forwarded,'__annotationWheelForwarded',{value:true}); + hit.dispatchEvent(forwarded); + expect(onWheel).toHaveBeenCalledTimes(1); + }); it('shows a pan cursor while temporary pan mode is active', () => { const { container } = renderLayer({ isTemporaryPanMode: true }) @@ -316,3 +269,35 @@ describe('annotation selection and laser rendering', () => { } }) }) + +it.each([ + { id: 'shape', kind: 'shape', shape: 'rectangle', x1: 0, y1: 0, x2: 100, y2: 60, color: '#000000', thickness: 2 }, + { id: 'stroke', kind: 'stroke', tool: 'pen', points: [{ x: 0, y: 0 }, { x: 100, y: 60 }], color: '#000000', thickness: 2, opacity: 1 }, +])('forwards wheel events over a selectable $kind', (item) => { + const { container } = renderLayer({ + activeTool: 'select', selectedId: item.id, + annotations: { conceptual: { items: [item] } }, + }) + container.classList.add('react-flow') + const renderer = document.createElement('div') + renderer.className = 'react-flow__renderer' + container.appendChild(renderer) + const onWheel = vi.fn() + renderer.addEventListener('wheel', onWheel) + const hit = container.querySelector('[role="button"] [pointer-events="stroke"]') + expect(hit).not.toBeNull() + fireEvent.wheel(hit, { deltaY: -120 }) + expect(onWheel).toHaveBeenCalledOnce() +}) + +it('preserves wheel scrolling inside the annotation text editor', () => { + const { container } = renderLayer({ activeTool: 'text', editingTextId: 'text-1' }) + container.classList.add('react-flow') + const renderer = document.createElement('div') + renderer.className = 'react-flow__renderer' + container.appendChild(renderer) + const onWheel = vi.fn() + renderer.addEventListener('wheel', onWheel) + fireEvent.wheel(screen.getByRole('textbox'), { deltaY: 120 }) + expect(onWheel).not.toHaveBeenCalled() +}) diff --git a/src/components/annotations/__tests__/AnnotationToolbox.test.jsx b/src/components/annotations/__tests__/AnnotationToolbox.test.jsx index 18a7348..e794e95 100644 --- a/src/components/annotations/__tests__/AnnotationToolbox.test.jsx +++ b/src/components/annotations/__tests__/AnnotationToolbox.test.jsx @@ -186,3 +186,23 @@ describe('AnnotationToolbox', () => { expect(screen.queryByText('Clear annotations?')).not.toBeInTheDocument() }) }) + +it('groups pointer and keyboard slider gestures and ends them on blur or unmount', () => { + const start=vi.fn(),end=vi.fn(); + const {unmount}=renderToolbox({activeTool:'text',onStyleEditStart:start,onStyleEditEnd:end}); + fireEvent.click(screen.getByRole('button',{name:'Text options'})); + const slider=screen.getByRole('slider',{name:'Font size'}); + fireEvent.pointerDown(slider); + fireEvent.change(slider,{target:{value:16}}); + fireEvent.change(slider,{target:{value:20}}); + fireEvent.pointerUp(window); + expect(start).toHaveBeenCalledTimes(1);expect(end).toHaveBeenCalledTimes(1); + fireEvent.keyDown(slider,{key:'ArrowRight'}); + fireEvent.keyDown(slider,{key:'ArrowRight',repeat:true}); + fireEvent.keyUp(slider,{key:'ArrowRight'}); + expect(start).toHaveBeenCalledTimes(2);expect(end).toHaveBeenCalledTimes(2); + fireEvent.pointerDown(slider);fireEvent.blur(slider); + expect(end).toHaveBeenCalledTimes(3); + fireEvent.pointerDown(slider);unmount(); + expect(end).toHaveBeenCalledTimes(4); +}); diff --git a/src/components/dialogs/FileErrorDialog.jsx b/src/components/dialogs/FileErrorDialog.jsx new file mode 100644 index 0000000..f932095 --- /dev/null +++ b/src/components/dialogs/FileErrorDialog.jsx @@ -0,0 +1,26 @@ +import * as Dialog from '@radix-ui/react-dialog' +import { dialogStyles } from './dialogStyles.js' + +export default function FileErrorDialog({ error, onOpenChange }) { + const unsupported = error.code === 'UNSUPPORTED_MODEL_VERSION' + const newer = unsupported && typeof error.fileVersion === 'number' && error.fileVersion > error.supportedVersion + return + + + + {newer ? 'Newer Modelizer required' : unsupported ? 'Unsupported model format' : 'Could not open model'} + + {unsupported + ? `This file uses model format ${String(error.fileVersion)}. This version of Modelizer supports formats 1 and ${error.supportedVersion}.` + : error.message} + + {unsupported &&

Open the file in the latest Modelizer online, or update your downloaded copy and try again.

} +

The selected file has not been changed.

+
+ Close + {unsupported && Open latest Modelizer} +
+
+
+
+} diff --git a/src/components/dialogs/HelpDialog.jsx b/src/components/dialogs/HelpDialog.jsx index 162e7d6..f564c8f 100644 --- a/src/components/dialogs/HelpDialog.jsx +++ b/src/components/dialogs/HelpDialog.jsx @@ -1,3 +1,4 @@ +import { useId, useState } from 'react' import * as Dialog from '@radix-ui/react-dialog' import * as Tabs from '@radix-ui/react-tabs' import MarkdownIt from 'markdown-it' @@ -5,51 +6,129 @@ import { dialogStyles } from './dialogStyles.js' import helpMarkdown from '../../content/help.md?raw' import aboutMarkdown from '../../content/about.md?raw' -const markdown = new MarkdownIt({ breaks: true, linkify: true }) -const helpHtml = markdown.render(helpMarkdown) -const aboutHtml = markdown.render(aboutMarkdown) -const markdownClass = - 'text-xs leading-relaxed text-base-content [&_p]:mt-2 [&_ul]:mt-2 [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:mt-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_li]:mt-1 [&_h1]:mt-3 [&_h1]:text-base [&_h1]:font-semibold [&_h2]:mt-3 [&_h2]:text-sm [&_h2]:font-semibold [&_h3]:mt-2 [&_h3]:text-xs [&_h3]:font-semibold [&_a]:text-primary [&_a]:underline' +const markdown = new MarkdownIt({ linkify: true }) +markdown.renderer.rules.link_open = (tokens, index, options, env, renderer) => { + // Keep help links from navigating away from an unsaved model. + tokens[index].attrSet('target', '_blank') + tokens[index].attrSet('rel', 'noopener noreferrer') + return renderer.renderToken(tokens, index, options) +} + +// Level-two headings define topics; keep the guide editable as Markdown. +function readSections(source) { + const [intro, ...sections] = source.split(/^## /m) + return { + intro: markdown.render(intro), + sections: sections.map((section, index) => { + const lineEnd = section.indexOf('\n') + return { + id: `topic-${index}`, + title: section.slice(0, lineEnd).trim(), + html: markdown.render(section.slice(lineEnd + 1)), + } + }), + } +} + +const guide = readSections(helpMarkdown) +const about = readSections(aboutMarkdown) +const focusClass = 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-base-100' + +function MarkdownContent({ html, className = '' }) { + // Bundled, trusted Markdown only; MarkdownIt leaves raw HTML disabled. + return
+} + +function HelpGuide() { + const [topicId, setTopicId] = useState(guide.sections[0].id) + const headingId = useId() + const topic = guide.sections.find(section => section.id === topicId) + + return ( +
+ +
+ + +
+
+

{topic.title}

+ +
+
+ ) +} + +function AboutContent() { + return ( +
+
+ +
+ {about.sections.map(section => ( +
+

{section.title}

+ +
+ ))} +
+
+
+ ) +} export function HelpDialog({ open, onOpenChange }) { + const [tab, setTab] = useState('help') + const appVersion = typeof __APP_VERSION__ === 'string' ? `v${__APP_VERSION__}` : '' + return ( - - - - - Help - - - About - + +
+ +
+ {tab === 'help' ? 'Modelizer help' : 'About Modelizer'} + + {tab === 'help' ? 'From your first class to a model ready to share.' : 'A database modeling tool for teaching and learning.'} + +
+
+ + + {['help', 'about'].map(value => ( + + {value === 'help' ? 'Help' : 'About'} + + ))} - -
+ + - -
+ + -
- Close -
+
+ Modelizer {appVersion} + Close +
diff --git a/src/components/dialogs/ModelContentDialog.jsx b/src/components/dialogs/ModelContentDialog.jsx new file mode 100644 index 0000000..6f5c3e3 --- /dev/null +++ b/src/components/dialogs/ModelContentDialog.jsx @@ -0,0 +1,54 @@ +import { useEffect } from 'react' +import * as Dialog from '@radix-ui/react-dialog' +import { dialogStyles } from './dialogStyles.js' + +const CATEGORIES = [ + ['hiddenNotes', 'notes', 'notes'], + ['hiddenAreas', 'areas', 'areas'], + ['hiddenCompositions', 'compositions', 'composite aggregations'], + ['hiddenAnnotations', 'annotations', 'annotations'], +] + +export default function ModelContentDialog({ report, enabled, onDismiss, onReveal, visible = true }) { + const categories = CATEGORIES.filter(([key]) => report?.[key]) + const pending = categories.filter(([, setting]) => !enabled[setting]) + const resolved = categories.length > 0 && pending.length === 0 + + useEffect(() => { + // Forget this file-opening report once resolved; later settings changes + // must not revive it, even when a different view is active. + if (resolved) onDismiss() + }, [resolved, onDismiss]) + + const needsComposition = pending.some(([, setting]) => setting === 'compositions') + const content = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' }) + .format(pending.filter(([, setting]) => setting !== 'compositions').map(([, , label]) => label)) + + return ( + 0} onOpenChange={open => { if (!open) onDismiss() }}> + + + + {needsComposition && !content ? 'Enable composite aggregation?' : 'Show hidden content?'} + + {content && <>This model contains {content} hidden by your display settings. } + {needsComposition && 'Composite aggregation is disabled. Enabling it will show the composite aggregations in this model and allow you to create them.'} + +
+ + {needsComposition ? (content ? 'Keep current settings' : 'Keep disabled') : 'Keep hidden'} + + +
+
+
+
+ ) +} diff --git a/src/components/dialogs/__tests__/HelpDialog.test.jsx b/src/components/dialogs/__tests__/HelpDialog.test.jsx new file mode 100644 index 0000000..3c16125 --- /dev/null +++ b/src/components/dialogs/__tests__/HelpDialog.test.jsx @@ -0,0 +1,60 @@ +import { useState } from 'react' +import { cleanup, render, screen, within } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { afterEach, expect, it } from 'vitest' +import { HelpDialog } from '../HelpDialog.jsx' + +afterEach(cleanup) + +function Harness() { + const [open, setOpen] = useState(false) + return <> +} + +it('opens a named guide and lets readers choose task instructions with the keyboard', async () => { + const user = userEvent.setup() + render() + await user.click(screen.getByRole('button', { name: 'Open help' })) + expect(screen.getByRole('dialog', { name: 'Modelizer help' })).toHaveAccessibleDescription('From your first class to a model ready to share.') + expect(screen.getByRole('article', { name: 'Your first model' })).toHaveTextContent('Reader') + const topic = within(screen.getByRole('navigation', { name: 'Help topics' })).getByRole('button', { name: 'Connect classes and tables' }) + topic.focus() + await user.keyboard('{Enter}') + expect(topic).toHaveAttribute('aria-current', 'page') + expect(screen.queryByRole('article', { name: 'Your first model' })).not.toBeInTheDocument() + expect(screen.getByRole('article', { name: 'Connect classes and tables' })).toHaveTextContent('Associations have no direction') + await user.keyboard('{Escape}') + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() +}) + +it('supports the compact topic selector and exposes shortcut tables', async () => { + const user = userEvent.setup() + render( {}} />) + await user.selectOptions(screen.getByRole('combobox', { name: 'Help topic' }), screen.getByRole('option', { name: 'Keyboard shortcuts' })) + const article = screen.getByRole('article', { name: 'Keyboard shortcuts' }) + expect(within(article).getAllByRole('table')).toHaveLength(2) + expect(article).toHaveTextContent('Ctrl/Cmd + S') +}) + +it('shows About with preserved credits, local setup, safe links, and a working close button', async () => { + const user = userEvent.setup() + render() + await user.click(screen.getByRole('button', { name: 'Open help' })) + screen.getByRole('tab', { name: 'Help', exact: true }).focus() + await user.keyboard('{ArrowRight}') + const dialog = screen.getByRole('dialog', { name: 'About Modelizer' }) + expect(within(dialog).getByRole('heading', { name: 'Run locally on Windows' })).toBeInTheDocument() + expect(within(dialog).getByRole('heading', { name: 'Acknowledgments' })).toBeInTheDocument() + expect(within(dialog).getByRole('link', { name: 'Laurent Haan' })).toHaveAttribute('href', 'https://www.haan.lu') + expect(within(dialog).getByRole('link', { name: 'GitHub Releases' })).toHaveAttribute('href', 'https://github.com/haan/modelizer/releases') + expect(dialog).toHaveTextContent('modelizer.bat') + expect(dialog).toHaveTextContent('Bob Fisch') + expect(within(dialog).getByRole('link', { name: 'ChartDB' })).toBeInTheDocument() + expect(within(dialog).getByRole('link', { name: 'miniserve' })).toBeInTheDocument() + for (const link of within(dialog).getAllByRole('link')) { + expect(link).toHaveAttribute('target', '_blank') + expect(link).toHaveAttribute('rel', 'noopener noreferrer') + } + await user.click(within(dialog).getByRole('button', { name: 'Close' })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() +}) diff --git a/src/components/dialogs/__tests__/ModelOpeningNotices.test.jsx b/src/components/dialogs/__tests__/ModelOpeningNotices.test.jsx new file mode 100644 index 0000000..84325d2 --- /dev/null +++ b/src/components/dialogs/__tests__/ModelOpeningNotices.test.jsx @@ -0,0 +1,118 @@ +import { cleanup, fireEvent, render, screen } from '@testing-library/react' +import { useState } from 'react' +import { afterEach, expect, it, vi } from 'vitest' +import FileErrorDialog from '../FileErrorDialog.jsx' +import ModelContentDialog from '../ModelContentDialog.jsx' + +afterEach(cleanup) + +it('explains that revealing compositions also enables their creation', () => { + const onReveal = vi.fn(), onDismiss = vi.fn() + render() + expect(screen.getByRole('dialog', { name: 'Enable composite aggregation?' })).toHaveTextContent('allow you to create them') + expect(onReveal).not.toHaveBeenCalled() + fireEvent.click(screen.getByRole('button', { name: 'Enable composite aggregation', exact: true })) + expect(onReveal.mock.calls).toEqual([['compositions']]) + expect(onDismiss).toHaveBeenCalledOnce() +}) + +it('distinguishes enabling composition from revealing other hidden content', () => { + const onReveal = vi.fn(), onDismiss = vi.fn() + render() + expect(screen.getByRole('dialog')).toHaveTextContent('notes and annotations hidden by your display settings') + expect(screen.getByRole('dialog')).toHaveTextContent('Composite aggregation is disabled.') + fireEvent.click(screen.getByRole('button', { name: 'Enable and show all' })) + expect(onReveal.mock.calls).toEqual([['notes'], ['compositions'], ['annotations']]) + expect(onDismiss).toHaveBeenCalledOnce() +}) + +it('leaves composition disabled when the feature prompt is declined', () => { + const onReveal = vi.fn(), onDismiss = vi.fn() + render() + fireEvent.click(screen.getByRole('button', { name: 'Keep disabled' })) + expect(onReveal).not.toHaveBeenCalled() + expect(onDismiss).toHaveBeenCalledOnce() +}) + +it('provides a persistent, actionable unsupported-format dialog with a separate close control', () => { + const onOpenChange = vi.fn() + render() + expect(screen.getByRole('dialog', { name: 'Newer Modelizer required' })).toBeInTheDocument() + expect(screen.getByText(/supports formats 1 and 2/)).toBeInTheDocument() + expect(screen.getByRole('link', { name: 'Open latest Modelizer' })).toHaveAttribute('href', 'https://www.modelizer.lu/') + fireEvent.click(screen.getByRole('button', { name: 'Close' })) + expect(onOpenChange).toHaveBeenCalledWith(false) +}) + +it('lists only hidden categories and reveals them together only after Show all', () => { + const onReveal = vi.fn(), onDismiss = vi.fn() + const report = { hiddenNotes: true, hiddenAreas: true, hiddenAnnotations: true, hiddenInConceptual: { classes: 1 }, annotationViews: ['logical'] } + render() + expect(onReveal).not.toHaveBeenCalled() + expect(screen.getByRole('dialog', { name: 'Show hidden content?' })).toBeInTheDocument() + expect(screen.getByText('This model contains notes and annotations hidden by your display settings.')).toBeInTheDocument() + expect(screen.queryByText(/Hidden in conceptual view/)).not.toBeInTheDocument() + fireEvent.click(screen.getByRole('button', { name: 'Show all' })) + expect(onReveal.mock.calls).toEqual([['notes'], ['annotations']]) + expect(onDismiss).toHaveBeenCalledOnce() +}) + +it('stays closed for intentional per-view visibility and clears reports resolved through settings', () => { + const onDismiss = vi.fn() + const renderNotice = (report, enabled = {}) => + const { rerender } = render(renderNotice({ hiddenInConceptual: { attributes: 7 }, annotationViews: ['logical'] })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() + rerender(renderNotice({ hiddenNotes: true })) + expect(screen.getByRole('dialog')).toBeInTheDocument() + rerender(renderNotice({ hiddenNotes: true }, { notes: true })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() + expect(onDismiss).toHaveBeenCalledOnce() +}) + +it('supports keyboard dismissal without changing display preferences', () => { + const onDismiss = vi.fn(), onReveal = vi.fn() + render() + fireEvent.keyDown(screen.getByRole('button', { name: 'Keep hidden' }), { key: 'Escape' }) + expect(onDismiss).toHaveBeenCalledOnce() + expect(onReveal).not.toHaveBeenCalled() +}) + +it('keeps settings unchanged when Keep hidden is chosen', () => { + const onDismiss = vi.fn(), onReveal = vi.fn() + render() + fireEvent.click(screen.getByRole('button', { name: 'Keep hidden' })) + expect(onDismiss).toHaveBeenCalledOnce() + expect(onReveal).not.toHaveBeenCalled() +}) + +it('never revives a resolved file-opening dialog but offers it again for a new file', () => { + function FileOpeningDialog() { + const [report, setReport] = useState({ hiddenNotes: true, hiddenAreas: true }) + const [enabled, setEnabled] = useState({}) + return <> + setReport(null)} + onReveal={setting => setEnabled(current => ({ ...current, [setting]: true }))} /> + + + + } + render() + fireEvent.click(screen.getByRole('button', { name: 'Show all' })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() + fireEvent.click(screen.getByRole('button', { name: 'Toggle notes in menu' })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() + fireEvent.click(screen.getByRole('button', { name: 'Open another file' })) + expect(screen.getByRole('dialog')).toBeInTheDocument() + fireEvent.click(screen.getByRole('button', { name: 'Keep hidden' })) + fireEvent.click(screen.getByRole('button', { name: 'Toggle notes in menu' })) + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() +}) + +it('clears resolved reports even while another dialog or view is active', () => { + const onDismiss = vi.fn() + render() + expect(onDismiss).toHaveBeenCalledOnce() + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() +}) diff --git a/src/components/flow/edges/Association.jsx b/src/components/flow/edges/Association.jsx index 55b7b1b..3b01b57 100644 --- a/src/components/flow/edges/Association.jsx +++ b/src/components/flow/edges/Association.jsx @@ -1,43 +1,12 @@ +import { getEndpointLabelTransform, getRoleLabelTransform } from '../utils/associationLabelTransforms.js' import { EdgeLabelRenderer, useInternalNode } from '@xyflow/react' import { AssociationLabel } from '../labels/AssociationLabel.jsx' import { MultiplicityLabel } from '../labels/MultiplicityLabel.jsx' import { RoleLabel } from '../labels/RoleLabel.jsx' import { getAssociationLayout } from '../utils/associationUtils.js' import { EdgeControlPoints } from './EdgeControlPoints.jsx' - -function getEndpointLabelTransform(position, x, y) { - const offset = 0 - - switch (position) { - case 'left': - return `translate(-100%, 0%) translate(${x - offset}px, ${y + 1}px)` - case 'right': - return `translate(0%, 0%) translate(${x + offset}px, ${y + 1}px)` - case 'top': - return `translate(0%, -100%) translate(${x + 1}px, ${y - offset}px)` - case 'bottom': - return `translate(0%, 0%) translate(${x + 1}px, ${y + offset}px)` - default: - return `translate(-50%, -50%) translate(${x}px, ${y}px)` - } -} - -function getRoleLabelTransform(position, x, y) { - const offset = 0 - - switch (position) { - case 'left': - return `translate(-100%, -100%) translate(${x - offset}px, ${y - 1}px)` - case 'right': - return `translate(0%, -100%) translate(${x + offset}px, ${y - 1}px)` - case 'top': - return `translate(-100%, -100%) translate(${x - 1}px, ${y - offset}px)` - case 'bottom': - return `translate(-100%, 0%) translate(${x - 1}px, ${y + offset}px)` - default: - return `translate(-50%, -50%) translate(${x}px, ${y}px)` - } -} +import { useParallelLabels } from './useParallelLabels.js' +import { useAssociationAnchors } from './useAssociationAnchors.js' export function Association({ id, @@ -51,7 +20,9 @@ export function Association({ const sourceNode = useInternalNode(source) const targetNode = useInternalNode(target) - const layout = getAssociationLayout(sourceNode, targetNode, data) + const anchors = useAssociationAnchors(id) + const layout = getAssociationLayout(sourceNode, targetNode, data, anchors) + const parallelLabels = useParallelLabels(id, source, target, data, sourceNode, targetNode, layout) if (!layout) { return null } @@ -138,7 +109,8 @@ export function Association({ ) : null} {name ? ( ) : null} diff --git a/src/components/flow/edges/AssociativeAssociation.jsx b/src/components/flow/edges/AssociativeAssociation.jsx index 8be7aae..f86f9d4 100644 --- a/src/components/flow/edges/AssociativeAssociation.jsx +++ b/src/components/flow/edges/AssociativeAssociation.jsx @@ -1,7 +1,27 @@ -import { getStraightPath } from '@xyflow/react' +import { getStraightPath, useStore } from '@xyflow/react' +import { getAssociationLayout } from '../utils/associationUtils.js' +import { getReflexiveAssociationLayout } from '../utils/reflexiveAssociationUtils.js' +import { getAssociationAnchorsFromState } from './useAssociationAnchors.js' + +function getAttachment(state, helperId) { + if (!helperId?.startsWith('assoc-edge-')) return null + const base = state.edges.find(edge => edge.id === helperId.slice('assoc-edge-'.length)) + if (!base) return null + const sourceNode = state.nodeLookup.get(base.source) + if (base.type === 'reflexiveAssociation') { + return getReflexiveAssociationLayout(sourceNode, base.data)?.helperAnchor ?? null + } + const layout = getAssociationLayout(sourceNode, state.nodeLookup.get(base.target), base.data, + getAssociationAnchorsFromState(state, base.id)) + return layout ? { x: layout.labelX, y: layout.labelY } : null +} + +const samePoint = (a, b) => a?.x === b?.x && a?.y === b?.y export function AssociativeAssociation({ id, + source, + target, sourceX, sourceY, sourceHandle, @@ -12,6 +32,10 @@ export function AssociativeAssociation({ markerEnd, selected, }) { + // Derive attachment from the rendered path too: offscreen exports remeasure + // classes locally and may not share the editor's helper-node coordinates. + const sourceAttachment = useStore(state => getAttachment(state, source), samePoint) + const targetAttachment = useStore(state => getAttachment(state, target), samePoint) const sourceSide = sourceHandle?.split('-')[0] ?? (sourcePosition ?? '').toString() const sourceOffsets = { @@ -23,10 +47,10 @@ export function AssociativeAssociation({ const { x: sourceOffsetX = 0, y: sourceOffsetY = 0 } = sourceOffsets[sourceSide] ?? {} const [edgePath] = getStraightPath({ - sourceX: sourceX + sourceOffsetX, - sourceY: sourceY + sourceOffsetY, - targetX, - targetY: targetY + 8, + sourceX: sourceAttachment?.x ?? sourceX + sourceOffsetX, + sourceY: sourceAttachment?.y ?? sourceY + sourceOffsetY, + targetX: targetAttachment?.x ?? targetX, + targetY: targetAttachment?.y ?? targetY + 8, }) const strokeClass = selected ? 'text-primary' : 'text-base-content/70' diff --git a/src/components/flow/edges/Composition.jsx b/src/components/flow/edges/Composition.jsx index fbe8d24..54fc954 100644 --- a/src/components/flow/edges/Composition.jsx +++ b/src/components/flow/edges/Composition.jsx @@ -1,26 +1,12 @@ +import { getEndpointLabelTransform } from '../utils/associationLabelTransforms.js' import { EdgeLabelRenderer, useInternalNode } from '@xyflow/react' import { AssociationLabel } from '../labels/AssociationLabel.jsx' import { MultiplicityLabel } from '../labels/MultiplicityLabel.jsx' import { getAssociationLayout } from '../utils/associationUtils.js' import { ASSOCIATION_LINE_STYLE_STRAIGHT } from '../../../model/constants.js' import { EdgeControlPoints } from './EdgeControlPoints.jsx' - -function getEndpointLabelTransform(position, x, y) { - const offset = 0 - - switch (position) { - case 'left': - return `translate(-100%, 0%) translate(${x - offset}px, ${y + 1}px)` - case 'right': - return `translate(0%, 0%) translate(${x + offset}px, ${y + 1}px)` - case 'top': - return `translate(0%, -100%) translate(${x + 1}px, ${y - offset}px)` - case 'bottom': - return `translate(0%, 0%) translate(${x + 1}px, ${y + offset}px)` - default: - return `translate(-50%, -50%) translate(${x}px, ${y}px)` - } -} +import { useParallelLabels } from './useParallelLabels.js' +import { useAssociationAnchors } from './useAssociationAnchors.js' export function Composition({ id, @@ -34,7 +20,9 @@ export function Composition({ const sourceNode = useInternalNode(source) const targetNode = useInternalNode(target) - const layout = getAssociationLayout(sourceNode, targetNode, data) + const anchors = useAssociationAnchors(id) + const layout = getAssociationLayout(sourceNode, targetNode, data, anchors) + const parallelLabels = useParallelLabels(id, source, target, data, sourceNode, targetNode, layout) if (!layout) { return null } @@ -185,7 +173,8 @@ export function Composition({ ) : null} {name ? ( ) : null} diff --git a/src/components/flow/edges/__tests__/parallelLabels.test.jsx b/src/components/flow/edges/__tests__/parallelLabels.test.jsx new file mode 100644 index 0000000..5e1b4e0 --- /dev/null +++ b/src/components/flow/edges/__tests__/parallelLabels.test.jsx @@ -0,0 +1,82 @@ +import { cleanup, render, screen } from '@testing-library/react' +import { createPortal } from 'react-dom' +import { afterEach, describe, expect, it, vi } from 'vitest' +import { Association } from '../Association.jsx' +import { Composition } from '../Composition.jsx' +import { AssociativeAssociation } from '../AssociativeAssociation.jsx' +import { getAssociationEndpointAllocations, getAssociationLayout } from '../../utils/associationUtils.js' + +const flow = vi.hoisted(() => ({ edges: [], nodes: { + a: { position: { x: 0, y: 0 }, measured: { width: 188, height: 80 } }, + b: { position: { x: 400, y: 0 }, measured: { width: 188, height: 80 } }, +} })) +vi.mock('@xyflow/react', async importOriginal => ({ + ...await importOriginal(), + useStore: selector => selector({ ...flow, nodeLookup: new Map(Object.entries(flow.nodes)) }), + useInternalNode: id => flow.nodes[id], + useReactFlow: () => ({}), + EdgeLabelRenderer: ({ children }) => createPortal(children, document.body), +})) +afterEach(cleanup) + +it('attaches a dashed association-class link to the allocated path despite stale helper coordinates', () => { + const nodes = { ...flow.nodes, upper: { position: { x: 0, y: -150 }, measured: { width: 188, height: 80 } } } + flow.nodes = nodes + flow.edges = [ + { id: 'base', type: 'association', source: 'a', target: 'b', data: { lineStyle: 'orthogonal' } }, + { id: 'other', type: 'association', source: 'upper', target: 'b', data: { lineStyle: 'orthogonal' } }, + ] + const allocations = getAssociationEndpointAllocations(flow.edges, id => nodes[id]) + const layout = getAssociationLayout(nodes.a, nodes.b, flow.edges[0].data, allocations.get('base')) + const { container } = render() + const coordinates = container.querySelector('#dashed').getAttribute('d').match(/-?\d+(?:\.\d+)?/g).map(Number) + expect(coordinates.slice(-2)).toEqual([layout.labelX, layout.labelY]) +}) + +describe.each([['association', Association], ['composition', Composition]])('%s parallel labels', (type, Component) => { + it('keeps upper endpoint labels in their familiar positions when the peer changes mode', () => { + const first = { id: 'one', source: 'a', target: 'b', type, data: { + parallelCount: 2, parallelIndex: 0, lineStyle: 'orthogonal', + name: 'Full association name', multiplicityA: '0..*', multiplicityB: '1..1', + roleA: 'Full source role', roleB: 'Full target role', + } } + flow.edges = [first, { id: 'two', source: 'b', target: 'a', type: 'association', + data: { parallelCount: 2, parallelIndex: 1, lineStyle: 'orthogonal' } }] + const { rerender, container } = render() + const path = container.querySelector('.react-flow__edge-path').getAttribute('d') + const multiplicityTransform = screen.getByText('0..*').style.transform + expect(multiplicityTransform).toContain('translate(0%, 0%)') + const roleTransform = type === 'association' ? screen.getByText('Full source role').style.transform : null + if (roleTransform) expect(roleTransform).toContain('translate(0%, -100%)') + expect(screen.getByText('Full association name')).toHaveClass('whitespace-nowrap') + + flow.edges = [first, { ...flow.edges[1], data: { ...flow.edges[1].data, lineStyle: 'straight' } }] + rerender() + expect(screen.getByText('0..*').style.transform).toBe(multiplicityTransform) + if (roleTransform) expect(screen.getByText('Full source role').style.transform).toBe(roleTransform) + expect(screen.getByText('Full association name')).not.toHaveClass('whitespace-nowrap') + expect(container.querySelector('.react-flow__edge-path').getAttribute('d')).toBe(path) + }) + + it('keeps the lower roles aligned at the class, including with reversed endpoints', () => { + const first = { id: 'one', source: 'a', target: 'b', type, data: { + parallelCount: 2, parallelIndex: 1, lineStyle: 'orthogonal', + roleA: 'source role', roleB: 'target role', multiplicityA: '0..*', + } } + flow.edges = [first, { id: 'two', source: 'b', target: 'a', type: 'association', + data: { parallelCount: 2, parallelIndex: 0, lineStyle: 'orthogonal', + multiplicityA: 'target neighbour', multiplicityB: 'source neighbour' } }] + const { rerender } = render() + expect(screen.queryByText('source neighbour')).toBeNull() + expect(screen.queryByText('target neighbour')).toBeNull() + if (type === 'association') { + expect(screen.getByText('source role').style.transform).toContain('translate(0%, -100%)') + expect(screen.getByText('target role').style.transform).toContain('translate(-100%, -100%)') + } + flow.edges = [first, { ...flow.edges[1], data: { ...flow.edges[1].data, lineStyle: 'manual' } }] + rerender() + expect(screen.queryByText('source neighbour')).toBeNull() + expect(screen.queryByText('target neighbour')).toBeNull() + }) +}) diff --git a/src/components/flow/edges/useAssociationAnchors.js b/src/components/flow/edges/useAssociationAnchors.js new file mode 100644 index 0000000..955b54c --- /dev/null +++ b/src/components/flow/edges/useAssociationAnchors.js @@ -0,0 +1,20 @@ +import { useStore } from '@xyflow/react' +import { getAssociationEndpointAllocations } from '../utils/associationUtils.js' + +// All edge components share one allocation per React Flow store snapshot. +// A WeakMap avoids retaining old snapshots and keeps separate export canvases isolated. +const allocations = new WeakMap() + +export function getAssociationAnchorsFromState(state, id) { + if (!allocations.has(state)) { + allocations.set(state, getAssociationEndpointAllocations(state.edges, key => state.nodeLookup.get(key))) + } + return allocations.get(state).get(id) +} + +const samePoint = (a, b) => a?.x === b?.x && a?.y === b?.y +const sameAnchors = (a, b) => samePoint(a?.source, b?.source) && samePoint(a?.target, b?.target) + +export function useAssociationAnchors(id) { + return useStore(state => getAssociationAnchorsFromState(state, id), sameAnchors) +} diff --git a/src/components/flow/edges/useParallelLabels.js b/src/components/flow/edges/useParallelLabels.js new file mode 100644 index 0000000..9d433d0 --- /dev/null +++ b/src/components/flow/edges/useParallelLabels.js @@ -0,0 +1,31 @@ +import { useStore } from '@xyflow/react' +import { getAssociationLayout } from '../utils/associationUtils.js' +import { getOrthogonalPeer, getParallelLabelPlacement } from '../utils/parallelLabelUtils.js' +import { useAssociationAnchors } from './useAssociationAnchors.js' + +export function useParallelLabels(id, source, target, data, sourceNode, targetNode, layout) { + const peer = useStore(state => data?.parallelCount === 2 + ? getOrthogonalPeer(state.edges, id, source, target) + : null) + const peerAnchors = useAssociationAnchors(peer?.id) + if (!peer || !layout) return null + const reversed = peer.source !== source + const peerLayout = getAssociationLayout( + reversed ? targetNode : sourceNode, + reversed ? sourceNode : targetNode, + peer.data, + peerAnchors, + ) + if (!peerLayout) return null + // Compare endpoints at the same class, even when source/target are reversed. + const alignedPeer = reversed ? { + ...peerLayout, + sourceX: peerLayout.targetX, + sourceY: peerLayout.targetY, + sourcePos: peerLayout.targetPos, + targetX: peerLayout.sourceX, + targetY: peerLayout.sourceY, + targetPos: peerLayout.sourcePos, + } : peerLayout + return getParallelLabelPlacement(layout, alignedPeer) +} diff --git a/src/components/flow/labels/AssociationLabel.jsx b/src/components/flow/labels/AssociationLabel.jsx index 3c73287..bf218b1 100644 --- a/src/components/flow/labels/AssociationLabel.jsx +++ b/src/components/flow/labels/AssociationLabel.jsx @@ -1,8 +1,9 @@ export function AssociationLabel({ transform, label, className = '' }) { return (
{label}
diff --git a/src/components/flow/labels/AssociationLabelMask.jsx b/src/components/flow/labels/AssociationLabelMask.jsx new file mode 100644 index 0000000..8e5d962 --- /dev/null +++ b/src/components/flow/labels/AssociationLabelMask.jsx @@ -0,0 +1,16 @@ +import { useId, useLayoutEffect, useRef } from 'react' +import { observeAssociationLabelMask } from './associationLabelMask.js' + +export default function AssociationLabelMask() { + const id = `association-label-mask-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}` + const svgRef = useRef(null) + const maskRef = useRef(null) + + useLayoutEffect(() => observeAssociationLabelMask(svgRef.current, maskRef.current, id), [id]) + + return +} diff --git a/src/components/flow/labels/__tests__/associationLabelMask.test.jsx b/src/components/flow/labels/__tests__/associationLabelMask.test.jsx new file mode 100644 index 0000000..6dd6a5d --- /dev/null +++ b/src/components/flow/labels/__tests__/associationLabelMask.test.jsx @@ -0,0 +1,157 @@ +import { act, cleanup, render } from '@testing-library/react' +import { afterEach, beforeEach, expect, it, vi } from 'vitest' +import { AssociationLabel } from '../AssociationLabel.jsx' +import AssociationLabelMask from '../AssociationLabelMask.jsx' +import { prepareAssociationLabelsForExport, refreshAssociationLabelMasks } from '../associationLabelMask.js' +import { toSvg } from 'html-to-image' + +let zoom, pan, labelBounds, observers +const bounds = (x, y, width, height) => ({ left: x, top: y, width, height, right: x + width, bottom: y + height }) +const screenRect = rect => bounds(pan.x + rect.x * zoom, pan.y + rect.y * zoom, rect.width * zoom, rect.height * zoom) + +function Canvas({ name = 'records', transform = 'translate(-50%, -100%) translate(-100px, 80px)', showLabel = true }) { + return
+
+ + {['association', 'composition', 'reflexiveAssociation', 'associativeAssociation', 'relationship'].map(type => + + + + )} + +
+ {showLabel && } +
+
+ +
+} + +beforeEach(() => { + zoom = 1; pan = { x: 0, y: 0 } + labelBounds = { x: -140, y: 61, width: 80, height: 18 } + observers = [] + vi.stubGlobal('ResizeObserver', class { + constructor(callback) { this.callback = callback; this.elements = new Set(); observers.push(this) } + observe(element) { this.elements.add(element) } + unobserve(element) { this.elements.delete(element) } + disconnect() { this.elements.clear() } + }) + vi.spyOn(HTMLElement.prototype, 'offsetWidth', 'get').mockReturnValue(1000) + vi.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(function () { + if (this.matches('.react-flow__viewport')) return screenRect({ x: 0, y: 0, width: 1000, height: 800 }) + if (this.matches('[data-association-label]')) return screenRect(labelBounds) + return screenRect({ x: -100, y: -200, width: 0, height: 500 }) + }) +}) +afterEach(() => { cleanup(); vi.restoreAllMocks(); vi.unstubAllGlobals() }) + +it('cuts all conceptual strokes behind the name without painting a label background or masking hit targets', () => { + const { container } = render() + const mask = container.querySelector('mask') + expect(mask).toHaveAttribute('maskUnits', 'userSpaceOnUse') + expect(mask).toHaveAttribute('y', '-232') + expect(mask).toHaveAttribute('height', '564') + expect(mask.querySelector('rect[fill="black"]')).toHaveAttribute('x', '-140') + expect(mask.querySelector('rect[fill="black"]')).toHaveAttribute('height', '18') + for (const path of container.querySelectorAll('.react-flow__edge-path')) { + if (path.closest('.react-flow__edge-relationship')) expect(path).not.toHaveAttribute('mask') + else expect(path).toHaveAttribute('mask', `url(#${mask.id})`) + } + for (const path of container.querySelectorAll('.react-flow__edge-interaction')) expect(path).not.toHaveAttribute('mask') + const label = container.querySelector('[data-association-label]') + expect(label.className).not.toMatch(/bg-|backdrop|shadow/) + // A name ending at y=79 must not erase a horizontal line at y=80. + const hole = mask.querySelector('rect[fill="black"]') + expect(Number(hole.getAttribute('y')) + Number(hole.getAttribute('height'))).toBe(79) +}) + +it.each([0.25, 1, 3])('keeps flow-space gaps unchanged under zoom %s and pan, including negative coordinates', scale => { + zoom = scale; pan = { x: 350, y: -80 } + const { container } = render() + const hole = container.querySelector('rect[fill="black"]') + expect(hole).toHaveAttribute('x', '-140') + expect(hole).toHaveAttribute('y', '61') + expect(hole).toHaveAttribute('width', '80') + expect(hole).toHaveAttribute('height', '18') +}) + +it('updates moved and renamed labels, observes font/size changes, and removes obsolete gaps', async () => { + const { container, rerender } = render() + labelBounds = { x: -300, y: 200, width: 300, height: 36 } + rerender() + await act(async () => {}) + expect(container.querySelector('rect[fill="black"]')).toHaveAttribute('width', '300') + expect(container.querySelector('rect[fill="black"]')).toHaveAttribute('y', '200') + labelBounds.width = 320 + act(() => observers[0].callback()) + expect(container.querySelector('rect[fill="black"]')).toHaveAttribute('width', '320') + rerender() + await act(async () => {}) + expect(container.querySelector('rect[fill="black"]')).toBeNull() + expect(container.querySelector('.react-flow__edge-path')).not.toHaveAttribute('mask') + expect(observers[0].elements.size).toBe(1) // Only the viewport remains observed. +}) + +it('isolates simultaneous editor/export canvases and flushes measurements synchronously for capture', () => { + const editor = render() + labelBounds = { x: 80, y: 100, width: 100, height: 18 } + const exported = render() + const editorMask = editor.container.querySelector('mask') + const exportMask = exported.container.querySelector('mask') + expect(editorMask.id).not.toBe(exportMask.id) + labelBounds.width = 200 + refreshAssociationLabelMasks(exported.container) + expect(exportMask.querySelector('rect[fill="black"]')).toHaveAttribute('width', '200') + expect(editorMask.querySelector('rect[fill="black"]')).toHaveAttribute('width', '80') + exported.unmount() + expect(observers[1].elements.size).toBe(0) + expect(editor.container.querySelector('.react-flow__edge-path')).toHaveAttribute('mask', `url(#${editorMask.id})`) +}) + +it('preserves label clipping through the real html-to-image serializer instead of embedding a local mask URL', async () => { + vi.stubGlobal('SVGImageElement', class SVGImageElement {}) // Absent in jsdom; this fixture has no SVG images. + const { container } = render() + const sourceStyle = window.getComputedStyle.bind(window) + vi.spyOn(window, 'getComputedStyle').mockImplementation((element, pseudo) => { + if (pseudo) { + const style = document.createElement('span').style + style.setProperty('content', 'none') + return style + } + // jsdom does not resolve SVG presentation attributes into computed CSS. + // Supply the mask/clip CSS that browsers expose to html-to-image. + if (element.matches('.react-flow__edge-path')) { + const style = document.createElement('span').style + style.setProperty('stroke', 'rgb(80, 90, 100)') + if (element.hasAttribute('mask')) style.setProperty('mask-image', element.getAttribute('mask')) + if (element.hasAttribute('clip-path')) style.setProperty('clip-path', element.getAttribute('clip-path')) + return style + } + return sourceStyle(element) + }) + const fetchMock = vi.fn(async () => ({ status: 200, headers: { get: () => 'text/html' }, + blob: async () => new Blob(['Modelizer'], { type: 'text/html' }) })) + vi.stubGlobal('fetch', fetchMock) + const options = { skipFonts: true, width: 1000, height: 800 } + const broken = decodeURIComponent(await toSvg(container, options)) + expect(fetchMock).toHaveBeenCalledWith(expect.stringMatching(/^#association-label-mask-/), undefined) + const brokenXml = new DOMParser().parseFromString(broken.slice(broken.indexOf(' x > rect.x && x < rect.x + rect.width && y > rect.y && y < rect.y + rect.height + +it('keeps horizontal and vertical strokes visible except inside label gaps, including overlaps', () => { + const bounds = { x: -200, y: -200, width: 400, height: 500 } + const holes = [ + { x: -100, y: -20, width: 120, height: 18 }, + { x: -50, y: -10, width: 120, height: 18 }, + { x: 0, y: 100, width: 60, height: 18 }, + ] + const visible = getLabelClipRects(bounds, holes) + // Compare every pixel centre against the union, not a second clipping algorithm. + for (let y = -199.5; y < 300; y++) { + for (let x = -199.5; x < 200; x++) { + if (visible.some(rect => contains(rect, x, y)) !== !holes.some(rect => contains(rect, x, y))) { + throw new Error(`Incorrect clipping at ${x}, ${y}`) + } + } + } + expect(visible.some(rect => contains(rect, -25, -5))).toBe(false) +}) + +it('supports empty, duplicate, enclosing and partially out-of-bounds labels', () => { + const bounds = { x: 0, y: 0, width: 100, height: 100 } + expect(getLabelClipRects(bounds, [])).toEqual([bounds]) + expect(getLabelClipRects(bounds, [{ x: -10, y: -10, width: 120, height: 120 }])).toEqual([]) + const hole = { x: -10, y: -10, width: 60, height: 60 } + expect(getLabelClipRects(bounds, [hole, hole])).toEqual([ + { x: 50, y: 0, width: 50, height: 50 }, { x: 0, y: 50, width: 100, height: 50 }, + ]) +}) diff --git a/src/components/flow/labels/associationLabelMask.js b/src/components/flow/labels/associationLabelMask.js new file mode 100644 index 0000000..365f1cd --- /dev/null +++ b/src/components/flow/labels/associationLabelMask.js @@ -0,0 +1,117 @@ +import { getLabelClipRects } from './labelClipRects.js' + +const SVG_NS = 'http://www.w3.org/2000/svg' +const refreshers = new WeakMap() +const strokeSelector = ['association', 'composition', 'reflexiveAssociation', 'associativeAssociation'] + .map(type => `.react-flow__edge-${type} .react-flow__edge-path`).join(',') + +// Export calls this synchronously after its final viewport/size adjustment. +// Masks and measurements belong to this canvas, never to persisted model data. +export function refreshAssociationLabelMasks(container) { + container.querySelectorAll('[data-association-label-mask]').forEach(element => refreshers.get(element)?.refresh()) +} + +// html-to-image 1.11.11 embeds CSS mask URLs as external images, including +// local SVG fragments. Use equivalent vector clipping in the export canvas; +// clip-path references are left intact by its resource-embedding step. +export function prepareAssociationLabelsForExport(container) { + container.querySelectorAll('[data-association-label-mask]').forEach(svg => { + const observer = refreshers.get(svg) + observer?.refresh() + observer?.stop() + const mask = svg.querySelector('mask') + if (!mask?.children.length) return + const readRect = rect => Object.fromEntries(['x', 'y', 'width', 'height'].map(key => [key, Number(rect.getAttribute(key))])) + const rects = getLabelClipRects(readRect(mask), [...mask.querySelectorAll('rect[fill="black"]')].map(readRect)) + const clip = document.createElementNS(SVG_NS, 'clipPath') + clip.id = `${mask.id}-export` + clip.setAttribute('clipPathUnits', 'userSpaceOnUse') + const outline = document.createElementNS(SVG_NS, 'path') + outline.setAttribute('d', rects.map(({ x, y, width, height }) => `M${x},${y}h${width}v${height}h${-width}Z`).join('')) + clip.appendChild(outline) + mask.parentNode.appendChild(clip) + container.querySelectorAll(strokeSelector).forEach(path => { + if (path.getAttribute('mask') !== `url(#${mask.id})`) return + path.removeAttribute('mask') + path.setAttribute('clip-path', `url(#${clip.id})`) + }) + }) +} + +export function observeAssociationLabelMask(svg, mask, id) { + const viewport = svg.closest('.react-flow')?.querySelector('.react-flow__viewport') + if (!viewport) return + const observed = new Set() + let maskedPaths = new Set() + let previousGeometry = '' + const maskUrl = `url(#${id})` + const clearPath = path => { + if (path.getAttribute('mask') === maskUrl) path.removeAttribute('mask') + } + const refresh = () => { + const origin = viewport.getBoundingClientRect() + const zoom = origin.width / viewport.offsetWidth + if (!Number.isFinite(zoom) || zoom <= 0) return + + const labels = new Set(viewport.querySelectorAll('[data-association-label]')) + for (const element of observed) { + if (!labels.has(element)) { resizeObserver.unobserve(element); observed.delete(element) } + } + for (const element of labels) { + if (!observed.has(element)) { observed.add(element); resizeObserver.observe(element) } + } + + const toFlowRect = element => { + const rect = element.getBoundingClientRect() + return { x: (rect.left - origin.left) / zoom, y: (rect.top - origin.top) / zoom, + width: rect.width / zoom, height: rect.height / zoom } + } + // The label already has horizontal padding and a full text line box. + // Extra vertical padding would cut lines immediately below horizontal names. + const holes = [...labels].map(toFlowRect).filter(rect => rect.width > 0 && rect.height > 0) + const paths = new Set(holes.length ? viewport.querySelectorAll(strokeSelector) : []) + for (const path of maskedPaths) if (!paths.has(path)) clearPath(path) + for (const path of paths) if (path.getAttribute('mask') !== maskUrl) path.setAttribute('mask', maskUrl) + maskedPaths = paths + + if (!paths.size) { + mask.replaceChildren() + previousGeometry = '' + return + } + + // Explicit user-space bounds also work for perfectly horizontal/vertical + // paths, whose object bounding box has a zero dimension. Include negative + // coordinates and leave ample room for strokes/markers at the extremes. + const rects = [...paths].map(toFlowRect).concat(holes) + const x = Math.min(...rects.map(rect => rect.x)) - 32 + const y = Math.min(...rects.map(rect => rect.y)) - 32 + const width = Math.max(...rects.map(rect => rect.x + rect.width)) + 32 - x + const height = Math.max(...rects.map(rect => rect.y + rect.height)) + 32 - y + const geometry = JSON.stringify([x, y, width, height, holes]) + if (geometry === previousGeometry) return + previousGeometry = geometry + for (const [key, value] of Object.entries({ x, y, width, height })) mask.setAttribute(key, value) + const makeRect = (bounds, fill) => { + const rect = document.createElementNS(SVG_NS, 'rect') + for (const [key, value] of Object.entries({ ...bounds, fill })) rect.setAttribute(key, value) + return rect + } + mask.replaceChildren(makeRect({ x, y, width, height }, 'white'), ...holes.map(rect => makeRect(rect, 'black'))) + } + const resizeObserver = new ResizeObserver(refresh) + const mutations = new MutationObserver(refresh) + // Mask definitions live outside the viewport. Updating them cannot trigger + // this observer; mask attributes on strokes are deliberately excluded too. + mutations.observe(viewport, { subtree: true, childList: true, characterData: true, + attributes: true, attributeFilter: ['transform', 'style', 'class', 'd'] }) + resizeObserver.observe(viewport) + const stop = () => { mutations.disconnect(); resizeObserver.disconnect() } + refreshers.set(svg, { refresh, stop }) + refresh() + return () => { + stop() + refreshers.delete(svg) + maskedPaths.forEach(clearPath) + } +} diff --git a/src/components/flow/labels/labelClipRects.js b/src/components/flow/labels/labelClipRects.js new file mode 100644 index 0000000..38abc3a --- /dev/null +++ b/src/components/flow/labels/labelClipRects.js @@ -0,0 +1,23 @@ +// Decompose the area outside the union of label rectangles into disjoint bands. +// Unlike even-odd holes, overlapping labels never restore a piece of the line. +export function getLabelClipRects(bounds, holes) { + const right = bounds.x + bounds.width + const bottom = bounds.y + bounds.height + const clipped = holes.map(rect => ({ + x: Math.max(bounds.x, rect.x), y: Math.max(bounds.y, rect.y), + right: Math.min(right, rect.x + rect.width), bottom: Math.min(bottom, rect.y + rect.height), + })).filter(rect => rect.right > rect.x && rect.bottom > rect.y) + const rows = [...new Set([bounds.y, bottom, ...clipped.flatMap(rect => [rect.y, rect.bottom])])].sort((a, b) => a - b) + const result = [] + for (let i = 1; i < rows.length; i++) { + const y = rows[i - 1], height = rows[i] - y + const intervals = clipped.filter(rect => rect.y < rows[i] && rect.bottom > y).sort((a, b) => a.x - b.x) + let x = bounds.x + for (const interval of intervals) { + if (interval.x > x) result.push({ x, y, width: interval.x - x, height }) + x = Math.max(x, interval.right) + } + if (x < right) result.push({ x, y, width: right - x, height }) + } + return result +} diff --git a/src/components/flow/utils/__tests__/associationEndpointAllocations.test.js b/src/components/flow/utils/__tests__/associationEndpointAllocations.test.js new file mode 100644 index 0000000..8c7e657 --- /dev/null +++ b/src/components/flow/utils/__tests__/associationEndpointAllocations.test.js @@ -0,0 +1,84 @@ +import { describe, expect, it } from 'vitest' +import { getAssociationEndpointAllocations, getAssociationLayout } from '../associationUtils.js' + +const node = (id, x, y, width = 180, height = 180) => ({ + id, type: 'class', position: { x, y }, measured: { width, height }, +}) +const edge = (id, source, target, data = {}) => ({ id, source, target, type: 'association', data: { lineStyle: 'orthogonal', ...data } }) +const allocate = (nodes, edges) => getAssociationEndpointAllocations(edges, id => nodes.find(n => n.id === id)) + +describe('shared class-border allocation', () => { + it.each(['left', 'right', 'top', 'bottom'])('keeps %s slots spaced and ordered as distance increases', side => { + const horizontal = side === 'left' || side === 'right' + const sign = side === 'left' || side === 'top' ? -1 : 1 + const nodes = [node('hub', 0, 0, 400, 180), ...[-1, 0, 1].map((i, j) => + node(`remote-${j}`, horizontal ? sign * 1000 : 110 + i * 300, horizontal ? i * 250 : sign * 1000, 180, 77))] + // Reverse one association: the ordering must not depend on edge direction. + const edges = [edge('a', 'remote-0', 'hub'), edge('b', 'hub', 'remote-1'), edge('c', 'remote-2', 'hub')] + const before = JSON.stringify([nodes, edges]) + const first = allocate(nodes, edges) + const moved = nodes.map(n => n.id === 'hub' ? n : { ...n, position: { + x: n.position.x + (horizontal ? sign * 1600 : 0), + y: n.position.y + (horizontal ? 0 : sign * 1600), + } }) + const second = allocate(moved, edges) + const slots = edges.map(e => first.get(e.id)[e.source === 'hub' ? 'source' : 'target']) + const spacing = horizontal ? 42 : 120 + expect(slots[1][horizontal ? 'y' : 'x'] - slots[0][horizontal ? 'y' : 'x']).toBe(spacing) + expect(slots[2][horizontal ? 'y' : 'x'] - slots[1][horizontal ? 'y' : 'x']).toBe(spacing) + edges.forEach(e => { + const endpoint = e.source === 'hub' ? 'source' : 'target' + expect(second.get(e.id)[endpoint]).toEqual(first.get(e.id)[endpoint]) + const layout = getAssociationLayout(nodes.find(n => n.id === e.source), nodes.find(n => n.id === e.target), e.data, first.get(e.id)) + expect(layout[endpoint + 'Pos']).toBe(side) + expect(layout[endpoint + 'X']).toBe(first.get(e.id)[endpoint].x) + expect(layout[endpoint + 'Y']).toBe(first.get(e.id)[endpoint].y) + }) + expect(JSON.stringify([nodes, edges])).toBe(before) + }) + + it('allocates parallel and other neighbours together with deterministic ordering', () => { + const nodes = [node('hub', 600, 0), node('upper', 0, -200), node('middle', 0, 0), node('lower', 0, 200)] + const edges = [edge('upper', 'upper', 'hub'), + edge('middle-a', 'middle', 'hub', { parallelIndex: 0, parallelCount: 2 }), + edge('middle-b', 'hub', 'middle', { parallelIndex: 1, parallelCount: 2 }), edge('lower', 'lower', 'hub')] + const result = allocate(nodes, edges) + expect(edges.map(e => result.get(e.id)[e.source === 'hub' ? 'source' : 'target'].y)).toEqual([27, 69, 111, 153]) + const reversed = allocate(nodes, [...edges].reverse().map(e => ({ ...e, source: e.target, target: e.source }))) + edges.forEach(e => expect(reversed.get(e.id).source).toEqual(result.get(e.id).target)) + }) + + it('compresses crowded borders without merging endpoints or resizing classes', () => { + const nodes = [node('hub', 1000, 0, 180, 77), ...Array.from({ length: 8 }, (_, i) => node(`n${i}`, 0, -300 + i * 90))] + const edges = nodes.slice(1).map(n => edge(n.id, n.id, 'hub')) + const result = allocate(nodes, edges) + const slots = edges.map(e => result.get(e.id).target) + expect(new Set(slots.map(p => p.y)).size).toBe(8) + expect(slots[0].x).toBe(1000) + expect(slots[0].y).toBeCloseTo(8) + expect(slots.at(-1).x).toBe(1000) + expect(slots.at(-1).y).toBeCloseTo(69) + expect(nodes[0].measured.height).toBe(77) + }) + + it('excludes hidden, straight, manual and reflexive edges from automatic slots', () => { + const nodes = [node('hub', 600, 0), node('remote', 0, 0)] + const first = edge('one', 'remote', 'hub') + for (const other of [ + { ...edge('two', 'remote', 'hub'), hidden: true }, + edge('two', 'remote', 'hub', { lineStyle: 'straight' }), + edge('two', 'remote', 'hub', { lineStyle: 'manual' }), + edge('two', 'remote', 'hub', { controlPoints: [{ x: 200, y: 100 }] }), + { ...edge('two', 'hub', 'hub'), type: 'reflexiveAssociation' }, + ]) expect(allocate(nodes, [first, other]).size).toBe(0) + }) + + it('includes compositions and recomputes ordering after a neighbour moves', () => { + const nodes = [node('hub', 700, 0), node('upper', 0, -100), node('lower', 0, 100)] + const edges = [edge('a', 'upper', 'hub'), { ...edge('b', 'lower', 'hub'), type: 'composition' }] + const first = allocate(nodes, edges) + const moved = allocate(nodes.map(n => n.id === 'upper' ? { ...n, position: { x: 0, y: 200 } } : n), edges) + expect(first.get('a').target.y).toBeLessThan(first.get('b').target.y) + expect(moved.get('a').target.y).toBeGreaterThan(moved.get('b').target.y) + }) +}) diff --git a/src/components/flow/utils/__tests__/parallelAssociationLayout.test.js b/src/components/flow/utils/__tests__/parallelAssociationLayout.test.js new file mode 100644 index 0000000..51a63e5 --- /dev/null +++ b/src/components/flow/utils/__tests__/parallelAssociationLayout.test.js @@ -0,0 +1,146 @@ +import { describe, expect, it } from 'vitest' +import { getAssociationLayout } from '../associationUtils.js' + +// Exercise the installed React Flow path helpers, without mocking their routing. +const node = (x, y, width, height) => ({ + internals: { positionAbsolute: { x, y } }, measured: { width, height }, +}) +const layouts = (source, target, count, lineStyle) => Array.from({ length: count }, (_, parallelIndex) => + getAssociationLayout(source, target, { parallelCount: count, parallelIndex, lineStyle })) + +function expectAttached(layout, endpoint, target) { + const x = layout[`${endpoint}X`] + const y = layout[`${endpoint}Y`] + const side = layout[`${endpoint}Pos`] + const position = target.internals.positionAbsolute + const { width, height } = target.measured + expect(x).toBeGreaterThanOrEqual(position.x) + expect(x).toBeLessThanOrEqual(position.x + width) + expect(y).toBeGreaterThanOrEqual(position.y) + expect(y).toBeLessThanOrEqual(position.y + height) + if (side === 'left') expect(x).toBe(position.x) + if (side === 'right') expect(x).toBe(position.x + width) + if (side === 'top') expect(y).toBe(position.y) + if (side === 'bottom') expect(y).toBe(position.y + height) +} + +describe.each(['straight', 'orthogonal'])('parallel %s associations', (lineStyle) => { + it.each([ + ['staggered small classes', node(27, 206, 188, 79), node(423, 44, 189, 80), 2], + ['mixed bottom and left sides', node(0, 0, 180, 80), node(220, 50, 180, 200), 2], + ['crowded horizontal classes', node(0, 0, 180, 77), node(400, 0, 180, 77), 5], + ['crowded vertical classes', node(0, 0, 180, 77), node(0, 400, 180, 77), 12], + ['unequal heights near horizontal snap', node(-200, -100, 180, 77), node(200, -155, 180, 200), 5], + ['unequal widths near vertical snap', node(-100, -200, 180, 77), node(-155, 200, 300, 77), 12], + ])('keeps distinct endpoints on borders for %s', (_name, source, target, count) => { + const group = layouts(source, target, count, lineStyle) + const reverse = layouts(target, source, count, lineStyle) + for (const [index, layout] of group.entries()) { + expectAttached(layout, 'source', source) + expectAttached(layout, 'target', target) + expect(layout.edgePath).not.toMatch(/NaN|undefined/) + const coordinates = layout.edgePath.match(/-?\d+(?:\.\d+)?(?:e[+-]?\d+)?/gi).map(Number) + expect(coordinates.slice(0, 2)).toEqual([layout.sourceX, layout.sourceY]) + expect(coordinates.slice(-2)).toEqual([layout.targetX, layout.targetY]) + expect(reverse[index].targetX).toBeCloseTo(layout.sourceX) + expect(reverse[index].targetY).toBeCloseTo(layout.sourceY) + expect(reverse[index].sourceX).toBeCloseTo(layout.targetX) + expect(reverse[index].sourceY).toBeCloseTo(layout.targetY) + } + expect(new Set(group.map(l => `${l.sourceX},${l.sourceY}`)).size).toBe(count) + expect(new Set(group.map(l => `${l.targetX},${l.targetY}`)).size).toBe(count) + }) + + it('uses the preferred spacing when both class borders have room', () => { + const group = layouts(node(0, 0, 180, 200), node(400, 0, 180, 200), 3, lineStyle) + const spacing = lineStyle === 'orthogonal' ? 42 : 25 + expect(group.map(l => l.sourceY)).toEqual([100 - spacing, 100, 100 + spacing]) + expect(group.map(l => l.targetY)).toEqual([100 - spacing, 100, 100 + spacing]) + }) + + it('keeps mixed-face lane ordering consistent', () => { + const group = layouts(node(0, 0, 180, 80), node(220, 50, 180, 200), 3, lineStyle) + expect(group[0].sourceX).toBeGreaterThan(group[1].sourceX) + expect(group[1].sourceX).toBeGreaterThan(group[2].sourceX) + expect(group[0].targetY).toBeLessThan(group[1].targetY) + expect(group[1].targetY).toBeLessThan(group[2].targetY) + }) +}) + +it('does not redistribute manually routed endpoints', () => { + const source = node(0, 0, 180, 77) + const target = node(400, 0, 180, 77) + const data = { lineStyle: 'manual', controlPoints: [{ x: 280, y: 100 }] } + expect(getAssociationLayout(source, target, { ...data, parallelIndex: 0, parallelCount: 5 })) + .toEqual(getAssociationLayout(source, target, data)) +}) + +describe('two default orthogonal connections on minimum classes', () => { + it.each([ + ['horizontal', node(0, 0, 180, 77), node(500, 0, 180, 77), 'Y', 42], + ['vertical', node(0, 0, 180, 77), node(0, 350, 180, 77), 'X', 120], + ['staggered horizontal', node(0, 0, 180, 77), node(500, 125, 180, 77), 'Y', 42], + ['staggered vertical', node(0, 0, 180, 77), node(130, 350, 180, 77), 'X', 120], + ])('provides label room without changing node dimensions: %s', (_name, source, target, axis, spacing) => { + const before = JSON.stringify([source, target]) + const group = layouts(source, target, 2, 'orthogonal') + for (const endpoint of ['source', 'target']) { + expect(Math.abs(group[1][endpoint + axis] - group[0][endpoint + axis])).toBeCloseTo(spacing) + } + group.forEach(layout => { + expectAttached(layout, 'source', source) + expectAttached(layout, 'target', target) + }) + expect(JSON.stringify([source, target])).toBe(before) + }) + + it('retains the existing 25px spacing for straight groups', () => { + const source = node(0, 0, 180, 77) + const target = node(500, 0, 180, 77) + for (const count of [2, 3]) { + const group = layouts(source, target, count, 'straight') + expect(group[1].sourceY - group[0].sourceY).toBe(25) + } + }) +}) + +describe('readable spacing for larger orthogonal groups', () => { + it.each([ + ['three on tall classes', 180, 160, 3, 'Y', 42], + ['four on tall classes', 180, 160, 4, 'Y', 42], + ['three on minimum classes', 180, 77, 3, 'Y', 30.5], + ['six on minimum classes', 180, 77, 6, 'Y', 12.2], + ['three on wide classes', 300, 77, 3, 'X', 120], + ['three on minimum-width classes', 180, 77, 3, 'X', 82], + ])('%s use the largest spacing up to the readable default', (_name, width, height, count, axis, spacing) => { + const source = node(-200, -100, width, height) + const target = axis === 'Y' ? node(400, -100, width, height) : node(-200, 400, width, height) + const group = layouts(source, target, count, 'orthogonal') + group.forEach((layout, i) => { + expectAttached(layout, 'source', source) + expectAttached(layout, 'target', target) + if (i > 0) { + expect(layout['source' + axis] - group[i - 1]['source' + axis]).toBeCloseTo(spacing) + expect(layout['target' + axis] - group[i - 1]['target' + axis]).toBeCloseTo(spacing) + } + }) + }) + + it('compresses only the endpoint whose class has insufficient space', () => { + const group = layouts(node(0, 0, 180, 77), node(500, -41.5, 180, 160), 3, 'orthogonal') + expect(group.map(l => l.sourceY)).toEqual([8, 38.5, 69]) + expect(group.map(l => l.targetY)).toEqual([-3.5, 38.5, 80.5]) + }) + + it('leaves room between neighbouring role and multiplicity rows on tall classes', () => { + const group = layouts(node(0, 0, 180, 160), node(500, 0, 180, 160), 3, 'orthogonal') + for (const endpoint of ['source', 'target']) { + for (let i = 1; i < group.length; i++) { + // Existing 18px label line height, with a 1px offset on either side. + const previousMultiplicityBottom = group[i - 1][endpoint + 'Y'] + 1 + 18 + const nextRoleTop = group[i][endpoint + 'Y'] - 1 - 18 + expect(nextRoleTop - previousMultiplicityBottom).toBeGreaterThanOrEqual(4) + } + } + }) +}) diff --git a/src/components/flow/utils/__tests__/parallelLabelUtils.test.js b/src/components/flow/utils/__tests__/parallelLabelUtils.test.js new file mode 100644 index 0000000..9eb5f36 --- /dev/null +++ b/src/components/flow/utils/__tests__/parallelLabelUtils.test.js @@ -0,0 +1,105 @@ +import { describe, expect, it } from 'vitest' +import { getAssociationLayout } from '../associationUtils.js' +import { getOrthogonalPeer, getParallelLabelPlacement } from '../parallelLabelUtils.js' +import { getEndpointLabelTransform, getRoleLabelTransform } from '../associationLabelTransforms.js' + +const node = (x, y, width = 188, height = 80) => ({ position: { x, y }, measured: { width, height } }) +const edge = (id, parallelIndex, data = {}) => ({ + id, source: 'a', target: 'b', type: 'association', + data: { parallelCount: 2, parallelIndex, lineStyle: 'orthogonal', ...data }, +}) + +// Resolve CSS percentage translations against representative label dimensions. +// These are geometry checks, not a substitute for browser/font verification. +function bounds(transform, width, height) { + const [px, py, x, y] = transform.match(/-?\d+(?:\.\d+)?/g).map(Number) + return { left: x + px * width / 100, top: y + py * height / 100, + right: x + px * width / 100 + width, bottom: y + py * height / 100 + height } +} +function overlaps(a, b) { + return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom +} + +describe('two orthogonal associations', () => { + it.each([ + ['horizontal', node(0, 0, 180, 77), node(500, 0, 180, 77)], + ['vertical', node(0, 0, 180, 77), node(0, 350, 180, 77)], + ['staggered sideways down', node(0, 0, 180, 77), node(500, 125, 180, 77)], + ['staggered sideways up', node(0, 0, 180, 77), node(500, -125, 180, 77)], + ['staggered vertically right', node(0, 0, 180, 77), node(130, 350, 180, 77)], + ['staggered vertically left', node(0, 0, 180, 77), node(-130, 350, 180, 77)], + ])('fits two names, four roles and four multiplicities on minimum classes: %s', (_name, source, target) => { + const layouts = [0, 1].map(i => getAssociationLayout(source, target, edge(String(i), i).data)) + const boxes = layouts.flatMap((layout, i) => { + const placement = getParallelLabelPlacement(layout, layouts[1 - i]) + const endpointBoxes = ['source', 'target'].flatMap(endpoint => { + const args = [layout[endpoint + 'Pos'], layout[endpoint + 'X'], layout[endpoint + 'Y']] + return [ + bounds(getEndpointLabelTransform(...args), 32, 18), + bounds(getRoleLabelTransform(...args), 80, 18), + ] + }) + return [...endpointBoxes, bounds(placement.nameTransform, 120, 18)] + }) + boxes.forEach((box, i) => boxes.slice(i + 1).forEach(other => expect(overlaps(box, other)).toBe(false))) + }) + + it.each([ + ['vertical middle, upwards', node(16, 155), node(492, 30)], + ['vertical middle, downwards', node(16, 30), node(492, 155)], + ['horizontal middle, rightwards', node(0, 0), node(130, 350)], + ['horizontal middle, leftwards', node(0, 0), node(-130, 350)], + ['aligned horizontally', node(0, 0), node(400, 0)], + ['aligned vertically', node(0, 0), node(0, 350)], + ['negative coordinates, unequal heights', node(-400, -300, 180, 77), node(0, -200, 180, 130)], + ])('separates names and preserves endpoint anchors: %s', (_name, source, target) => { + const layouts = [0, 1].map(i => getAssociationLayout(source, target, edge(String(i), i).data)) + const placements = layouts.map((l, i) => getParallelLabelPlacement(l, layouts[1 - i])) + expect(placements.every(Boolean)).toBe(true) + const names = placements.map(p => bounds(p.nameTransform, 160, 18)) + expect(overlaps(...names)).toBe(false) + const reverse = [0, 1].map(i => getAssociationLayout(target, source, edge(String(i), i).data)) + reverse.forEach((layout, i) => { + const placement = getParallelLabelPlacement(layout, reverse[1 - i]) + expect(placement.nameTransform).toBe(placements[i].nameTransform) + }) + }) + + it('leaves mixed-face and manual geometry alone', () => { + for (const [source, target, data] of [ + [node(0, 0, 180), node(220, 50, 180, 200), {}], + [node(0, 0), node(400, 0), { lineStyle: 'manual' }], + ]) { + const layouts = [0, 1].map(i => getAssociationLayout(source, target, edge(String(i), i, data).data)) + expect(getParallelLabelPlacement(...layouts)).toBeNull() + } + }) +}) + +describe('orthogonal pair eligibility', () => { + it('includes a reversed peer and composition without changing the edges', () => { + const first = edge('one', 0) + const second = { ...edge('two', 1), source: 'b', target: 'a', type: 'composition' } + const edges = [first, second] + const before = JSON.stringify(edges) + expect(getOrthogonalPeer(edges, 'one', 'a', 'b')).toBe(second) + expect(JSON.stringify(edges)).toBe(before) + }) + + it.each([ + { lineStyle: 'straight' }, { lineStyle: 'manual' }, + { controlPoints: [{ x: 300, y: 100 }] }, { parallelCount: 3 }, + ])('leaves mixed routes or larger groups alone: %j', data => { + const first = edge('one', 0) + const second = edge('two', 1, data) + expect(getOrthogonalPeer([first, second], 'one', 'a', 'b')).toBeNull() + expect(getOrthogonalPeer([first, second], 'two', 'a', 'b')).toBeNull() + }) + + it('does not pair hidden edges, single associations or larger groups', () => { + const first = edge('one', 0) + expect(getOrthogonalPeer([first], 'one', 'a', 'b')).toBeNull() + expect(getOrthogonalPeer([first, { ...edge('two', 1), hidden: true }], 'one', 'a', 'b')).toBeNull() + expect(getOrthogonalPeer([first, edge('two', 1), edge('three', 2)], 'one', 'a', 'b')).toBeNull() + }) +}) diff --git a/src/components/flow/utils/associationLabelTransforms.js b/src/components/flow/utils/associationLabelTransforms.js new file mode 100644 index 0000000..f0d24b7 --- /dev/null +++ b/src/components/flow/utils/associationLabelTransforms.js @@ -0,0 +1,33 @@ +export function getEndpointLabelTransform(position, x, y) { + const offset = 0 + + switch (position) { + case 'left': + return `translate(-100%, 0%) translate(${x - offset}px, ${y + 1}px)` + case 'right': + return `translate(0%, 0%) translate(${x + offset}px, ${y + 1}px)` + case 'top': + return `translate(0%, -100%) translate(${x + 1}px, ${y - offset}px)` + case 'bottom': + return `translate(0%, 0%) translate(${x + 1}px, ${y + offset}px)` + default: + return `translate(-50%, -50%) translate(${x}px, ${y}px)` + } +} + +export function getRoleLabelTransform(position, x, y) { + const offset = 0 + + switch (position) { + case 'left': + return `translate(-100%, -100%) translate(${x - offset}px, ${y - 1}px)` + case 'right': + return `translate(0%, -100%) translate(${x + offset}px, ${y - 1}px)` + case 'top': + return `translate(-100%, -100%) translate(${x - 1}px, ${y - offset}px)` + case 'bottom': + return `translate(-100%, 0%) translate(${x - 1}px, ${y + offset}px)` + default: + return `translate(-50%, -50%) translate(${x}px, ${y}px)` + } +} diff --git a/src/components/flow/utils/associationUtils.js b/src/components/flow/utils/associationUtils.js index f83666a..e13757b 100644 --- a/src/components/flow/utils/associationUtils.js +++ b/src/components/flow/utils/associationUtils.js @@ -2,9 +2,18 @@ import { Position, getSmoothStepPath, getStraightPath } from '@xyflow/react' import { ASSOCIATION_LINE_STYLE_MANUAL, ASSOCIATION_LINE_STYLE_STRAIGHT, + ASSOCIATION_EDGE_TYPE, + COMPOSITION_EDGE_TYPE, } from '../../../model/constants.js' const PARALLEL_OFFSET_SPACING = 25 +// Prefer readable separation for automatic orthogonal groups; each endpoint +// compresses the entire group only when its class border has insufficient room. +// Side labels need two text rows; top/bottom labels need horizontal text room. +const ORTHOGONAL_SIDE_SPACING = 42 +const ORTHOGONAL_TOP_BOTTOM_SPACING = 120 +const ORTHOGONAL_STEP_SPACING = -24 +const PARALLEL_CORNER_CLEARANCE = 8 const STEP_SHIFT_SPACING = -20 const SNAP_AXIS_THRESHOLD = 10 const MANUAL_STUB_LENGTH = 18 @@ -185,17 +194,23 @@ function isHorizontalConnection(sourcePos, targetPos) { ) } -function getParallelLineOffset(parallelOffset, isHorizontal) { - if (parallelOffset === 0) { - return { offsetX: 0, offsetY: 0 } - } - - const offsetDistance = parallelOffset * PARALLEL_OFFSET_SPACING - - return { - offsetX: isHorizontal ? 0 : offsetDistance, - offsetY: isHorizontal ? offsetDistance : 0, - } +function getParallelAnchor(node, side, x, y, count, offset, direction, preferredSpacing) { + const position = getNodePosition(node) + const measured = getNodeMeasured(node) + const width = Math.max(measured.width, 1) + const height = Math.max(measured.height, 1) + const isSideEdge = side === Position.Left || side === Position.Right + const length = isSideEdge ? height : width + const start = isSideEdge ? position.y : position.x + const clearance = Math.min(PARALLEL_CORNER_CLEARANCE, length / 4) + const spacing = Math.min(preferredSpacing, (length - 2 * clearance) / (count - 1)) + const halfSpan = spacing * (count - 1) / 2 + // Fit the entire group, rather than clamping individual endpoints together. + const center = clamp(isSideEdge ? y : x, start + clearance + halfSpan, start + length - clearance - halfSpan) + const alongEdge = center + offset * spacing * direction + return isSideEdge + ? { x: side === Position.Left ? position.x : position.x + width, y: alongEdge } + : { x: alongEdge, y: side === Position.Top ? position.y : position.y + height } } function getPositionSign(sourceCenter, targetCenter, isHorizontal) { @@ -361,7 +376,53 @@ export function getPolylineMidpointByLength(points) { return { x: lastPoint.x, y: lastPoint.y } } -export function getAssociationLayout(sourceNode, targetNode, data) { +// Allocate all automatic endpoints sharing a class border together. No model +// metadata is written: slots follow current measurements and visible edges. +export function getAssociationEndpointAllocations(edges, getNode) { + const borders = new Map() + for (const edge of edges) { + if (edge.hidden || ![ASSOCIATION_EDGE_TYPE, COMPOSITION_EDGE_TYPE].includes(edge.type) || + edge.source === edge.target || edge.data?.lineStyle === ASSOCIATION_LINE_STYLE_STRAIGHT || + edge.data?.lineStyle === ASSOCIATION_LINE_STYLE_MANUAL || normalizeControlPoints(edge.data?.controlPoints).length) continue + const source = getNode(edge.source), target = getNode(edge.target) + if (!source || !target || source.hidden || target.hidden) continue + const params = getEdgeParams(source, target) + const horizontal = isHorizontalConnection(params.sourcePos, params.targetPos) + const sign = getPositionSign(getNodeCenter(source), getNodeCenter(target), horizontal) + for (const [endpoint, nodeId, node, otherId, other, side] of [ + ['source', edge.source, source, edge.target, target, params.sourcePos], + ['target', edge.target, target, edge.source, source, params.targetPos], + ]) { + const key = JSON.stringify([nodeId, side]) + const sideEdge = side === Position.Left || side === Position.Right + const direction = horizontal && !sideEdge ? -sign : 1 + const entry = { edgeId: edge.id, endpoint, node, side, otherId, + order: getNodeCenter(other)[sideEdge ? 'y' : 'x'], + lane: (edge.data?.parallelIndex ?? 0) * direction } + if (!borders.has(key)) borders.set(key, []) + borders.get(key).push(entry) + } + } + const result = new Map() + for (const entries of borders.values()) { + if (entries.length < 2) continue + entries.sort((a, b) => a.order - b.order || String(a.otherId).localeCompare(String(b.otherId)) || + a.lane - b.lane || String(a.edgeId).localeCompare(String(b.edgeId))) + const first = entries[0] + const center = getNodeCenter(first.node) + const preferred = first.side === Position.Left || first.side === Position.Right + ? ORTHOGONAL_SIDE_SPACING : ORTHOGONAL_TOP_BOTTOM_SPACING + entries.forEach((entry, index) => { + const anchor = getParallelAnchor(entry.node, entry.side, center.x, center.y, + entries.length, index - (entries.length - 1) / 2, 1, preferred) + if (!result.has(entry.edgeId)) result.set(entry.edgeId, {}) + result.get(entry.edgeId)[entry.endpoint] = anchor + }) + } + return result +} + +export function getAssociationLayout(sourceNode, targetNode, data, anchors) { if (!sourceNode || !targetNode) { return null } @@ -424,13 +485,20 @@ export function getAssociationLayout(sourceNode, targetNode, data) { sourceNode, targetNode, ) - const { parallelOffset } = getParallelMeta(data) + const { parallelOffset, parallelCount } = getParallelMeta(data) const isHorizontal = isHorizontalConnection(sourcePos, targetPos) - const { offsetX, offsetY } = getParallelLineOffset(parallelOffset, isHorizontal) - let sourceXOffset = sx + offsetX - let sourceYOffset = sy + offsetY - let targetXOffset = tx + offsetX - let targetYOffset = ty + offsetY + const isStraightLine = data?.lineStyle === ASSOCIATION_LINE_STYLE_STRAIGHT + const oppositeSides = { + left: Position.Right, right: Position.Left, top: Position.Bottom, bottom: Position.Top, + } + const isOrthogonalGroup = parallelCount > 1 && !isStraightLine && oppositeSides[sourcePos] === targetPos + const preferredSpacing = isOrthogonalGroup + ? (isHorizontal ? ORTHOGONAL_SIDE_SPACING : ORTHOGONAL_TOP_BOTTOM_SPACING) + : PARALLEL_OFFSET_SPACING + let sourceXOffset = sx + let sourceYOffset = sy + let targetXOffset = tx + let targetYOffset = ty const sourceCenter = getNodeCenter(sourceNode) const targetCenter = getNodeCenter(targetNode) const deltaX = Math.abs(sourceCenter.x - targetCenter.x) @@ -455,9 +523,31 @@ export function getAssociationLayout(sourceNode, targetNode, data) { targetXOffset = avgX } + if (parallelCount > 1) { + // Each endpoint follows its own border, including mixed side/top connections. + // Reverse horizontal-border ordering for mixed faces so lanes do not cross. + const directionFor = (side) => isHorizontal && (side === Position.Top || side === Position.Bottom) + ? -positionSign : 1 + const sourceAnchor = getParallelAnchor(sourceNode, sourcePos, sourceXOffset, sourceYOffset, + parallelCount, parallelOffset, directionFor(sourcePos), preferredSpacing) + const targetAnchor = getParallelAnchor(targetNode, targetPos, targetXOffset, targetYOffset, + parallelCount, parallelOffset, directionFor(targetPos), preferredSpacing) + sourceXOffset = sourceAnchor.x + sourceYOffset = sourceAnchor.y + targetXOffset = targetAnchor.x + targetYOffset = targetAnchor.y + } + + if (!isStraightLine && anchors) { + sourceXOffset = anchors.source?.x ?? sourceXOffset + sourceYOffset = anchors.source?.y ?? sourceYOffset + targetXOffset = anchors.target?.x ?? targetXOffset + targetYOffset = anchors.target?.y ?? targetYOffset + } + const stepShift = isPerfectHorizontal || isPerfectVertical ? 0 - : parallelOffset * STEP_SHIFT_SPACING * positionSign + : parallelOffset * (isOrthogonalGroup ? ORTHOGONAL_STEP_SPACING : STEP_SHIFT_SPACING) * positionSign const centerX = (sourceXOffset + targetXOffset) / 2 + (isHorizontal ? stepShift : 0) + @@ -466,7 +556,6 @@ export function getAssociationLayout(sourceNode, targetNode, data) { (sourceYOffset + targetYOffset) / 2 + (isHorizontal ? 0 : stepShift) + (snapHorizontal ? sourceCenter.y - targetCenter.y : 0) - const isStraightLine = data?.lineStyle === ASSOCIATION_LINE_STYLE_STRAIGHT let edgePath let labelX let labelY diff --git a/src/components/flow/utils/parallelLabelUtils.js b/src/components/flow/utils/parallelLabelUtils.js new file mode 100644 index 0000000..7542706 --- /dev/null +++ b/src/components/flow/utils/parallelLabelUtils.js @@ -0,0 +1,61 @@ +import { + ASSOCIATION_EDGE_TYPE, + COMPOSITION_EDGE_TYPE, + ASSOCIATION_LINE_STYLE_MANUAL, + ASSOCIATION_LINE_STYLE_STRAIGHT, +} from '../../../model/constants.js' + +const isAutomaticOrthogonal = (edge) => + edge.data?.lineStyle !== ASSOCIATION_LINE_STYLE_MANUAL && + edge.data?.lineStyle !== ASSOCIATION_LINE_STYLE_STRAIGHT && + !edge.data?.controlPoints?.length + +// Read the rendered edges, rather than persisting extra layout metadata in the model. +export function getOrthogonalPeer(edges, id, source, target) { + const group = edges.filter(edge => !edge.hidden && + (edge.type === ASSOCIATION_EDGE_TYPE || edge.type === COMPOSITION_EDGE_TYPE) && + ((edge.source === source && edge.target === target) || + (edge.source === target && edge.target === source))) + if (source === target || group.length !== 2 || !group.some(edge => edge.id === id) || + !group.every(edge => edge.data?.parallelCount === 2 && isAutomaticOrthogonal(edge))) { + return null + } + return group.find(edge => edge.id !== id) +} + +const isHorizontalSide = side => side === 'left' || side === 'right' +const oppositeSide = { left: 'right', right: 'left', top: 'bottom', bottom: 'top' } + +function middleOrientation(layout) { + // Mixed faces have an L bend rather than a shared middle segment. Leave these + // and user-routed edges to their existing label placement. + if (layout.isManualRouting || oppositeSide[layout.sourcePos] !== layout.targetPos) return null + if (isHorizontalSide(layout.sourcePos)) { + return Math.abs(layout.sourceY - layout.targetY) < 0.001 ? 'horizontal' : 'vertical' + } + return Math.abs(layout.sourceX - layout.targetX) < 0.001 ? 'vertical' : 'horizontal' +} + +export function getParallelLabelPlacement(layout, peer) { + if (!layout || !peer) return null + const orientation = middleOrientation(layout) + if (!orientation || orientation !== middleOrientation(peer)) return null + const horizontal = orientation === 'horizontal' + const delta = horizontal ? layout.labelY - peer.labelY : layout.labelX - peer.labelX + if (Math.abs(delta) < 0.001) return null + const outward = Math.sign(delta) + const x = layout.labelX + (horizontal ? 0 : outward * 2) + let y = layout.labelY - (horizontal ? 1 : 0) + if (!horizontal) { + // On staggered classes, keep both names in the shared vertical section, + // away from the other connection's endpoint labels when there is room. + const sharedStart = Math.max(Math.min(layout.sourceY, layout.targetY), Math.min(peer.sourceY, peer.targetY)) + const sharedEnd = Math.min(Math.max(layout.sourceY, layout.targetY), Math.max(peer.sourceY, peer.targetY)) + if (sharedEnd - sharedStart >= 42) y = (sharedStart + sharedEnd) / 2 + } + return { + nameTransform: horizontal + ? `translate(-50%, -100%) translate(${x}px, ${y}px)` + : `translate(${outward < 0 ? -100 : 0}%, -50%) translate(${x}px, ${y}px)`, + } +} diff --git a/src/components/layout/Navbar.jsx b/src/components/layout/Navbar.jsx index 85ebb44..d0a3023 100644 --- a/src/components/layout/Navbar.jsx +++ b/src/components/layout/Navbar.jsx @@ -2,8 +2,12 @@ import { useRef, useState } from 'react' import * as Menubar from '@radix-ui/react-menubar' import { CheckIcon, DotFilledIcon } from '@radix-ui/react-icons' import Input from '../ui/Input.jsx' +import ControlTooltip from '../ui/ControlTooltip.jsx' import { HelpDialog } from '../dialogs/HelpDialog.jsx' +const menuTriggerClass = + 'shrink-0 rounded-md px-2.5 py-2 text-sm font-medium text-base-content transition-colors hover:bg-base-200 data-[highlighted]:bg-base-200 data-[state=open]:bg-base-200 focus-visible:outline-2 focus-visible:outline-primary' + const choiceItemClass = 'relative cursor-pointer rounded-sm py-1 pl-6 pr-2 text-xs text-base-content transition-colors hover:bg-base-200 data-[highlighted]:bg-base-200 focus:outline-none' const indicatorClass = @@ -100,22 +104,22 @@ export default function Navbar({ return (