feat(companysetting): add writeonly column and mask values for GUI
This commit is contained in:
@@ -16,23 +16,24 @@ Returns a single company setting by key for the user's selected company.
|
|||||||
| `key` | `string` | The setting key. |
|
| `key` | `string` | The setting key. |
|
||||||
| `[options]` | `object` | Optional options. |
|
| `[options]` | `object` | Optional options. |
|
||||||
| `[options.frontendOnly]` | `boolean` | Only return the setting if it is frontend-visible. |
|
| `[options.frontendOnly]` | `boolean` | Only return the setting if it is frontend-visible. |
|
||||||
|
| `[options.maskWriteonly]` | `boolean` | Mask writeonly settings as '***'. Defaults to `frontendOnly` (usergui gets '***', backend gets full value). |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
|
|
||||||
`Promise<{key: string, value: string, frontend: boolean}|undefined>` — The setting, or `undefined` if not found.
|
`Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}|undefined>` — The setting, or `undefined` if not found.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const setting = await store.companysetting.get(42, 'theme');
|
const setting = await store.companysetting.get(42, 'ui.theme');
|
||||||
// => { key, value, frontend }
|
// => { key, value, frontend, writeonly }
|
||||||
```
|
```
|
||||||
|
|
||||||
## `companysetting.list`
|
## `companysetting.list`
|
||||||
|
|
||||||
*Source: `src/store/companysetting/list.js`*
|
*Source: `src/store/companysetting/list.js`*
|
||||||
|
|
||||||
Lists the settings of the user's selected company, optionally only frontend-visible ones.
|
Lists the settings of the user's selected company, optionally only frontend-visible ones. Write-only settings (such as `keys.tavily`, `keys.openrouter`) have their value masked with `'***'` by default for usergui presentation.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -41,23 +42,24 @@ Lists the settings of the user's selected company, optionally only frontend-visi
|
|||||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
| `[options]` | `object` | Optional options. |
|
| `[options]` | `object` | Optional options. |
|
||||||
| `[options.frontendOnly]` | `boolean` | Only return frontend-visible settings. |
|
| `[options.frontendOnly]` | `boolean` | Only return frontend-visible settings. |
|
||||||
|
| `[options.maskWriteonly]` | `boolean` | Whether to mask writeonly settings with '***'. Defaults to `true`. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
|
|
||||||
`Promise<Array<{key: string, value: string, frontend: boolean}>>` — The settings.
|
`Promise<Array<{key: string, value: string, frontend: boolean, writeonly: boolean}>>` — The settings.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const settings = await store.companysetting.list(42, { frontendOnly: true });
|
const settings = await store.companysetting.list(42, { frontendOnly: true });
|
||||||
// => [{ key, value, frontend }]
|
// => [{ key, value, frontend, writeonly }]
|
||||||
```
|
```
|
||||||
|
|
||||||
## `companysetting.set`
|
## `companysetting.set`
|
||||||
|
|
||||||
*Source: `src/store/companysetting/set.js`*
|
*Source: `src/store/companysetting/set.js`*
|
||||||
|
|
||||||
Sets (upserts) a company setting by key for the user's selected company. Only a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`, `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.
|
Sets (upserts) a company setting by key for the user's selected company. Only a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`, `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`. Keys in the write-only set (`keys.tavily`, `keys.openrouter`) are stored with `writeonly = 1`; when retrieved by the GUI the value is returned as `"***"`. The backend always receives the real value.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -68,10 +70,11 @@ Sets (upserts) a company setting by key for the user's selected company. Only a
|
|||||||
| `input.key` | `string` | The setting key (must be in the allow-list). |
|
| `input.key` | `string` | The setting key (must be in the allow-list). |
|
||||||
| `input.value` | `string` | The setting value. |
|
| `input.value` | `string` | The setting value. |
|
||||||
| `[input.frontend]` | `boolean` | Whether the setting is frontend-visible. |
|
| `[input.frontend]` | `boolean` | Whether the setting is frontend-visible. |
|
||||||
|
| `[input.writeonly]` | `boolean` | Whether the setting is write-only. Defaults to true for `keys.tavily` and `keys.openrouter`, false otherwise. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
|
|
||||||
`Promise<{key: string, value: string, frontend: boolean}>` — The upserted setting.
|
`Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}>` — The upserted setting.
|
||||||
|
|
||||||
**Throws**
|
**Throws**
|
||||||
|
|
||||||
@@ -81,5 +84,5 @@ Sets (upserts) a company setting by key for the user's selected company. Only a
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const setting = await store.companysetting.set(42, { key: 'ui.theme', value: 'dark' });
|
const setting = await store.companysetting.set(42, { key: 'ui.theme', value: 'dark' });
|
||||||
// => { key, value, frontend }
|
// => { key, value, frontend, writeonly }
|
||||||
```
|
```
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -160,13 +160,15 @@ Company-scoped key/value settings. Auth via selected company (`google_auth.selec
|
|||||||
|
|
||||||
| Method | Signature | Returns |
|
| Method | Signature | Returns |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `list` | `(googleAuthId, { frontendOnly? })` | `{ key, value, frontend }[]` |
|
| `list` | `(googleAuthId, { frontendOnly?, maskWriteonly? })` | `{ key, value, frontend, writeonly }[]` |
|
||||||
| `get` | `(googleAuthId, key, { frontendOnly? })` | `{ key, value, frontend } \| undefined` |
|
| `get` | `(googleAuthId, key, { frontendOnly?, maskWriteonly? })` | `{ key, value, frontend, writeonly } \| undefined` |
|
||||||
| `set` | `(googleAuthId, { key, value, frontend? })` | `{ key, value, frontend }` |
|
| `set` | `(googleAuthId, { key, value, frontend?, writeonly? })` | `{ key, value, frontend, writeonly }` |
|
||||||
|
|
||||||
- `value` is always a string (`NVARCHAR(MAX)`).
|
- `value` is always a string (`NVARCHAR(MAX)`).
|
||||||
- `frontend: true` → readable by frontend routes (`frontendOnly: true`). Default on `set` is `false` (backend-only).
|
- `frontend: true` → readable by frontend routes (`frontendOnly: true`). Default on `set` is `false` (backend-only).
|
||||||
- With `frontendOnly: true`, backend-only keys are omitted / `get` returns `undefined` (no leak via error type beyond missing).
|
- With `frontendOnly: true`, backend-only keys are omitted / `get` returns `undefined` (no leak via error type beyond missing).
|
||||||
|
- `writeonly: true` → usergui gets a `"***"` scrambled version when retrieving the key (in `list`, or in `get` when `maskWriteonly` is enabled / `frontendOnly: true`). The backend receives the full value.
|
||||||
|
- `keys.tavily` and `keys.openrouter` default to `writeonly: true` on `set`.
|
||||||
- `set` only allows a fixed allow-list of keys: `ui.theme`, `keys.tavily`, `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.
|
- `set` only allows a fixed allow-list of keys: `ui.theme`, `keys.tavily`, `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.
|
||||||
- No delete endpoint — settings are upsert / read only.
|
- No delete endpoint — settings are upsert / read only.
|
||||||
|
|
||||||
@@ -295,8 +297,8 @@ Maps articles to suppliers (`entity`) with purchase pricing, stock, packaging un
|
|||||||
| `article_id` | `INT` | FK → `article(id)` (`ON DELETE CASCADE`) |
|
| `article_id` | `INT` | FK → `article(id)` (`ON DELETE CASCADE`) |
|
||||||
| `entity_id` | `INT` | FK → `entity(id)` (`ON DELETE CASCADE`) |
|
| `entity_id` | `INT` | FK → `entity(id)` (`ON DELETE CASCADE`) |
|
||||||
| `price_id` | `INT` | FK → `price(id)` (`ON DELETE NO ACTION`), nullable |
|
| `price_id` | `INT` | FK → `price(id)` (`ON DELETE NO ACTION`), nullable |
|
||||||
| `SupplierSKU` | `NVARCHAR(100)` | Supplier's SKU code, nullable |
|
| `supplierSKU` | `NVARCHAR(100)` | Supplier's SKU code, nullable |
|
||||||
| `SupplierStock` | `FLOAT` | Stock available at supplier, nullable |
|
| `supplierStock` | `FLOAT` | Stock available at supplier, nullable |
|
||||||
| `pu` | `FLOAT` | Packaging unit (Verpackungseinheit), default `1` |
|
| `pu` | `FLOAT` | Packaging unit (Verpackungseinheit), default `1` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ digraph schema {
|
|||||||
entitycontact [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>entitycontact</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contacttype" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">contacttype</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contact" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">contact</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
entitycontact [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>entitycontact</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contacttype" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">contacttype</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contact" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">contact</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
syncpos [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>syncpos</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="paircode" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">paircode</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="token" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">token?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
syncpos [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>syncpos</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="paircode" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">paircode</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="token" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">token?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
entityhistory [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>entityhistory</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="companyuser_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>companyuser_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="text" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">text</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
entityhistory [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>entityhistory</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="companyuser_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>companyuser_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="text" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">text</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
companysetting [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>companysetting</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="frontend" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">frontend</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
companysetting [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>companysetting</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="frontend" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">frontend</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="writeonly" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">writeonly</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
google_auth [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>google_auth</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="selected_company" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>selected_company</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="email" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">email</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(320)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picture" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">picture?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(2048)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picturebinary" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">picturebinary?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">VARBINARY(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sub" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sub?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
google_auth [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>google_auth</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="selected_company" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>selected_company</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="email" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">email</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(320)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picture" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">picture?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(2048)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picturebinary" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">picturebinary?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">VARBINARY(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sub" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sub?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
}
|
}
|
||||||
subgraph cluster_i18n {
|
subgraph cluster_i18n {
|
||||||
@@ -43,7 +43,7 @@ digraph schema {
|
|||||||
articleean [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articleean</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="ean" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">ean</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
articleean [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articleean</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="ean" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">ean</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
articlelist [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlelist</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
articlelist [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlelist</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
articlelistarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlelistarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="articlelist_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>articlelist_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="count" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">count</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
articlelistarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlelistarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="articlelist_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>articlelist_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="count" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">count</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
articlesupplier [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlesupplier</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="price_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>price_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="SupplierSKU" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">SupplierSKU?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="SupplierStock" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">SupplierStock?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="pu" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">pu</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
articlesupplier [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>articlesupplier</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="price_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>price_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="SupplierSKU" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">SupplierSKU?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="supplierStock" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">supplierStock?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="pu" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">pu</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
optionslist [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>optionslist</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
optionslist [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#33415c" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>optionslist</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
optionslistarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>optionslistarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="optionslist_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>optionslist_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="count" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">count</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="mandated" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">mandated</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
optionslistarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#3f4c5f"><TR><TD COLSPAN="2" BGCOLOR="#33415c" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#e2e8f0" POINT-SIZE="12"><B>optionslistarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="optionslist_id" COLSPAN="2" BGCOLOR="#2b3a52" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9"><B>optionslist_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="count" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">count</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sort" COLSPAN="2" BGCOLOR="#2a3242" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">sort</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="mandated" COLSPAN="2" BGCOLOR="#272e3d" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#d8dee9">mandated</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#8b95a7" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -641,38 +641,42 @@
|
|||||||
<!-- companysetting -->
|
<!-- companysetting -->
|
||||||
<g id="node11" class="node">
|
<g id="node11" class="node">
|
||||||
<title>companysetting</title>
|
<title>companysetting</title>
|
||||||
<polygon fill="#33415c" stroke="none" points="4140.66,-673.6 4140.66,-698 4269.34,-698 4269.34,-673.6 4140.66,-673.6"/>
|
<polygon fill="#33415c" stroke="none" points="4140.66,-687 4140.66,-711.4 4269.34,-711.4 4269.34,-687 4140.66,-687"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-673.6 4140.66,-698 4269.34,-698 4269.34,-673.6 4140.66,-673.6"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-687 4140.66,-711.4 4269.34,-711.4 4269.34,-687 4140.66,-687"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4158.99" y="-683.2" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00" fill="#e2e8f0">companysetting</text>
|
<text xml:space="preserve" text-anchor="start" x="4158.99" y="-696.6" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00" fill="#e2e8f0">companysetting</text>
|
||||||
<polygon fill="#2b3a52" stroke="none" points="4140.66,-646.8 4140.66,-673.6 4269.34,-673.6 4269.34,-646.8 4140.66,-646.8"/>
|
<polygon fill="#2b3a52" stroke="none" points="4140.66,-660.2 4140.66,-687 4269.34,-687 4269.34,-660.2 4140.66,-660.2"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-646.8 4140.66,-673.6 4269.34,-673.6 4269.34,-646.8 4140.66,-646.8"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-660.2 4140.66,-687 4269.34,-687 4269.34,-660.2 4140.66,-660.2"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-657" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="14.00" fill="#d8dee9">id</text>
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-670.4" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="14.00" fill="#d8dee9">id</text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4234.84" y="-658.5" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">INT </text>
|
<text xml:space="preserve" text-anchor="start" x="4234.84" y="-671.9" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">INT </text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4251.84" y="-658.5" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="9.00" fill="#8b95a7">PK</text>
|
<text xml:space="preserve" text-anchor="start" x="4251.84" y="-671.9" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="9.00" fill="#8b95a7">PK</text>
|
||||||
<polygon fill="#2b3a52" stroke="none" points="4140.66,-620 4140.66,-646.8 4269.34,-646.8 4269.34,-620 4140.66,-620"/>
|
<polygon fill="#2b3a52" stroke="none" points="4140.66,-633.4 4140.66,-660.2 4269.34,-660.2 4269.34,-633.4 4140.66,-633.4"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-620 4140.66,-646.8 4269.34,-646.8 4269.34,-620 4140.66,-620"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-633.4 4140.66,-660.2 4269.34,-660.2 4269.34,-633.4 4140.66,-633.4"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-630.2" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="14.00" fill="#d8dee9">company_id</text>
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-643.6" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="14.00" fill="#d8dee9">company_id</text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4235.35" y="-631.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">INT </text>
|
<text xml:space="preserve" text-anchor="start" x="4235.35" y="-645.1" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">INT </text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4252.35" y="-631.7" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="9.00" fill="#8b95a7">FK</text>
|
<text xml:space="preserve" text-anchor="start" x="4252.35" y="-645.1" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="9.00" fill="#8b95a7">FK</text>
|
||||||
<polygon fill="#2a3242" stroke="none" points="4140.66,-593.2 4140.66,-620 4269.34,-620 4269.34,-593.2 4140.66,-593.2"/>
|
<polygon fill="#2a3242" stroke="none" points="4140.66,-606.6 4140.66,-633.4 4269.34,-633.4 4269.34,-606.6 4140.66,-606.6"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-593.2 4140.66,-620 4269.34,-620 4269.34,-593.2 4140.66,-593.2"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-606.6 4140.66,-633.4 4269.34,-633.4 4269.34,-606.6 4140.66,-606.6"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-601" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">key</text>
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-614.4" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">key</text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4192.83" y="-603" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">NVARCHAR(255)</text>
|
<text xml:space="preserve" text-anchor="start" x="4192.83" y="-616.4" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">NVARCHAR(255)</text>
|
||||||
<polygon fill="#272e3d" stroke="none" points="4140.66,-566.4 4140.66,-593.2 4269.34,-593.2 4269.34,-566.4 4140.66,-566.4"/>
|
<polygon fill="#272e3d" stroke="none" points="4140.66,-579.8 4140.66,-606.6 4269.34,-606.6 4269.34,-579.8 4140.66,-579.8"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-566.4 4140.66,-593.2 4269.34,-593.2 4269.34,-566.4 4140.66,-566.4"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-579.8 4140.66,-606.6 4269.34,-606.6 4269.34,-579.8 4140.66,-579.8"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-574.2" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">value</text>
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-587.6" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">value</text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4188.34" y="-576.2" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">NVARCHAR(MAX)</text>
|
<text xml:space="preserve" text-anchor="start" x="4188.34" y="-589.6" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">NVARCHAR(MAX)</text>
|
||||||
<polygon fill="#2a3242" stroke="none" points="4140.66,-539.6 4140.66,-566.4 4269.34,-566.4 4269.34,-539.6 4140.66,-539.6"/>
|
<polygon fill="#2a3242" stroke="none" points="4140.66,-553 4140.66,-579.8 4269.34,-579.8 4269.34,-553 4140.66,-553"/>
|
||||||
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-539.6 4140.66,-566.4 4269.34,-566.4 4269.34,-539.6 4140.66,-539.6"/>
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-553 4140.66,-579.8 4269.34,-579.8 4269.34,-553 4140.66,-553"/>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-547.4" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">frontend</text>
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-560.8" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">frontend</text>
|
||||||
<text xml:space="preserve" text-anchor="start" x="4250.34" y="-549.4" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">BIT</text>
|
<text xml:space="preserve" text-anchor="start" x="4250.34" y="-562.8" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">BIT</text>
|
||||||
|
<polygon fill="#272e3d" stroke="none" points="4140.66,-526.2 4140.66,-553 4269.34,-553 4269.34,-526.2 4140.66,-526.2"/>
|
||||||
|
<polygon fill="none" stroke="#3f4c5f" points="4140.66,-526.2 4140.66,-553 4269.34,-553 4269.34,-526.2 4140.66,-526.2"/>
|
||||||
|
<text xml:space="preserve" text-anchor="start" x="4145.66" y="-534" font-family="Helvetica,sans-Serif" font-size="14.00" fill="#d8dee9">writeonly</text>
|
||||||
|
<text xml:space="preserve" text-anchor="start" x="4250.34" y="-536" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#8b95a7">BIT</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- companysetting->company -->
|
<!-- companysetting->company -->
|
||||||
<g id="edge59" class="edge">
|
<g id="edge59" class="edge">
|
||||||
<title>companysetting:w->company:n</title>
|
<title>companysetting:w->company:n</title>
|
||||||
<g id="a_edge59"><a xlink:title="FK_companysetting_company">
|
<g id="a_edge59"><a xlink:title="FK_companysetting_company">
|
||||||
<path fill="none" stroke="#ff8f66" stroke-width="1.4" d="M4139.66,-633.4C4080.56,-633.4 4144.57,-544.43 4099,-506.8 3991.54,-418.07 3485.2,-565.62 3463.5,-438.57"/>
|
<path fill="none" stroke="#ff8f66" stroke-width="1.4" d="M4139.66,-646.8C4074.86,-646.8 4148.38,-548.75 4099,-506.8 3992.8,-416.57 3485.26,-565.56 3463.5,-438.57"/>
|
||||||
<polygon fill="#ff8f66" stroke="#ff8f66" stroke-width="1.4" points="3465.96,-438.69 3462.95,-431.91 3461.08,-439.09 3465.96,-438.69"/>
|
<polygon fill="#ff8f66" stroke="#ff8f66" stroke-width="1.4" points="3465.97,-438.69 3462.95,-431.91 3461.08,-439.09 3465.97,-438.69"/>
|
||||||
</a>
|
</a>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
@@ -536,8 +536,8 @@ BEGIN
|
|||||||
article_id INT NOT NULL,
|
article_id INT NOT NULL,
|
||||||
entity_id INT NOT NULL,
|
entity_id INT NOT NULL,
|
||||||
price_id INT NULL,
|
price_id INT NULL,
|
||||||
SupplierSKU NVARCHAR(100) NULL,
|
supplierSKU NVARCHAR(100) NULL,
|
||||||
SupplierStock FLOAT NULL,
|
supplierStock FLOAT NULL,
|
||||||
pu FLOAT NOT NULL CONSTRAINT DF_articlesupplier_pu DEFAULT 1,
|
pu FLOAT NOT NULL CONSTRAINT DF_articlesupplier_pu DEFAULT 1,
|
||||||
CONSTRAINT FK_articlesupplier_article FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE,
|
CONSTRAINT FK_articlesupplier_article FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE,
|
||||||
CONSTRAINT FK_articlesupplier_entity FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE,
|
CONSTRAINT FK_articlesupplier_entity FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE,
|
||||||
@@ -762,6 +762,7 @@ BEGIN
|
|||||||
[key] NVARCHAR(255) NOT NULL,
|
[key] NVARCHAR(255) NOT NULL,
|
||||||
value NVARCHAR(MAX) NOT NULL,
|
value NVARCHAR(MAX) NOT NULL,
|
||||||
frontend BIT NOT NULL CONSTRAINT DF_companysetting_frontend DEFAULT 0,
|
frontend BIT NOT NULL CONSTRAINT DF_companysetting_frontend DEFAULT 0,
|
||||||
|
writeonly BIT NOT NULL CONSTRAINT DF_companysetting_writeonly DEFAULT 0,
|
||||||
CONSTRAINT UQ_companysetting_company_key UNIQUE (company_id, [key]),
|
CONSTRAINT UQ_companysetting_company_key UNIQUE (company_id, [key]),
|
||||||
CONSTRAINT FK_companysetting_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
|
CONSTRAINT FK_companysetting_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ export const LIST_BY_COMPANY = `
|
|||||||
SELECT
|
SELECT
|
||||||
[key],
|
[key],
|
||||||
value,
|
value,
|
||||||
CAST(frontend AS INT) AS frontend
|
CAST(frontend AS INT) AS frontend,
|
||||||
|
CAST(writeonly AS INT) AS writeonly
|
||||||
FROM companysetting
|
FROM companysetting
|
||||||
WHERE company_id = @companyId
|
WHERE company_id = @companyId
|
||||||
ORDER BY [key]
|
ORDER BY [key]
|
||||||
@@ -12,7 +13,8 @@ export const LIST_BY_COMPANY_FRONTEND = `
|
|||||||
SELECT
|
SELECT
|
||||||
[key],
|
[key],
|
||||||
value,
|
value,
|
||||||
CAST(frontend AS INT) AS frontend
|
CAST(frontend AS INT) AS frontend,
|
||||||
|
CAST(writeonly AS INT) AS writeonly
|
||||||
FROM companysetting
|
FROM companysetting
|
||||||
WHERE company_id = @companyId
|
WHERE company_id = @companyId
|
||||||
AND frontend = 1
|
AND frontend = 1
|
||||||
@@ -23,7 +25,8 @@ export const GET_BY_COMPANY_AND_KEY = `
|
|||||||
SELECT
|
SELECT
|
||||||
[key],
|
[key],
|
||||||
value,
|
value,
|
||||||
CAST(frontend AS INT) AS frontend
|
CAST(frontend AS INT) AS frontend,
|
||||||
|
CAST(writeonly AS INT) AS writeonly
|
||||||
FROM companysetting
|
FROM companysetting
|
||||||
WHERE company_id = @companyId
|
WHERE company_id = @companyId
|
||||||
AND [key] = @key
|
AND [key] = @key
|
||||||
@@ -34,8 +37,8 @@ MERGE companysetting AS target
|
|||||||
USING (SELECT @companyId AS company_id, @key AS [key]) AS src
|
USING (SELECT @companyId AS company_id, @key AS [key]) AS src
|
||||||
ON target.company_id = src.company_id AND target.[key] = src.[key]
|
ON target.company_id = src.company_id AND target.[key] = src.[key]
|
||||||
WHEN MATCHED THEN
|
WHEN MATCHED THEN
|
||||||
UPDATE SET value = @value, frontend = @frontend
|
UPDATE SET value = @value, frontend = @frontend, writeonly = @writeonly
|
||||||
WHEN NOT MATCHED THEN
|
WHEN NOT MATCHED THEN
|
||||||
INSERT (company_id, [key], value, frontend)
|
INSERT (company_id, [key], value, frontend, writeonly)
|
||||||
VALUES (@companyId, @key, @value, @frontend);
|
VALUES (@companyId, @key, @value, @frontend, @writeonly);
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -12,13 +12,18 @@ export default function get(pool) {
|
|||||||
* @param {string} key - The setting key.
|
* @param {string} key - The setting key.
|
||||||
* @param {object} [options] - Optional options.
|
* @param {object} [options] - Optional options.
|
||||||
* @param {boolean} [options.frontendOnly] - Only return the setting if it is frontend-visible.
|
* @param {boolean} [options.frontendOnly] - Only return the setting if it is frontend-visible.
|
||||||
* @returns {Promise<{key: string, value: string, frontend: boolean}|undefined>} The setting, or `undefined` if not found.
|
* @param {boolean} [options.maskWriteonly] - Mask writeonly settings as '***'. Defaults to `frontendOnly` (usergui gets '***', backend gets full value).
|
||||||
|
* @returns {Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}|undefined>} The setting, or `undefined` if not found.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const setting = await store.companysetting.get(42, 'theme');
|
* const setting = await store.companysetting.get(42, 'ui.theme');
|
||||||
* // => { key, value, frontend }
|
* // => { key, value, frontend, writeonly }
|
||||||
*/
|
*/
|
||||||
return async (googleAuthId, key, { frontendOnly = false } = {}) => {
|
return async (
|
||||||
|
googleAuthId,
|
||||||
|
key,
|
||||||
|
{ frontendOnly = false, maskWriteonly } = {},
|
||||||
|
) => {
|
||||||
if (!key?.trim()) {
|
if (!key?.trim()) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -39,6 +44,7 @@ export default function get(pool) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shapeSetting(row);
|
const shouldMask = maskWriteonly ?? frontendOnly;
|
||||||
|
return shapeSetting(row, { exposeValue: !shouldMask });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,23 @@ export default function list(pool) {
|
|||||||
/**
|
/**
|
||||||
* Lists the settings of the user's selected company, optionally only frontend-visible ones.
|
* Lists the settings of the user's selected company, optionally only frontend-visible ones.
|
||||||
*
|
*
|
||||||
|
* Write-only settings (such as `keys.tavily`, `keys.openrouter`) have their value masked
|
||||||
|
* with `'***'` by default for usergui presentation.
|
||||||
|
*
|
||||||
* @param {number} googleAuthId - The id of the Google auth user.
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
* @param {object} [options] - Optional options.
|
* @param {object} [options] - Optional options.
|
||||||
* @param {boolean} [options.frontendOnly] - Only return frontend-visible settings.
|
* @param {boolean} [options.frontendOnly] - Only return frontend-visible settings.
|
||||||
* @returns {Promise<Array<{key: string, value: string, frontend: boolean}>>} The settings.
|
* @param {boolean} [options.maskWriteonly] - Whether to mask writeonly settings with '***'. Defaults to `true`.
|
||||||
|
* @returns {Promise<Array<{key: string, value: string, frontend: boolean, writeonly: boolean}>>} The settings.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const settings = await store.companysetting.list(42, { frontendOnly: true });
|
* const settings = await store.companysetting.list(42, { frontendOnly: true });
|
||||||
* // => [{ key, value, frontend }]
|
* // => [{ key, value, frontend, writeonly }]
|
||||||
*/
|
*/
|
||||||
return async (googleAuthId, { frontendOnly = false } = {}) => {
|
return async (
|
||||||
|
googleAuthId,
|
||||||
|
{ frontendOnly = false, maskWriteonly = true } = {},
|
||||||
|
) => {
|
||||||
const { companyId } = await access(googleAuthId);
|
const { companyId } = await access(googleAuthId);
|
||||||
|
|
||||||
const result = await pool
|
const result = await pool
|
||||||
@@ -28,6 +35,8 @@ export default function list(pool) {
|
|||||||
.input('companyId', companyId)
|
.input('companyId', companyId)
|
||||||
.query(frontendOnly ? LIST_BY_COMPANY_FRONTEND : LIST_BY_COMPANY);
|
.query(frontendOnly ? LIST_BY_COMPANY_FRONTEND : LIST_BY_COMPANY);
|
||||||
|
|
||||||
return result.recordset.map(shapeSetting);
|
return result.recordset.map((row) =>
|
||||||
|
shapeSetting(row, { exposeValue: !maskWriteonly }),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ const ALLOWED_KEYS = new Set([
|
|||||||
'labelprinter.type',
|
'labelprinter.type',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Keys that are write-only by default: the GUI receives a scrambled "***"
|
||||||
|
// placeholder when reading, but the backend always gets the real value.
|
||||||
|
const WRITEONLY_KEYS = new Set([
|
||||||
|
'keys.tavily',
|
||||||
|
'keys.openrouter',
|
||||||
|
]);
|
||||||
|
|
||||||
export default function set(pool) {
|
export default function set(pool) {
|
||||||
const access = resolveSelectedCompanyAccess(pool);
|
const access = resolveSelectedCompanyAccess(pool);
|
||||||
|
|
||||||
@@ -19,17 +26,22 @@ export default function set(pool) {
|
|||||||
* Only a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`,
|
* Only a fixed allow-list of keys can be set: `ui.theme`, `keys.tavily`,
|
||||||
* `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.
|
* `keys.openrouter`, `labelprinter.addr`, `labelprinter.type`.
|
||||||
*
|
*
|
||||||
|
* Keys in the write-only set (`keys.tavily`, `keys.openrouter`) are stored
|
||||||
|
* with `writeonly = 1`; when retrieved by the GUI the value is returned as
|
||||||
|
* `"***"`. The backend always receives the real value.
|
||||||
|
*
|
||||||
* @param {number} googleAuthId - The id of the Google auth user.
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
* @param {object} input - The setting input.
|
* @param {object} input - The setting input.
|
||||||
* @param {string} input.key - The setting key (must be in the allow-list).
|
* @param {string} input.key - The setting key (must be in the allow-list).
|
||||||
* @param {string} input.value - The setting value.
|
* @param {string} input.value - The setting value.
|
||||||
* @param {boolean} [input.frontend] - Whether the setting is frontend-visible.
|
* @param {boolean} [input.frontend] - Whether the setting is frontend-visible.
|
||||||
* @returns {Promise<{key: string, value: string, frontend: boolean}>} The upserted setting.
|
* @param {boolean} [input.writeonly] - Whether the setting is write-only. Defaults to true for `keys.tavily` and `keys.openrouter`, false otherwise.
|
||||||
|
* @returns {Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}>} The upserted setting.
|
||||||
* @throws {Error} If the input is invalid.
|
* @throws {Error} If the input is invalid.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const setting = await store.companysetting.set(42, { key: 'ui.theme', value: 'dark' });
|
* const setting = await store.companysetting.set(42, { key: 'ui.theme', value: 'dark' });
|
||||||
* // => { key, value, frontend }
|
* // => { key, value, frontend, writeonly }
|
||||||
*/
|
*/
|
||||||
return async (googleAuthId, input = {}) => {
|
return async (googleAuthId, input = {}) => {
|
||||||
const key = input.key?.trim();
|
const key = input.key?.trim();
|
||||||
@@ -41,6 +53,10 @@ export default function set(pool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const frontend = Boolean(input.frontend);
|
const frontend = Boolean(input.frontend);
|
||||||
|
const writeonly =
|
||||||
|
input.writeonly !== undefined
|
||||||
|
? Boolean(input.writeonly)
|
||||||
|
: WRITEONLY_KEYS.has(key);
|
||||||
const { companyId } = await access(googleAuthId);
|
const { companyId } = await access(googleAuthId);
|
||||||
|
|
||||||
await pool
|
await pool
|
||||||
@@ -49,6 +65,7 @@ export default function set(pool) {
|
|||||||
.input('key', key)
|
.input('key', key)
|
||||||
.input('value', input.value)
|
.input('value', input.value)
|
||||||
.input('frontend', frontend)
|
.input('frontend', frontend)
|
||||||
|
.input('writeonly', writeonly)
|
||||||
.query(UPSERT);
|
.query(UPSERT);
|
||||||
|
|
||||||
const result = await pool
|
const result = await pool
|
||||||
@@ -57,6 +74,7 @@ export default function set(pool) {
|
|||||||
.input('key', key)
|
.input('key', key)
|
||||||
.query(GET_BY_COMPANY_AND_KEY);
|
.query(GET_BY_COMPANY_AND_KEY);
|
||||||
|
|
||||||
|
// Return the masked value to the GUI; the DB holds the real value.
|
||||||
return shapeSetting(result.recordset[0]);
|
return shapeSetting(result.recordset[0]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
function shapeSetting(row) {
|
function shapeSetting(row, { exposeValue = false } = {}) {
|
||||||
|
const writeonly = Boolean(row.writeonly);
|
||||||
return {
|
return {
|
||||||
key: row.key,
|
key: row.key,
|
||||||
value: row.value,
|
value: writeonly && !exposeValue ? '***' : row.value,
|
||||||
frontend: Boolean(row.frontend),
|
frontend: Boolean(row.frontend),
|
||||||
|
writeonly,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user