From e9b4ac5d796a22dac1b548250b3c4c3c252cedde Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 22 Oct 2026 14:39:45 +0200 Subject: [PATCH] u --- API.md | 14 +- API.posterminal.md | 28 +- generate-api-doc.js | 4 +- generate-schema-graph.js | 6 +- schema-graph.dot | 241 +- schema-graph.svg | 6126 +++++++++-------- scripts/test-category-delete-recursive.js | 8 +- .../{test-tombstone.js => test-obituary.js} | 136 +- src/index.js | 8 +- src/providers/mssql/queries/posterminal.js | 28 +- src/providers/mssql/schema.js | 18 +- src/providers/sqlite3/index.js | 4 +- src/providers/sqlite3/queries/posterminal.js | 6 +- src/providers/sqlite3/schema.js | 12 +- src/store/article/delete.js | 6 +- src/store/category/delete.js | 10 +- src/store/customergroup/delete.js | 6 +- src/store/entity/delete.js | 6 +- src/store/posterminal/findByPairingpin.js | 2 +- src/store/posterminal/findByToken.js | 2 +- .../posterminal/getDeletedEntityCount.js | 2 +- src/store/posterminal/getDeletedEntityList.js | 2 +- src/store/posterminal/list.js | 4 +- .../{recordTombstone.js => recordObituary.js} | 8 +- .../posterminal/setMaxKnownObituaryId.js | 27 + .../posterminal/setMaxKnownTombstoneId.js | 27 - src/store/posterminal/setOff.js | 12 +- src/store/posterminal/setOffAll.js | 12 +- src/store/posterminal/setOn.js | 6 +- src/store/posterminal/setOnAll.js | 6 +- src/store/posterminal/upsert.js | 20 +- 31 files changed, 3405 insertions(+), 3392 deletions(-) rename scripts/{test-tombstone.js => test-obituary.js} (58%) rename src/store/posterminal/{recordTombstone.js => recordObituary.js} (72%) create mode 100644 src/store/posterminal/setMaxKnownObituaryId.js delete mode 100644 src/store/posterminal/setMaxKnownTombstoneId.js diff --git a/API.md b/API.md index 2a3e016..1c0da25 100644 --- a/API.md +++ b/API.md @@ -63,9 +63,9 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - **package**: `id PK, shipping_id->shipping, entityaddress_id->entityaddress, number:s(100), type:s(100), state:s(100), details?:txt` - **payment**: `id PK, account_id->account, manifest_id->manifest, type:s(100), amount:f` - **pic**: `id PK, w:i, h:i, size:bi, hash:s(64) UQ, thumbw:i, thumbh:i, thumbhash:s(64), source:txt, fullbinary:bin, thumbbinary:bin` -- **posterminal**: `id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt` +- **posterminal**: `id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt` - **posterminalcategory**: `id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)` -- **posterminaltombstone**: `id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt` +- **posterminalobituary**: `id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt` - **price**: `id PK, tax_id->tax, article_id->article, minmultiplier:d(18,4)=1, customergroup_id->customergroup, net:f` - **printer**: `id PK, company_id->company, address:s(255), type:s(50), model?:s(255), serial?:s(255), sort:i=0, desc?:txt` - **propertyname**: `id PK, company_id->company, name:s(255), sort:i=0, exclusive:b=0, UQ(company_id, name)` @@ -254,8 +254,8 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `ship(provider: object): Function` - [posterminal](API.posterminal.md) - `delete(googleAuthId: number, id: number, tx?: object): Promise` - - `findByPairingpin(pairingpin: string, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` - - `findByToken(token: string, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` + - `findByPairingpin(pairingpin: string, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` + - `findByToken(token: string, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` - `getCategoryCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise` - `getCategoryList(input: {posterminalId: number, cursor?: number, limit?: number}, tx?: object): Promise>` - `getCompositeProductCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise` @@ -268,10 +268,10 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `getMaxOrderIdCount(input: {posterminalId: number}, tx?: object): Promise` - `getProductCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise` - `getProductList(input: {posterminalId: number, cursor?: number, limit?: number}, tx?: object): Promise>` - - `list(googleAuthId: number, tx?: object): Promise>` + - `list(googleAuthId: number, tx?: object): Promise>` - `pair(id: number, input: {token: string, clientserial?: string, pairedAt?: string}, tx?: object): Promise<{id: number, token: string, clientserial: string|null, pairedAt: string|null}>` - - `recordTombstone(input: {companyId: number, entityType: string, entityId: number}, tx?: object): Promise` - - `setMaxKnownTombstoneId(id: number, maxknowntombstoneid: number|null, tx?: object): Promise<{id: number, maxknowntombstoneid: number|null}>` + - `recordObituary(input: {companyId: number, entityType: string, entityId: number}, tx?: object): Promise` + - `setMaxKnownObituaryId(id: number, maxknownobituaryid: number|null, tx?: object): Promise<{id: number, maxknownobituaryid: number|null}>` - `setOff(googleAuthId: number, posterminalId: number, categoryId: number, tx?: object): Promise<{id: number, categoryIds: Array}>` - `setOffAll(googleAuthId: number, posterminalId: number, tx?: object): Promise<{id: number, categoryIds: Array}>` - `setOn(googleAuthId: number, posterminalId: number, categoryId: number, tx?: object): Promise<{id: number, categoryIds: Array}>` diff --git a/API.posterminal.md b/API.posterminal.md index a5da219..54ef4b1 100644 --- a/API.posterminal.md +++ b/API.posterminal.md @@ -45,7 +45,7 @@ Finds a posterminal by its pairingpin. **Returns** -`Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` — The posterminal, or null if not found. +`Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` — The posterminal, or null if not found. ## `posterminal.findByToken` @@ -62,7 +62,7 @@ Finds a posterminal by its auth token. **Returns** -`Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` — The posterminal, or null if not found. +`Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>` — The posterminal, or null if not found. ## `posterminal.getCategoryCount` @@ -212,7 +212,7 @@ Counts deleted entities for a POS terminal after the given cursor ID. | --- | --- | --- | | `input` | `object` | | | `input.posterminalId` | `number` | The POS terminal id. | -| `[input.cursor=0]` | `number` | The highest synced tombstone ID. | +| `[input.cursor=0]` | `number` | The highest synced obituary ID. | | `[tx]` | `object` | Optional transaction. | **Returns** @@ -231,7 +231,7 @@ Lists deleted entities for a POS terminal after the given cursor ID. | --- | --- | --- | | `input` | `object` | | | `input.posterminalId` | `number` | The POS terminal id. | -| `[input.cursor=0]` | `number` | The highest synced tombstone ID. | +| `[input.cursor=0]` | `number` | The highest synced obituary ID. | | `[input.limit=200]` | `number` | Max items to return. | | `[tx]` | `object` | Optional transaction. | @@ -311,13 +311,13 @@ Lists the posterminals of the user's selected company. **Returns** -`Promise>` — The posterminals. +`Promise>` — The posterminals. **Example** ```js const terminals = await store.posterminal.list(42); -// => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] +// => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] ``` ## `posterminal.pair` @@ -341,11 +341,11 @@ Completes POS device pairing for a terminal. `Promise<{id: number, token: string, clientserial: string|null, pairedAt: string|null}>` -## `posterminal.recordTombstone` +## `posterminal.recordObituary` -*Source: `src/store/posterminal/recordTombstone.js`* +*Source: `src/store/posterminal/recordObituary.js`* -Records a tombstone for all active paired POS terminals of a company. +Records an obituary for all active paired POS terminals of a company. **Parameters** @@ -361,23 +361,23 @@ Records a tombstone for all active paired POS terminals of a company. `Promise` -## `posterminal.setMaxKnownTombstoneId` +## `posterminal.setMaxKnownObituaryId` -*Source: `src/store/posterminal/setMaxKnownTombstoneId.js`* +*Source: `src/store/posterminal/setMaxKnownObituaryId.js`* -Updates the max known tombstone ID for a POS terminal. +Updates the max known obituary ID for a POS terminal. **Parameters** | Name | Type | Description | | --- | --- | --- | | `id` | `number` | The posterminal id. | -| `maxknowntombstoneid` | `number|null` | The highest synced tombstone ID. | +| `maxknownobituaryid` | `number|null` | The highest synced obituary ID. | | `[tx]` | `object` | Optional transaction to run within. | **Returns** -`Promise<{id: number, maxknowntombstoneid: number|null}>` +`Promise<{id: number, maxknownobituaryid: number|null}>` ## `posterminal.setOff` diff --git a/generate-api-doc.js b/generate-api-doc.js index b9d0c6d..7f5c939 100644 --- a/generate-api-doc.js +++ b/generate-api-doc.js @@ -379,9 +379,9 @@ const SCHEMA_TABLES = [ ['package', 'id PK, shipping_id->shipping, entityaddress_id->entityaddress, number:s(100), type:s(100), state:s(100), details?:txt'], ['payment', 'id PK, account_id->account, manifest_id->manifest, type:s(100), amount:f'], ['pic', 'id PK, w:i, h:i, size:bi, hash:s(64) UQ, thumbw:i, thumbh:i, thumbhash:s(64), source:txt, fullbinary:bin, thumbbinary:bin'], - ['posterminal', 'id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt'], + ['posterminal', 'id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt'], ['posterminalcategory', 'id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)'], - ['posterminaltombstone', 'id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt'], + ['posterminalobituary', 'id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt'], ['price', 'id PK, tax_id->tax, article_id->article, minmultiplier:d(18,4)=1, customergroup_id->customergroup, net:f'], ['printer', 'id PK, company_id->company, address:s(255), type:s(50), model?:s(255), serial?:s(255), sort:i=0, desc?:txt'], ['propertyname', 'id PK, company_id->company, name:s(255), sort:i=0, exclusive:b=0, UQ(company_id, name)'], diff --git a/generate-schema-graph.js b/generate-schema-graph.js index 7bbe1dc..b375c8f 100644 --- a/generate-schema-graph.js +++ b/generate-schema-graph.js @@ -170,8 +170,8 @@ function addInferredEdges(tables, edges) { const match = column.name.match(/^(.+)_id$/i); if (!match) continue; - // Tombstone tables store references to deleted entities, not active foreign keys. - if (tableName.includes('tombstone')) continue; + // Obituary tables store references to deleted entities, not active foreign keys. + if (tableName.includes('obituary') || tableName.includes('tombstone')) continue; const candidate = match[1]; if (!tables.has(candidate) || candidate === tableName) continue; @@ -390,7 +390,7 @@ const CLUSTERS = [ tables: ['tax', 'price', 'account', 'payment'], }, { id: 'units', label: 'Units', tables: ['unit'] }, - { id: 'pos', label: 'POS', tables: ['posterminal', 'posterminalcategory', 'posterminaltombstone', 'printer', 'labeltemplate'] }, + { id: 'pos', label: 'POS', tables: ['posterminal', 'posterminalcategory', 'posterminalobituary', 'printer', 'labeltemplate'] }, { id: 'ai', label: 'AI & Models', diff --git a/schema-graph.dot b/schema-graph.dot index b74cbd0..d08e33c 100644 --- a/schema-graph.dot +++ b/schema-graph.dot @@ -10,16 +10,16 @@ digraph schema { style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; customergroup [label=<
customergroup
idINT PK
company_id?INT FK
nameNVARCHAR(255)
sortINT
updated_atDATETIME2
>]; - company [label=<
company
idINT PK
root_category_id?INT FK
taxrate?INT FK
reducedtaxrate?INT FK
taxfreerate?INT FK
default_language_id?INT FK
poscustomergroup_idINT FK
nameNVARCHAR(255)
>]; meta [label=<
meta
keyNVARCHAR(255)
valueNVARCHAR(MAX)
>]; companyhistory [label=<
companyhistory
idINT PK
company_idINT FK
companyuser_id?INT FK
dateDATETIME2
textNVARCHAR(MAX)
>]; - entityaddress [label=<
entityaddress
idINT PK
entity_idINT FK
first_name?NVARCHAR(255)
name?NVARCHAR(255)
street?NVARCHAR(255)
streetnumber?NVARCHAR(50)
zip?NVARCHAR(50)
city?NVARCHAR(255)
county?NVARCHAR(255)
addresstypeNVARCHAR(50)
sortINT
>]; + company [label=<
company
idINT PK
poscustomergroup_idINT FK
taxrate?INT FK
reducedtaxrate?INT FK
taxfreerate?INT FK
root_category_id?INT FK
default_language_id?INT FK
nameNVARCHAR(255)
>]; numbers [label=<
numbers
idINT PK
company_idINT FK
typeNVARCHAR(100)
prefixNVARCHAR(50)
paddingINT
nextINT
>]; + entityaddress [label=<
entityaddress
idINT PK
entity_idINT FK
first_name?NVARCHAR(255)
name?NVARCHAR(255)
street?NVARCHAR(255)
streetnumber?NVARCHAR(50)
zip?NVARCHAR(50)
city?NVARCHAR(255)
county?NVARCHAR(255)
addresstypeNVARCHAR(50)
sortINT
>]; entity [label=<
entity
idINT PK
customergroup_idINT FK
first_name?NVARCHAR(255)
nameNVARCHAR(255)
number?NVARCHAR(100)
created_atDATETIME2
updated_atDATETIME2
>]; - entitycontact [label=<
entitycontact
idINT PK
entity_idINT FK
contacttypeNVARCHAR(50)
contactNVARCHAR(255)
sortINT
>]; companysetting [label=<
companysetting
idINT PK
company_idINT FK
keyNVARCHAR(255)
valueNVARCHAR(MAX)
frontendBIT
writeonlyBIT
>]; - entityhistory [label=<
entityhistory
idINT PK
entity_idINT FK
companyuser_id?INT FK
dateDATETIME2
textNVARCHAR(MAX)
>]; + entitycontact [label=<
entitycontact
idINT PK
entity_idINT FK
contacttypeNVARCHAR(50)
contactNVARCHAR(255)
sortINT
>]; companyuser [label=<
companyuser
idINT PK
company_idINT FK
google_auth_idINT FK
>]; + entityhistory [label=<
entityhistory
idINT PK
entity_idINT FK
companyuser_id?INT FK
dateDATETIME2
textNVARCHAR(MAX)
>]; google_auth [label=<
google_auth
idINT PK
selected_company?INT FK
emailNVARCHAR(320)
picture?NVARCHAR(2048)
picturebinary?VARBINARY(MAX)
sub?NVARCHAR(255)
created_atDATETIME2
>]; } subgraph cluster_i18n { @@ -37,25 +37,24 @@ digraph schema { fontcolor="#e2e8f0"; margin=14; categoryarticle [label=<
categoryarticle
idINT PK
category_idINT FK
article_idINT FK
>]; category [label=<
category
idINT PK
parent_id?INT FK
sortINT
updated_atDATETIME2
>]; - articlehistory [label=<
articlehistory
idINT PK
article_idINT FK
companyuser_id?INT FK
dateDATETIME2
textNVARCHAR(MAX)
meta?NVARCHAR(MAX)
>]; - article [label=<
article
idINT PK
parentattributename_id?INT FK
parentarticle_id?INT FK
articlelist_id?INT FK
optionslist_id?INT FK
brand_id?INT FK
unit_idINT FK
company_idINT FK
sku?NVARCHAR(100)
unitamountFLOAT
weightFLOAT
track_stockBIT
is_parentBIT
parentsortINT
created_atDATETIME2
updated_atDATETIME2
>]; + articlehistory [label=<
articlehistory
idINT PK
companyuser_id?INT FK
article_idINT FK
dateDATETIME2
textNVARCHAR(MAX)
meta?NVARCHAR(MAX)
>]; + article [label=<
article
idINT PK
company_idINT FK
parentattributename_id?INT FK
parentarticle_id?INT FK
articlelist_id?INT FK
optionslist_id?INT FK
brand_id?INT FK
unit_idINT FK
sku?NVARCHAR(100)
unitamountFLOAT
weightFLOAT
track_stockBIT
is_parentBIT
parentsortINT
created_atDATETIME2
updated_atDATETIME2
>]; articleean [label=<
articleean
idINT PK
article_idINT FK
eanNVARCHAR(50)
>]; - articlesupplier [label=<
articlesupplier
idINT PK
article_idINT FK
tax_id?INT FK
entity_idINT FK
net?FLOAT
sku?NVARCHAR(100)
stock?FLOAT
puFLOAT
sortINT
>]; + articlesupplier [label=<
articlesupplier
idINT PK
entity_idINT FK
tax_id?INT FK
article_idINT FK
net?FLOAT
sku?NVARCHAR(100)
stock?FLOAT
puFLOAT
sortINT
>]; articlelist [label=<
articlelist
idINT PK
>]; articlelistarticle [label=<
articlelistarticle
idINT PK
article_idINT FK
articlelist_idINT FK
countINT
sortINT
>]; optionslist [label=<
optionslist
idINT PK
>]; optionslistarticle [label=<
optionslistarticle
idINT PK
article_idINT FK
optionslist_idINT FK
countINT
sortINT
mandatedBIT
>]; brand [label=<
brand
idINT PK
company_idINT FK
nameNVARCHAR(255)
gsprpinfo?NVARCHAR(MAX)
>]; - articletombstone [label=<
articletombstone
idINT PK
company_idINT FK
article_id?INT
sku?NVARCHAR(100)
name?NVARCHAR(255)
taxrate?DECIMAL(18,4)
net?FLOAT
deleted_atDATETIME2
>]; } subgraph cluster_media { label="Media"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; + pic [label=<
pic
idINT PK
wINT
hINT
sizeBIGINT
hashNVARCHAR(64)
thumbwINT
thumbhINT
thumbhashNVARCHAR(64)
smallthumbwINT
smallthumbhINT
sourceNVARCHAR(MAX)
fullbinaryVARBINARY(MAX)
thumbbinaryVARBINARY(MAX)
smallthumbbinaryVARBINARY(MAX)
>]; attributevaluepic [label=<
attributevaluepic
idINT PK
attributevalue_idINT FK
pic_idINT FK
sortINT
>]; categorypic [label=<
categorypic
idINT PK
category_idINT FK
pic_idINT FK
sortINT
>]; - articlepic [label=<
articlepic
idINT PK
pic_idINT FK
article_idINT FK
sortINT
>]; - pic [label=<
pic
idINT PK
wINT
hINT
sizeBIGINT
hashNVARCHAR(64)
thumbwINT
thumbhINT
thumbhashNVARCHAR(64)
smallthumbwINT
smallthumbhINT
sourceNVARCHAR(MAX)
fullbinaryVARBINARY(MAX)
thumbbinaryVARBINARY(MAX)
smallthumbbinaryVARBINARY(MAX)
>]; + articlepic [label=<
articlepic
idINT PK
article_idINT FK
pic_idINT FK
sortINT
>]; brandpic [label=<
brandpic
idINT PK
pic_idINT FK
brand_idINT FK
sortINT
>]; file [label=<
file
idINT PK
hashNVARCHAR(64)
mimetypeNVARCHAR(255)
nameNVARCHAR(255)
sizeBIGINT
createdDATETIME2
modifiedDATETIME2
contentVARBINARY(MAX)
thumbavif?VARBINARY(MAX)
thumbx?INT
thumby?INT
meta?NVARCHAR(MAX)
>]; } @@ -63,27 +62,27 @@ digraph schema { label="Documents & Shipping"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; - articlewarehousesummary [label=<
articlewarehousesummary
idINT PK
article_idINT FK
warehouse_idINT FK
stockFLOAT
>]; - ledger [label=<
ledger
idINT PK
warehouse_id?INT FK
manifestarticle_idINT FK
transaction_typeNVARCHAR(100)
amountFLOAT
transaction_textNVARCHAR(MAX)
hash_versionINT
prev_hash?NVARCHAR(128)
created_atDATETIME2
>]; - warehouse [label=<
warehouse
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
>]; - manifestarticle [label=<
manifestarticle
idINT PK
manifest_idINT FK
sku?NVARCHAR(100)
name?NVARCHAR(255)
puFLOAT
amountFLOAT
netFLOAT
comment?NVARCHAR(MAX)
rebateFLOAT
taxrateFLOAT
>]; + deliverysummary [label=<
deliverysummary
idINT PK
company_idINT FK
supplier_id?INT FK
manifest_idINT FK
delivery_numberNVARCHAR(100)
external_number?NVARCHAR(100)
delivery_dateDATETIME2
created_atDATETIME2
supplier_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
net_totalFLOAT
total_quantityFLOAT
stock_positionsINT
booked_positionsINT
unbooked_positionsINT
stock_quantityFLOAT
booked_quantityFLOAT
unbooked_quantityFLOAT
is_bookedTINYINT
>]; + ordersummary [label=<
ordersummary
idINT PK
company_idINT FK
entity_id?INT FK
manifest_idINT FK
order_numberNVARCHAR(100)
order_dateDATETIME2
created_atDATETIME2
customer_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
paid_totalFLOAT
ordered_quantityFLOAT
shipped_quantityFLOAT
is_paidTINYINT
is_shippedTINYINT
>]; + quotesummary [label=<
quotesummary
idINT PK
company_idINT FK
entity_id?INT FK
manifest_idINT FK
quote_numberNVARCHAR(100)
quote_dateDATETIME2
created_atDATETIME2
customer_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
total_quantityFLOAT
>]; + shipmentsummary [label=<
shipmentsummary
idINT PK
company_idINT FK
entity_id?INT FK
manifest_idINT FK
shipment_numberNVARCHAR(100)
shipment_dateDATETIME2
created_atDATETIME2
order_id?INT
order_number?NVARCHAR(100)
customer_name?NVARCHAR(255)
positionsINT
total_quantityFLOAT
package_countINT
carrier?NVARCHAR(100)
tracking_code?NVARCHAR(255)
stateNVARCHAR(50)
>]; + package [label=<
package
idINT PK
entityaddress_idINT FK
shipping_idINT FK
numberNVARCHAR(100)
typeNVARCHAR(100)
stateNVARCHAR(100)
details?NVARCHAR(MAX)
>]; + manifestarticle [label=<
manifestarticle
idINT PK
manifest_idINT FK
sku?NVARCHAR(100)
name?NVARCHAR(255)
puFLOAT
amountFLOAT
netFLOAT
comment?NVARCHAR(MAX)
rebateFLOAT
taxrateFLOAT
shippableTINYINT
>]; manifest [label=<
manifest
idINT PK
company_idINT FK
entity_id?INT FK
numberNVARCHAR(100)
typeNVARCHAR(100)
external_number?NVARCHAR(100)
dateDATETIME2
created_atDATETIME2
>]; - manifestattachment [label=<
manifestattachment
idINT PK
file_idINT FK
manifest_idINT FK
sortINT
>]; - shipping [label=<
shipping
idINT PK
manifest_idINT FK
carrier_idINT FK
numberNVARCHAR(100)
tracking_code?NVARCHAR(255)
typeNVARCHAR(100)
stateNVARCHAR(100)
>]; - quotesummary [label=<
quotesummary
idINT PK
manifest_idINT FK
company_idINT FK
entity_id?INT FK
quote_numberNVARCHAR(100)
quote_dateDATETIME2
created_atDATETIME2
customer_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
total_quantityFLOAT
>]; - ordersummary [label=<
ordersummary
idINT PK
manifest_idINT FK
company_idINT FK
entity_id?INT FK
order_numberNVARCHAR(100)
order_dateDATETIME2
created_atDATETIME2
customer_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
paid_totalFLOAT
ordered_quantityFLOAT
shipped_quantityFLOAT
is_paidTINYINT
is_shippedTINYINT
>]; - package [label=<
package
idINT PK
shipping_idINT FK
entityaddress_idINT FK
numberNVARCHAR(100)
typeNVARCHAR(100)
stateNVARCHAR(100)
details?NVARCHAR(MAX)
>]; - deliverysummary [label=<
deliverysummary
idINT PK
manifest_idINT FK
company_idINT FK
supplier_id?INT FK
delivery_numberNVARCHAR(100)
external_number?NVARCHAR(100)
delivery_dateDATETIME2
created_atDATETIME2
supplier_name?NVARCHAR(255)
positionsINT
gross_totalFLOAT
net_totalFLOAT
total_quantityFLOAT
stock_positionsINT
booked_positionsINT
unbooked_positionsINT
stock_quantityFLOAT
booked_quantityFLOAT
unbooked_quantityFLOAT
is_bookedTINYINT
>]; - shipmentsummary [label=<
shipmentsummary
idINT PK
manifest_idINT FK
company_idINT FK
entity_id?INT FK
shipment_numberNVARCHAR(100)
shipment_dateDATETIME2
created_atDATETIME2
order_id?INT
order_number?NVARCHAR(100)
customer_name?NVARCHAR(255)
positionsINT
total_quantityFLOAT
package_countINT
carrier?NVARCHAR(100)
tracking_code?NVARCHAR(255)
stateNVARCHAR(50)
>]; + manifestattachment [label=<
manifestattachment
idINT PK
manifest_idINT FK
file_idINT FK
sortINT
>]; + shipping [label=<
shipping
idINT PK
carrier_idINT FK
manifest_idINT FK
numberNVARCHAR(100)
tracking_code?NVARCHAR(255)
typeNVARCHAR(100)
stateNVARCHAR(100)
>]; + warehouse [label=<
warehouse
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
>]; + ledger [label=<
ledger
idINT PK
manifestarticle_idINT FK
warehouse_id?INT FK
transaction_typeNVARCHAR(100)
amountFLOAT
transaction_textNVARCHAR(MAX)
hash_versionINT
prev_hash?NVARCHAR(128)
created_atDATETIME2
>]; + articlewarehousesummary [label=<
articlewarehousesummary
idINT PK
warehouse_idINT FK
article_idINT FK
stockFLOAT
>]; } subgraph cluster_commerce { label="Pricing & Payments"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; tax [label=<
tax
idINT PK
rateDECIMAL(18,4)
>]; - price [label=<
price
idINT PK
article_idINT FK
tax_idINT FK
customergroup_idINT FK
minmultiplierDECIMAL(18,4)
netFLOAT
>]; + payment [label=<
payment
idINT PK
manifest_idINT FK
account_idINT FK
typeNVARCHAR(100)
amountFLOAT
>]; account [label=<
account
idINT PK
company_idINT FK
typeNVARCHAR(100)
nameNVARCHAR(255)
>]; - payment [label=<
payment
idINT PK
account_idINT FK
manifest_idINT FK
typeNVARCHAR(100)
amountFLOAT
>]; + price [label=<
price
idINT PK
customergroup_idINT FK
tax_idINT FK
article_idINT FK
minmultiplierDECIMAL(18,4)
netFLOAT
>]; } subgraph cluster_units { label="Units"; labeljust="l"; fontsize=15; @@ -95,10 +94,11 @@ digraph schema { label="POS"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; - posterminalcategory [label=<
posterminalcategory
idINT PK
category_idINT FK
posterminal_idINT FK
>]; printer [label=<
printer
idINT PK
company_idINT FK
addressNVARCHAR(255)
typeNVARCHAR(50)
model?NVARCHAR(255)
serial?NVARCHAR(255)
sortINT
desc?NVARCHAR(MAX)
>]; - posterminal [label=<
posterminal
idINT PK
root_category_id?INT FK
company_idINT FK
nameNVARCHAR(255)
token?NVARCHAR(255)
pairingpin?NVARCHAR(50)
paired_at?DATETIME2
clientserial?NVARCHAR(255)
maxknowntombstoneid?INT
sync_root_articlesBIT
lastseen_at?DATETIME2
updated_atDATETIME2
>]; labeltemplate [label=<
labeltemplate
idINT PK
company_idINT FK
nameNVARCHAR(255)
widthINT
heightINT
dpiINT
typeNVARCHAR(50)
contentNVARCHAR(MAX)
thumb?VARBINARY(MAX)
>]; + posterminalobituary [label=<
posterminalobituary
idINT PK
posterminal_idINT FK
entity_typeNVARCHAR(50)
entity_idINT
created_atDATETIME2
>]; + posterminal [label=<
posterminal
idINT PK
company_idINT FK
root_category_id?INT FK
nameNVARCHAR(255)
token?NVARCHAR(255)
pairingpin?NVARCHAR(50)
paired_at?DATETIME2
clientserial?NVARCHAR(255)
maxknownobituaryid?INT
sync_root_articlesBIT
lastseen_at?DATETIME2
updated_atDATETIME2
>]; + posterminalcategory [label=<
posterminalcategory
idINT PK
posterminal_idINT FK
category_idINT FK
>]; } subgraph cluster_ai { label="AI & Models"; labeljust="l"; fontsize=15; @@ -113,132 +113,133 @@ digraph schema { label="Properties & Attributes"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; - propertyname [label=<
propertyname
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
exclusiveBIT
>]; attributevalue [label=<
attributevalue
idINT PK
attribute_idINT FK
valueNVARCHAR(255)
sortINT
>]; + attributename [label=<
attributename
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
exclusiveBIT
>]; + propertyname [label=<
propertyname
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
exclusiveBIT
>]; categoryproperty [label=<
categoryproperty
idINT PK
property_idINT FK
category_idINT FK
valueNVARCHAR(MAX)
sortINT
>]; categoryattributevalue [label=<
categoryattributevalue
idINT PK
attributevalue_idINT FK
category_idINT FK
sortINT
>]; articleproperty [label=<
articleproperty
idINT PK
property_idINT FK
article_idINT FK
valueNVARCHAR(MAX)
sortINT
>]; - attributename [label=<
attributename
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
exclusiveBIT
>]; articleattributevalue [label=<
articleattributevalue
idINT PK
attributevalue_idINT FK
article_idINT FK
sortINT
>]; } carrier [label=<
carrier
idINT PK
company_idINT FK
nameNVARCHAR(255)
sortINT
has_packagesBIT
is_reverseBIT
>]; - mcp_client [label=<
mcp_client
idINT PK
client_idNVARCHAR(100)
client_secret?NVARCHAR(255)
client_nameNVARCHAR(255)
redirect_urisNVARCHAR(MAX)
grant_types?NVARCHAR(255)
response_types?NVARCHAR(255)
scope?NVARCHAR(255)
created_atDATETIME2
>]; mcp_auth_code [label=<
mcp_auth_code
codeNVARCHAR(128) PK
google_auth_idINT FK
client_idNVARCHAR(100)
redirect_uriNVARCHAR(2048)
code_challengeNVARCHAR(255)
code_challenge_methodNVARCHAR(32)
scope?NVARCHAR(255)
expires_atDATETIME2
usedTINYINT
created_atDATETIME2
>]; mcp_token [label=<
mcp_token
idINT PK
google_auth_idINT FK
refresh_tokenNVARCHAR(128)
client_idNVARCHAR(100)
scope?NVARCHAR(255)
expires_atDATETIME2
revokedTINYINT
created_atDATETIME2
>]; + mcp_client [label=<
mcp_client
idINT PK
client_idNVARCHAR(100)
client_secret?NVARCHAR(255)
client_nameNVARCHAR(255)
redirect_urisNVARCHAR(MAX)
grant_types?NVARCHAR(255)
response_types?NVARCHAR(255)
scope?NVARCHAR(255)
created_atDATETIME2
>]; + healthcheck [label=<
healthcheck
idINT PK
sequenceBIGINT
updated_atDATETIME2
>]; __legend [label=<
Legend
PKprimary key
FKforeign key
?nullable column
—FOREIGN KEY constraint
- -naming convention only, no constraint
>]; - google_auth:selected_company:w -> company:in24:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_google_auth_selected_company", weight=3]; + google_auth:selected_company:w -> company:in11:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_google_auth_selected_company", weight=3]; category:parent_id:e -> category:id:e [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_category_parent", constraint=false]; - company:root_category_id:w -> category:in8:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_company_root_category", weight=3]; - company:default_language_id:w -> language:in1:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_company_default_language", constraint=false, weight=1]; - company:taxrate:w -> tax:in4:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_company_taxrate", constraint=false, weight=1]; - company:reducedtaxrate:w -> tax:in1:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_company_reducedtaxrate", constraint=false, weight=1]; - company:taxfreerate:w -> tax:in3:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_company_taxfreerate", constraint=false, weight=1]; - customergroup:company_id:sw -> company:in17:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_customergroup_company", weight=3]; - company:poscustomergroup_id:nw -> customergroup:in1:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_company_poscustomergroup", constraint=false, weight=1]; + company:root_category_id:w -> category:in1:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_company_root_category", weight=3]; + company:default_language_id:w -> language:in0:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_company_default_language", constraint=false, weight=1]; + company:taxrate:w -> tax:in2:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_company_taxrate", constraint=false, weight=1]; + company:reducedtaxrate:w -> tax:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_company_reducedtaxrate", constraint=false, weight=1]; + company:taxfreerate:w -> tax:in1:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_company_taxfreerate", constraint=false, weight=1]; + customergroup:company_id:nw -> company:in6:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_customergroup_company", weight=3]; + company:poscustomergroup_id:nw -> customergroup:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_company_poscustomergroup", constraint=false, weight=1]; entity:customergroup_id:w -> customergroup:in2:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_entity_customergroup", weight=3]; - entityaddress:entity_id:sw -> entity:in6:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_entityaddress_entity", weight=3]; - entitycontact:entity_id:se -> entity:in7:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_entitycontact_entity", weight=3]; - entityhistory:entity_id:sw -> entity:in8:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_entityhistory_entity", weight=3]; + entityaddress:entity_id:sw -> entity:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_entityaddress_entity", weight=3]; + entitycontact:entity_id:se -> entity:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_entitycontact_entity", weight=3]; + entityhistory:entity_id:w -> entity:in2:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_entityhistory_entity", weight=3]; entityhistory:companyuser_id:se -> companyuser:in3:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_entityhistory_companyuser", constraint=false, weight=1]; - unit:company_id:w -> company:in9:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_unit_company", weight=3]; - unittext:unit_id:sw -> unit:in1:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_unittext_unit", weight=3]; - unittext:language_id:w -> language:in3:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_unittext_language", constraint=false, weight=1]; - brand:company_id:e -> company:in4:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_brand_company", weight=3]; - article:company_id:e -> company:in2:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_article_company", weight=3]; + unit:company_id:e -> company:in23:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_unit_company", weight=3]; + unittext:unit_id:se -> unit:in1:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_unittext_unit", weight=3]; + unittext:language_id:e -> language:in3:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_unittext_language", constraint=false, weight=1]; + brand:company_id:e -> company:in22:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_brand_company", weight=3]; + article:company_id:w -> company:in21:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_article_company", weight=3]; article:unit_id:e -> unit:in0:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_article_unit", constraint=false, weight=1]; article:brand_id:w -> brand:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_article_brand", constraint=false, weight=1]; article:articlelist_id:w -> articlelist:in1:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_article_articlelist", constraint=false, weight=1]; - article:optionslist_id:w -> optionslist:in1:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_article_optionslist", constraint=false, weight=1]; + article:optionslist_id:w -> optionslist:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_article_optionslist", constraint=false, weight=1]; article:parentarticle_id:e -> article:id:e [color="#c79bff", fontcolor="#c79bff", tooltip="FK_article_parentarticle", constraint=false]; - article:parentattributename_id:ne -> attributename:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_parentattributename", constraint=false, weight=1]; - article:parentattributename_id:ne -> attributename:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_parentattributename", constraint=false, weight=1]; - articlehistory:article_id:se -> article:in3:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_articlehistory_article", weight=3]; - articlehistory:companyuser_id:e -> companyuser:in0:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlehistory_companyuser", constraint=false, weight=1]; - companyhistory:company_id:ne -> company:in20:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_companyhistory_company", weight=3]; - companyhistory:companyuser_id:e -> companyuser:in1:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_companyhistory_companyuser", constraint=false, weight=1]; - articletombstone:company_id:e -> company:in5:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articletombstone_company", weight=3]; - articleean:article_id:sw -> article:in6:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleean_article", weight=3]; - articlepic:article_id:ne -> article:in4:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_articlepic_article", weight=3]; + article:parentattributename_id:se -> attributename:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_parentattributename", constraint=false, weight=1]; + article:parentattributename_id:se -> attributename:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_parentattributename", constraint=false, weight=1]; + articlehistory:article_id:sw -> article:in3:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_articlehistory_article", weight=3]; + articlehistory:companyuser_id:e -> companyuser:in2:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlehistory_companyuser", constraint=false, weight=1]; + companyhistory:company_id:sw -> company:in7:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_companyhistory_company", weight=3]; + companyhistory:companyuser_id:e -> companyuser:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_companyhistory_companyuser", constraint=false, weight=1]; + posterminalobituary:posterminal_id:se -> posterminal:in1:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_posterminalobituary_posterminal", weight=3]; + articleean:article_id:se -> article:in7:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleean_article", weight=3]; + articlepic:article_id:sw -> article:in11:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_articlepic_article", weight=3]; articlepic:pic_id:e -> pic:in2:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_articlepic_pic", constraint=false, weight=1]; - brandpic:brand_id:w -> brand:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_brandpic_brand", weight=3]; + brandpic:brand_id:sw -> brand:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_brandpic_brand", weight=3]; brandpic:pic_id:w -> pic:in3:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_brandpic_pic", constraint=false, weight=1]; - attributevaluepic:attributevalue_id:w -> attributevalue:in2:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_attributevaluepic_attributevalue", weight=3]; - attributevaluepic:pic_id:e -> pic:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_attributevaluepic_pic", constraint=false, weight=1]; + attributevaluepic:attributevalue_id:e -> attributevalue:in2:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_attributevaluepic_attributevalue", weight=3]; + attributevaluepic:pic_id:w -> pic:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_attributevaluepic_pic", constraint=false, weight=1]; articlelistarticle:articlelist_id:se -> articlelist:in0:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_articlelistarticle_articlelist", weight=3]; - articlelistarticle:article_id:w -> article:in8:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_articlelistarticle_article", constraint=false, weight=1]; - optionslistarticle:optionslist_id:sw -> optionslist:in0:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_optionslistarticle_optionslist", weight=3]; - optionslistarticle:article_id:w -> article:in10:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_optionslistarticle_article", constraint=false, weight=1]; - categoryarticle:category_id:nw -> category:in2:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_categoryarticle_category", weight=3]; - categoryarticle:article_id:nw -> article:in2:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_categoryarticle_article", constraint=false, weight=1]; - categorypic:category_id:sw -> category:in3:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_categorypic_category", weight=3]; + articlelistarticle:article_id:w -> article:in9:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_articlelistarticle_article", constraint=false, weight=1]; + optionslistarticle:optionslist_id:sw -> optionslist:in1:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_optionslistarticle_optionslist", weight=3]; + optionslistarticle:article_id:e -> article:in10:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_optionslistarticle_article", constraint=false, weight=1]; + categoryarticle:category_id:se -> category:in5:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_categoryarticle_category", weight=3]; + categoryarticle:article_id:sw -> article:in4:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_categoryarticle_article", constraint=false, weight=1]; + categorypic:category_id:sw -> category:in7:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_categorypic_category", weight=3]; categorypic:pic_id:e -> pic:in1:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_categorypic_pic", constraint=false, weight=1]; - categorytext:category_id:w -> category:in5:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_categorytext_category", weight=3]; - categorytext:language_id:e -> language:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_categorytext_language", constraint=false, weight=1]; + categorytext:category_id:w -> category:in8:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_categorytext_category", weight=3]; + categorytext:language_id:e -> language:in1:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_categorytext_language", constraint=false, weight=1]; articletext:article_id:e -> article:in12:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articletext_article", weight=3]; articletext:language_id:w -> language:in2:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_articletext_language", constraint=false, weight=1]; - price:tax_id:e -> tax:in2:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_price_tax", constraint=false, weight=1]; - price:article_id:sw -> article:in9:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_price_article", weight=3]; - price:customergroup_id:e -> customergroup:in0:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_price_customergroup", constraint=false, weight=1]; - articlesupplier:article_id:sw -> article:in7:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articlesupplier_article", weight=3]; - articlesupplier:entity_id:e -> entity:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articlesupplier_entity", constraint=false, weight=1]; - articlesupplier:tax_id:nw -> tax:in0:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articlesupplier_tax", constraint=false, weight=1]; - manifest:company_id:e -> company:in8:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_manifest_company", weight=3]; - manifest:entity_id:e -> entity:in1:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_manifest_entity", constraint=false, weight=1]; - manifestarticle:manifest_id:se -> manifest:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_manifestarticle_manifest", weight=3]; - warehouse:company_id:e -> company:in6:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_warehouse_company", weight=3]; + price:tax_id:w -> tax:in3:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_price_tax", constraint=false, weight=1]; + price:article_id:nw -> article:in5:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_price_article", weight=3]; + price:customergroup_id:e -> customergroup:in1:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_price_customergroup", constraint=false, weight=1]; + articlesupplier:article_id:se -> article:in8:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articlesupplier_article", weight=3]; + articlesupplier:entity_id:e -> entity:in8:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articlesupplier_entity", constraint=false, weight=1]; + articlesupplier:tax_id:e -> tax:in4:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articlesupplier_tax", constraint=false, weight=1]; + manifest:company_id:w -> company:in18:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_manifest_company", weight=3]; + manifest:entity_id:e -> entity:in7:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_manifest_entity", constraint=false, weight=1]; + manifestarticle:manifest_id:sw -> manifest:in4:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_manifestarticle_manifest", weight=3]; + warehouse:company_id:e -> company:in19:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_warehouse_company", weight=3]; ledger:manifestarticle_id:w -> manifestarticle:in0:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_ledger_manifestarticle", constraint=false, weight=1]; - ledger:warehouse_id:se -> warehouse:in1:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_ledger_warehouse", weight=3]; - numbers:company_id:ne -> company:in21:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_numbers_company", weight=3]; - companyuser:google_auth_id:e -> google_auth:in0:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_companyuser_google_auth", constraint=false, weight=1]; - companyuser:company_id:w -> company:in23:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_companyuser_company", weight=3]; - modelconversation:companyuser_id:w -> companyuser:in2:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_modelconversation_companyuser", weight=3]; - modelvfs:company_id:se -> company:in18:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_modelvfs_company", weight=3]; - modelmessage:conversation_id:sw -> modelconversation:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_modelmessage_conversation", weight=3]; - companysetting:company_id:w -> company:in22:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_companysetting_company", weight=3]; - posterminal:company_id:e -> company:in13:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_posterminal_company", weight=3]; - posterminal:root_category_id:w -> category:in7:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_posterminal_root_category", constraint=false, weight=1]; + ledger:warehouse_id:sw -> warehouse:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_ledger_warehouse", weight=3]; + numbers:company_id:se -> company:in8:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_numbers_company", weight=3]; + companyuser:google_auth_id:w -> google_auth:in0:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_companyuser_google_auth", constraint=false, weight=1]; + companyuser:company_id:e -> company:in10:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_companyuser_company", weight=3]; + modelconversation:companyuser_id:w -> companyuser:in1:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_modelconversation_companyuser", weight=3]; + modelvfs:company_id:sw -> company:in3:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_modelvfs_company", weight=3]; + modelmessage:conversation_id:se -> modelconversation:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_modelmessage_conversation", weight=3]; + companysetting:company_id:se -> company:in9:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_companysetting_company", weight=3]; + posterminal:company_id:e -> company:in4:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_posterminal_company", weight=3]; + posterminal:root_category_id:w -> category:in0:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_posterminal_root_category", constraint=false, weight=1]; posterminalcategory:posterminal_id:se -> posterminal:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_posterminalcategory_posterminal", weight=3]; - posterminalcategory:category_id:w -> category:in6:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_posterminalcategory_category", constraint=false, weight=1]; - printer:company_id:e -> company:in12:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_printer_company", weight=3]; - labeltemplate:company_id:e -> company:in14:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_labeltemplate_company", weight=3]; - manifestattachment:manifest_id:sw -> manifest:in2:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_manifestattachment_manifest", weight=3]; + posterminalcategory:category_id:w -> category:in2:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_posterminalcategory_category", constraint=false, weight=1]; + printer:company_id:w -> company:in2:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_printer_company", weight=3]; + labeltemplate:company_id:e -> company:in1:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_labeltemplate_company", weight=3]; + manifestattachment:manifest_id:ne -> manifest:in5:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_manifestattachment_manifest", weight=3]; manifestattachment:file_id:w -> file:in0:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_manifestattachment_file", constraint=false, weight=1]; - propertyname:company_id:e -> company:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_propertyname_company", weight=3]; + propertyname:company_id:e -> company:in16:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_propertyname_company", weight=3]; articleproperty:article_id:w -> article:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articleproperty_article", weight=3]; - articleproperty:property_id:w -> propertyname:in1:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleproperty_property", constraint=false, weight=1]; - attributename:company_id:e -> company:in1:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_attributename_company", weight=3]; - attributevalue:attribute_id:e -> attributename:in2:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_attributevalue_attribute", weight=3]; + articleproperty:property_id:e -> propertyname:in1:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleproperty_property", constraint=false, weight=1]; + attributename:company_id:e -> company:in17:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_attributename_company", weight=3]; + attributevalue:attribute_id:se -> attributename:in2:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_attributevalue_attribute", weight=3]; articleattributevalue:article_id:e -> article:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_articleattributevalue_article", weight=3]; - articleattributevalue:attributevalue_id:w -> attributevalue:in1:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_articleattributevalue_attributevalue", constraint=false, weight=1]; - categoryproperty:category_id:e -> category:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_categoryproperty_category", weight=3]; - categoryproperty:property_id:w -> propertyname:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_categoryproperty_property", constraint=false, weight=1]; - categoryattributevalue:category_id:e -> category:in0:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_categoryattributevalue_category", weight=3]; - categoryattributevalue:attributevalue_id:w -> attributevalue:in0:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_categoryattributevalue_attributevalue", constraint=false, weight=1]; - account:company_id:e -> company:in3:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_account_company", weight=3]; + articleattributevalue:attributevalue_id:e -> attributevalue:in1:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_articleattributevalue_attributevalue", constraint=false, weight=1]; + categoryproperty:category_id:w -> category:in3:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_categoryproperty_category", weight=3]; + categoryproperty:property_id:e -> propertyname:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_categoryproperty_property", constraint=false, weight=1]; + categoryattributevalue:category_id:w -> category:in4:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_categoryattributevalue_category", weight=3]; + categoryattributevalue:attributevalue_id:e -> attributevalue:in0:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_categoryattributevalue_attributevalue", constraint=false, weight=1]; + account:company_id:w -> company:in20:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_account_company", weight=3]; payment:account_id:w -> account:in0:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_payment_account", constraint=false, weight=1]; - payment:manifest_id:e -> manifest:in0:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_payment_manifest", weight=3]; - carrier:company_id:e -> company:in16:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_carrier_company", weight=3]; - shipping:manifest_id:sw -> manifest:in4:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_shipping_manifest", weight=3]; + payment:manifest_id:e -> manifest:in7:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_payment_manifest", weight=3]; + carrier:company_id:w -> company:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_carrier_company", weight=3]; + shipping:manifest_id:sw -> manifest:in6:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_shipping_manifest", weight=3]; shipping:carrier_id:e -> carrier:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_shipping_carrier", constraint=false, weight=1]; - package:shipping_id:w -> shipping:in0:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_package_shipping", constraint=false, weight=1]; - package:entityaddress_id:w -> entityaddress:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_package_entityaddress", weight=3]; - ordersummary:company_id:sw -> company:in11:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_ordersummary_company", weight=3]; - ordersummary:manifest_id:e -> manifest:in5:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_ordersummary_manifest", constraint=false, weight=1]; - ordersummary:entity_id:w -> entity:in3:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_ordersummary_entity", constraint=false, weight=1]; - quotesummary:company_id:e -> company:in7:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_quotesummary_company", weight=3]; - quotesummary:manifest_id:sw -> manifest:in3:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_quotesummary_manifest", constraint=false, weight=1]; - quotesummary:entity_id:e -> entity:in2:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_quotesummary_entity", constraint=false, weight=1]; - shipmentsummary:company_id:ne -> company:in15:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_shipmentsummary_company", weight=3]; - shipmentsummary:manifest_id:w -> manifest:in7:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_shipmentsummary_manifest", constraint=false, weight=1]; - shipmentsummary:entity_id:e -> entity:in5:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_shipmentsummary_entity", constraint=false, weight=1]; - deliverysummary:company_id:sw -> company:in10:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_deliverysummary_company", weight=3]; - deliverysummary:manifest_id:e -> manifest:in6:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_deliverysummary_manifest", constraint=false, weight=1]; - deliverysummary:supplier_id:w -> entity:in4:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_deliverysummary_supplier", constraint=false, weight=1]; - articlewarehousesummary:article_id:sw -> article:in11:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_articlewarehousesummary_article", weight=3]; - articlewarehousesummary:warehouse_id:se -> warehouse:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_articlewarehousesummary_warehouse", constraint=false, weight=1]; - mcp_auth_code:google_auth_id:sw -> google_auth:in1:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_mcp_auth_code_google_auth", weight=3]; + package:shipping_id:e -> shipping:in0:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_package_shipping", constraint=false, weight=1]; + package:entityaddress_id:e -> entityaddress:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_package_entityaddress", weight=3]; + ordersummary:company_id:se -> company:in13:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_ordersummary_company", weight=3]; + ordersummary:manifest_id:w -> manifest:in1:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_ordersummary_manifest", constraint=false, weight=1]; + ordersummary:entity_id:e -> entity:in4:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_ordersummary_entity", constraint=false, weight=1]; + quotesummary:company_id:se -> company:in14:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_quotesummary_company", weight=3]; + quotesummary:manifest_id:w -> manifest:in2:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_quotesummary_manifest", constraint=false, weight=1]; + quotesummary:entity_id:e -> entity:in5:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_quotesummary_entity", constraint=false, weight=1]; + shipmentsummary:company_id:se -> company:in15:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_shipmentsummary_company", weight=3]; + shipmentsummary:manifest_id:w -> manifest:in3:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_shipmentsummary_manifest", constraint=false, weight=1]; + shipmentsummary:entity_id:e -> entity:in6:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_shipmentsummary_entity", constraint=false, weight=1]; + deliverysummary:company_id:se -> company:in12:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_deliverysummary_company", weight=3]; + deliverysummary:manifest_id:w -> manifest:in0:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_deliverysummary_manifest", constraint=false, weight=1]; + deliverysummary:supplier_id:se -> entity:in3:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_deliverysummary_supplier", constraint=false, weight=1]; + articlewarehousesummary:article_id:sw -> article:in2:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_articlewarehousesummary_article", weight=3]; + articlewarehousesummary:warehouse_id:se -> warehouse:in1:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_articlewarehousesummary_warehouse", constraint=false, weight=1]; + mcp_auth_code:google_auth_id:se -> google_auth:in1:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_mcp_auth_code_google_auth", weight=3]; mcp_token:google_auth_id:w -> google_auth:in2:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_mcp_token_google_auth", weight=3]; - subagentschedule:company_id:se -> company:in19:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_subagentschedule_company", weight=3]; + subagentschedule:company_id:sw -> company:in5:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_subagentschedule_company", weight=3]; } \ No newline at end of file diff --git a/schema-graph.svg b/schema-graph.svg index e4ad6c8..36260be 100644 --- a/schema-graph.svg +++ b/schema-graph.svg @@ -4,176 +4,265 @@ - - + + schema - + cluster_identity - -Identity & Company + +Identity & Company cluster_i18n - -Localization + +Localization cluster_catalog - -Catalog + +Catalog cluster_media - -Media + +Media cluster_manifests - -Documents & Shipping + +Documents & Shipping cluster_commerce - -Pricing & Payments + +Pricing & Payments cluster_units - -Units + +Units cluster_pos - -POS + +POS cluster_ai - -AI & Models + +AI & Models cluster_attributes - -Properties & Attributes + +Properties & Attributes customergroup - - - - - -customergroup - - -id -INT -PK - - -company_id -? -INT -FK - - -name -NVARCHAR(255) - - -sort -INT - - -updated_at -DATETIME2 + + + + + +customergroup + + +id +INT +PK + + +company_id +? +INT +FK + + +name +NVARCHAR(255) + + +sort +INT + + +updated_at +DATETIME2 - + company - - - - - - - - - - - - - - - - - - - - - - - - - - - -company - - -id -INT -PK - - -root_category_id -? -INT -FK - - -taxrate -? -INT -FK - - -reducedtaxrate -? -INT -FK - - -taxfreerate -? -INT -FK - - -default_language_id -? -INT -FK - - -poscustomergroup_id -INT -FK - - -name -NVARCHAR(255) + + + + + + + + + + + + + + + + + + + + + + + + + + +company + + +id +INT +PK + + +poscustomergroup_id +INT +FK + + +taxrate +? +INT +FK + + +reducedtaxrate +? +INT +FK + + +taxfreerate +? +INT +FK + + +root_category_id +? +INT +FK + + +default_language_id +? +INT +FK + + +name +NVARCHAR(255) -customergroup:sw->company:n +customergroup:nw->company:n - - + + + + + + + +meta + + +meta + + +key +NVARCHAR(255) + + +value +NVARCHAR(MAX) + + + +companyhistory + + +companyhistory + + +id +INT +PK + + +company_id +INT +FK + + +companyuser_id +? +INT +FK + + +date +DATETIME2 + + +text +NVARCHAR(MAX) + + + +companyhistory:sw->company:n + + + + + + + + +companyuser + + + + + + +companyuser + + +id +INT +PK + + +company_id +INT +FK + + +google_auth_id +INT +FK + + + +companyhistory:e->companyuser:n + + + @@ -181,111 +270,111 @@ company:nw->customergroup:n - - + + language - - - - - - -language - - -id -INT -PK - - -iso639 -NVARCHAR(10) + + + + + + +language + + +id +INT +PK + + +iso639 +NVARCHAR(10) company:w->language:n - - + + category - - - - - - - - - - - -category - - -id -INT -PK - - -parent_id -? -INT -FK - - -sort -INT - - -updated_at -DATETIME2 + + + + + + + + + + + +category + + +id +INT +PK + + +parent_id +? +INT +FK + + +sort +INT + + +updated_at +DATETIME2 company:w->category:n - - + + - + tax - - - - - - - -tax - - -id -INT -PK - - -rate -DECIMAL(18,4) + + + + + + + +tax + + +id +INT +PK + + +rate +DECIMAL(18,4) company:w->tax:n - - + + @@ -293,8 +382,8 @@ company:w->tax:n - - + + @@ -302,249 +391,159 @@ company:w->tax:n - - + + - - -meta - - -meta - - -key -NVARCHAR(255) - - -value -NVARCHAR(MAX) + + +numbers + + +numbers + + +id +INT +PK + + +company_id +INT +FK + + +type +NVARCHAR(100) + + +prefix +NVARCHAR(50) + + +padding +INT + + +next +INT - - -companyhistory - - -companyhistory - - -id -INT -PK - - -company_id -INT -FK - - -companyuser_id -? -INT -FK - - -date -DATETIME2 - - -text -NVARCHAR(MAX) - - - -companyhistory:ne->company:n - - - - - - - - -companyuser - - - - - - -companyuser - - -id -INT -PK - - -company_id -INT -FK - - -google_auth_id -INT -FK - - - -companyhistory:e->companyuser:n - - - + + +numbers:se->company:n + + + - + entityaddress - - - -entityaddress - - -id -INT -PK - - -entity_id -INT -FK - - -first_name? -NVARCHAR(255) - - -name? -NVARCHAR(255) - - -street? -NVARCHAR(255) - - -streetnumber? -NVARCHAR(50) - - -zip? -NVARCHAR(50) - - -city? -NVARCHAR(255) - - -county? -NVARCHAR(255) - - -addresstype -NVARCHAR(50) - - -sort -INT + + + +entityaddress + + +id +INT +PK + + +entity_id +INT +FK + + +first_name? +NVARCHAR(255) + + +name? +NVARCHAR(255) + + +street? +NVARCHAR(255) + + +streetnumber? +NVARCHAR(50) + + +zip? +NVARCHAR(50) + + +city? +NVARCHAR(255) + + +county? +NVARCHAR(255) + + +addresstype +NVARCHAR(50) + + +sort +INT entity - - - - - - - - - - - -entity - - -id -INT -PK - - -customergroup_id -INT -FK - - -first_name? -NVARCHAR(255) - - -name -NVARCHAR(255) - - -number? -NVARCHAR(100) - - -created_at -DATETIME2 - - -updated_at -DATETIME2 + + + + + + + + + + + +entity + + +id +INT +PK + + +customergroup_id +INT +FK + + +first_name? +NVARCHAR(255) + + +name +NVARCHAR(255) + + +number? +NVARCHAR(100) + + +created_at +DATETIME2 + + +updated_at +DATETIME2 entityaddress:sw->entity:n - - - - - - - -numbers - - -numbers - - -id -INT -PK - - -company_id -INT -FK - - -type -NVARCHAR(100) - - -prefix -NVARCHAR(50) - - -padding -INT - - -next -INT - - - -numbers:ne->company:n - - - + + @@ -552,128 +551,187 @@ entity:w->customergroup:n - - + + + + + + + +companysetting + + +companysetting + + +id +INT +PK + + +company_id +INT +FK + + +key +NVARCHAR(255) + + +value +NVARCHAR(MAX) + + +frontend +BIT + + +writeonly +BIT + + + +companysetting:se->company:n + + + - + entitycontact - - -entitycontact - - -id -INT -PK - - -entity_id -INT -FK - - -contacttype -NVARCHAR(50) - - -contact -NVARCHAR(255) - - -sort -INT + + +entitycontact + + +id +INT +PK + + +entity_id +INT +FK + + +contacttype +NVARCHAR(50) + + +contact +NVARCHAR(255) + + +sort +INT entitycontact:se->entity:n - - + + - - -companysetting - - -companysetting - - -id -INT -PK - - -company_id -INT -FK - - -key -NVARCHAR(255) - - -value -NVARCHAR(MAX) - - -frontend -BIT - - -writeonly -BIT + + +companyuser:e->company:n + + + + - - -companysetting:w->company:n - - - + + + +google_auth + + + + + +google_auth + + +id +INT +PK + + +selected_company +? +INT +FK + + +email +NVARCHAR(320) + + +picture? +NVARCHAR(2048) + + +picturebinary? +VARBINARY(MAX) + + +sub? +NVARCHAR(255) + + +created_at +DATETIME2 + + + +companyuser:w->google_auth:n + + + - + entityhistory - - -entityhistory - - -id -INT -PK - - -entity_id -INT -FK - - -companyuser_id -? -INT -FK - - -date -DATETIME2 - - -text -NVARCHAR(MAX) + + +entityhistory + + +id +INT +PK + + +entity_id +INT +FK + + +companyuser_id +? +INT +FK + + +date +DATETIME2 + + +text +NVARCHAR(MAX) -entityhistory:sw->entity:n +entityhistory:w->entity:n - - + + @@ -681,67 +739,8 @@ entityhistory:se->companyuser:n - - - - - - - -companyuser:w->company:n - - - - - - - - -google_auth - - - - - -google_auth - - -id -INT -PK - - -selected_company -? -INT -FK - - -email -NVARCHAR(320) - - -picture? -NVARCHAR(2048) - - -picturebinary? -VARBINARY(MAX) - - -sub? -NVARCHAR(255) - - -created_at -DATETIME2 - - - -companyuser:e->google_auth:n - - - + + @@ -749,55 +748,55 @@ google_auth:w->company:n - - + + categorytext - - -categorytext - - -id -INT -PK - - -category_id -INT -FK - - -language_id -INT -FK - - -name -NVARCHAR(255) - - -slug -NVARCHAR(255) - - -seo? -NVARCHAR(MAX) - - -desc? -NVARCHAR(MAX) + + +categorytext + + +id +INT +PK + + +category_id +INT +FK + + +language_id +INT +FK + + +name +NVARCHAR(255) + + +slug +NVARCHAR(255) + + +seo? +NVARCHAR(MAX) + + +desc? +NVARCHAR(MAX) categorytext:e->language:n - - + + @@ -805,280 +804,280 @@ categorytext:w->category:n - - + + articletext - - -articletext - - -id -INT -PK - - -article_id -INT -FK - - -language_id -INT -FK - - -name -NVARCHAR(255) - - -slug -NVARCHAR(255) - - -seo? -NVARCHAR(MAX) - - -desc? -NVARCHAR(MAX) + + +articletext + + +id +INT +PK + + +article_id +INT +FK + + +language_id +INT +FK + + +name +NVARCHAR(255) + + +slug +NVARCHAR(255) + + +seo? +NVARCHAR(MAX) + + +desc? +NVARCHAR(MAX) articletext:w->language:n - - + + article - - - - - - - - - - - - - - - -article - - -id -INT -PK - - -parentattributename_id -? -INT -FK - - -parentarticle_id -? -INT -FK - - -articlelist_id -? -INT -FK - - -optionslist_id -? -INT -FK - - -brand_id -? -INT -FK - - -unit_id -INT -FK - - -company_id -INT -FK - - -sku? -NVARCHAR(100) - - -unitamount -FLOAT - - -weight -FLOAT - - -track_stock -BIT - - -is_parent -BIT - - -parentsort -INT - - -created_at -DATETIME2 - - -updated_at -DATETIME2 + + + + + + + + + + + + + + + +article + + +id +INT +PK + + +company_id +INT +FK + + +parentattributename_id +? +INT +FK + + +parentarticle_id +? +INT +FK + + +articlelist_id +? +INT +FK + + +optionslist_id +? +INT +FK + + +brand_id +? +INT +FK + + +unit_id +INT +FK + + +sku? +NVARCHAR(100) + + +unitamount +FLOAT + + +weight +FLOAT + + +track_stock +BIT + + +is_parent +BIT + + +parentsort +INT + + +created_at +DATETIME2 + + +updated_at +DATETIME2 articletext:e->article:n - - + + unittext - - -unittext - - -id -INT -PK - - -language_id -INT -FK - - -unit_id -INT -FK - - -symbol -NVARCHAR(50) - - -name -NVARCHAR(255) + + +unittext + + +id +INT +PK + + +language_id +INT +FK + + +unit_id +INT +FK + + +symbol +NVARCHAR(50) + + +name +NVARCHAR(255) -unittext:w->language:n +unittext:e->language:n - - + + - + unit - - - - -unit - - -id -INT -PK - - -company_id -INT -FK - - -si -NVARCHAR(50) - - -basesi -NVARCHAR(50) - - -basesifactor -FLOAT + + + + +unit + + +id +INT +PK + + +company_id +INT +FK + + +si +NVARCHAR(50) + + +basesi +NVARCHAR(50) + + +basesifactor +FLOAT -unittext:sw->unit:n +unittext:se->unit:n - - + + categoryarticle - - -categoryarticle - - -id -INT -PK - - -category_id -INT -FK - - -article_id -INT -FK + + +categoryarticle + + +id +INT +PK + + +category_id +INT +FK + + +article_id +INT +FK -categoryarticle:nw->category:n +categoryarticle:se->category:n - - + + -categoryarticle:nw->article:n +categoryarticle:sw->article:n - - + + @@ -1086,70 +1085,70 @@ category:e->category:e - - + + articlehistory - - -articlehistory - - -id -INT -PK - - -article_id -INT -FK - - -companyuser_id -? -INT -FK - - -date -DATETIME2 - - -text -NVARCHAR(MAX) - - -meta? -NVARCHAR(MAX) + + +articlehistory + + +id +INT +PK + + +companyuser_id +? +INT +FK + + +article_id +INT +FK + + +date +DATETIME2 + + +text +NVARCHAR(MAX) + + +meta? +NVARCHAR(MAX) articlehistory:e->companyuser:n - - + + -articlehistory:se->article:n +articlehistory:sw->article:n - - + + -article:e->company:n +article:w->company:n - - + + @@ -1157,90 +1156,90 @@ article:e->article:e - - + + articlelist - - - - -articlelist - - -id -INT -PK + + + + +articlelist + + +id +INT +PK article:w->articlelist:n - - + + optionslist - - - - -optionslist - - -id -INT -PK + + + + +optionslist + + +id +INT +PK article:w->optionslist:n - - + + brand - - - - -brand - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -gsprpinfo? -NVARCHAR(MAX) + + + + +brand + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +gsprpinfo? +NVARCHAR(MAX) article:w->brand:n - - + + @@ -1248,202 +1247,202 @@ article:e->unit:n - - + + - + attributename - - - - - -attributename - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -sort -INT - - -exclusive -BIT + + + + + +attributename + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +sort +INT + + +exclusive +BIT -article:ne->attributename:n +article:se->attributename:n - - + + -article:ne->attributename:n +article:se->attributename:n - - + + articleean - - -articleean - - -id -INT -PK - - -article_id -INT -FK - - -ean -NVARCHAR(50) + + +articleean + + +id +INT +PK + + +article_id +INT +FK + + +ean +NVARCHAR(50) -articleean:sw->article:n +articleean:se->article:n - - + + articlesupplier - - -articlesupplier - - -id -INT -PK - - -article_id -INT -FK - - -tax_id -? -INT -FK - - -entity_id -INT -FK - - -net? -FLOAT - - -sku? -NVARCHAR(100) - - -stock? -FLOAT - - -pu -FLOAT - - -sort -INT + + +articlesupplier + + +id +INT +PK + + +entity_id +INT +FK + + +tax_id +? +INT +FK + + +article_id +INT +FK + + +net? +FLOAT + + +sku? +NVARCHAR(100) + + +stock? +FLOAT + + +pu +FLOAT + + +sort +INT articlesupplier:e->entity:n - - + + -articlesupplier:sw->article:n +articlesupplier:se->article:n - - + + -articlesupplier:nw->tax:n +articlesupplier:e->tax:n - - + + articlelistarticle - - -articlelistarticle - - -id -INT -PK - - -article_id -INT -FK - - -articlelist_id -INT -FK - - -count -INT - - -sort -INT + + +articlelistarticle + + +id +INT +PK + + +article_id +INT +FK + + +articlelist_id +INT +FK + + +count +INT + + +sort +INT articlelistarticle:w->article:n - - + + @@ -1451,51 +1450,51 @@ articlelistarticle:se->articlelist:n - - + + optionslistarticle - - -optionslistarticle - - -id -INT -PK - - -article_id -INT -FK - - -optionslist_id -INT -FK - - -count -INT - - -sort -INT - - -mandated -BIT + + +optionslistarticle + + +id +INT +PK + + +article_id +INT +FK + + +optionslist_id +INT +FK + + +count +INT + + +sort +INT + + +mandated +BIT -optionslistarticle:w->article:n +optionslistarticle:e->article:n - - + + @@ -1503,8 +1502,8 @@ optionslistarticle:sw->optionslist:n - - + + @@ -1512,233 +1511,183 @@ brand:e->company:n - - + + - + -articletombstone - - -articletombstone - - -id -INT -PK - - -company_id -INT -FK - - -article_id? -INT - - -sku? -NVARCHAR(100) - - -name? -NVARCHAR(255) - - -taxrate? -DECIMAL(18,4) - - -net? -FLOAT - - -deleted_at -DATETIME2 - - - -articletombstone:e->company:n - - - - - +pic + + + + + + +pic + + +id +INT +PK + + +w +INT + + +h +INT + + +size +BIGINT + + +hash +NVARCHAR(64) + + +thumbw +INT + + +thumbh +INT + + +thumbhash +NVARCHAR(64) + + +smallthumbw +INT + + +smallthumbh +INT + + +source +NVARCHAR(MAX) + + +fullbinary +VARBINARY(MAX) + + +thumbbinary +VARBINARY(MAX) + + +smallthumbbinary +VARBINARY(MAX) attributevaluepic - - -attributevaluepic - - -id -INT -PK - - -attributevalue_id -INT -FK - - -pic_id -INT -FK - - -sort -INT - - - -pic - - - - - - -pic - - -id -INT -PK - - -w -INT - - -h -INT - - -size -BIGINT - - -hash -NVARCHAR(64) - - -thumbw -INT - - -thumbh -INT - - -thumbhash -NVARCHAR(64) - - -smallthumbw -INT - - -smallthumbh -INT - - -source -NVARCHAR(MAX) - - -fullbinary -VARBINARY(MAX) - - -thumbbinary -VARBINARY(MAX) - - -smallthumbbinary -VARBINARY(MAX) + + +attributevaluepic + + +id +INT +PK + + +attributevalue_id +INT +FK + + +pic_id +INT +FK + + +sort +INT -attributevaluepic:e->pic:n +attributevaluepic:w->pic:n - - + + - + attributevalue - - - - - -attributevalue - - -id -INT -PK - - -attribute_id -INT -FK - - -value -NVARCHAR(255) - - -sort -INT + + + + + +attributevalue + + +id +INT +PK + + +attribute_id +INT +FK + + +value +NVARCHAR(255) + + +sort +INT -attributevaluepic:w->attributevalue:n +attributevaluepic:e->attributevalue:n - - + + categorypic - - -categorypic - - -id -INT -PK - - -category_id -INT -FK - - -pic_id -INT -FK - - -sort -INT + + +categorypic + + +id +INT +PK + + +category_id +INT +FK + + +pic_id +INT +FK + + +sort +INT categorypic:sw->category:n - - + + @@ -1746,43 +1695,43 @@ categorypic:e->pic:n - - + + articlepic - - -articlepic - - -id -INT -PK - - -pic_id -INT -FK - - -article_id -INT -FK - - -sort -INT + + +articlepic + + +id +INT +PK + + +article_id +INT +FK + + +pic_id +INT +FK + + +sort +INT -articlepic:ne->article:n +articlepic:sw->article:n - - + + @@ -1790,43 +1739,43 @@ articlepic:e->pic:n - - + + - + brandpic - - -brandpic - - -id -INT -PK - - -pic_id -INT -FK - - -brand_id -INT -FK - - -sort -INT + + +brandpic + + +id +INT +PK + + +pic_id +INT +FK + + +brand_id +INT +FK + + +sort +INT -brandpic:w->brand:n +brandpic:sw->brand:n - - + + @@ -1834,538 +1783,399 @@ brandpic:w->pic:n - - + + - + file - - - -file - - -id -INT -PK - - -hash -NVARCHAR(64) - - -mimetype -NVARCHAR(255) - - -name -NVARCHAR(255) - - -size -BIGINT - - -created -DATETIME2 - - -modified -DATETIME2 - - -content -VARBINARY(MAX) - - -thumbavif? -VARBINARY(MAX) - - -thumbx? -INT - - -thumby? -INT - - -meta? -NVARCHAR(MAX) + + + +file + + +id +INT +PK + + +hash +NVARCHAR(64) + + +mimetype +NVARCHAR(255) + + +name +NVARCHAR(255) + + +size +BIGINT + + +created +DATETIME2 + + +modified +DATETIME2 + + +content +VARBINARY(MAX) + + +thumbavif? +VARBINARY(MAX) + + +thumbx? +INT + + +thumby? +INT + + +meta? +NVARCHAR(MAX) - - -articlewarehousesummary - - -articlewarehousesummary - - -id -INT -PK - - -article_id -INT -FK - - -warehouse_id -INT -FK - - -stock -FLOAT + + +deliverysummary + + +deliverysummary + + +id +INT +PK + + +company_id +INT +FK + + +supplier_id +? +INT +FK + + +manifest_id +INT +FK + + +delivery_number +NVARCHAR(100) + + +external_number? +NVARCHAR(100) + + +delivery_date +DATETIME2 + + +created_at +DATETIME2 + + +supplier_name? +NVARCHAR(255) + + +positions +INT + + +gross_total +FLOAT + + +net_total +FLOAT + + +total_quantity +FLOAT + + +stock_positions +INT + + +booked_positions +INT + + +unbooked_positions +INT + + +stock_quantity +FLOAT + + +booked_quantity +FLOAT + + +unbooked_quantity +FLOAT + + +is_booked +TINYINT - - -articlewarehousesummary:sw->article:n - - - + + +deliverysummary:se->company:n + + + - - -warehouse - - - - -warehouse - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -sort -INT - - - -articlewarehousesummary:se->warehouse:n - - - - - - - - -ledger - - -ledger - - -id -INT -PK - - -warehouse_id -? -INT -FK - - -manifestarticle_id -INT -FK - - -transaction_type -NVARCHAR(100) - - -amount -FLOAT - - -transaction_text -NVARCHAR(MAX) - - -hash_version -INT - - -prev_hash? -NVARCHAR(128) - - -created_at -DATETIME2 - - - -ledger:se->warehouse:n - - - - - - - - -manifestarticle - - - -manifestarticle - - -id -INT -PK - - -manifest_id -INT -FK - - -sku? -NVARCHAR(100) - - -name? -NVARCHAR(255) - - -pu -FLOAT - - -amount -FLOAT - - -net -FLOAT - - -comment? -NVARCHAR(MAX) - - -rebate -FLOAT - - -taxrate -FLOAT - - - -ledger:w->manifestarticle:n - - - - - - - - -warehouse:e->company:n - - - + + +deliverysummary:se->entity:n + + + - -manifest - - - - - - - - - - -manifest - - -id -INT -PK - - -company_id -INT -FK - - -entity_id -? -INT -FK - - -number -NVARCHAR(100) - - -type -NVARCHAR(100) - - -external_number? -NVARCHAR(100) - - -date -DATETIME2 - - -created_at -DATETIME2 - - - -manifestarticle:se->manifest:n - - - - - - - - -manifest:e->company:n - - - - - - - - -manifest:e->entity:n - - - - - - - -manifestattachment - - -manifestattachment - - -id -INT -PK - - -file_id -INT -FK - - -manifest_id -INT -FK - - -sort -INT +manifest + + + + + + + + + + +manifest + + +id +INT +PK + + +company_id +INT +FK + + +entity_id +? +INT +FK + + +number +NVARCHAR(100) + + +type +NVARCHAR(100) + + +external_number? +NVARCHAR(100) + + +date +DATETIME2 + + +created_at +DATETIME2 - - -manifestattachment:w->file:n - - - + + +deliverysummary:w->manifest:n + + + - - -manifestattachment:sw->manifest:n - - - + + +ordersummary + + +ordersummary + + +id +INT +PK + + +company_id +INT +FK + + +entity_id +? +INT +FK + + +manifest_id +INT +FK + + +order_number +NVARCHAR(100) + + +order_date +DATETIME2 + + +created_at +DATETIME2 + + +customer_name? +NVARCHAR(255) + + +positions +INT + + +gross_total +FLOAT + + +paid_total +FLOAT + + +ordered_quantity +FLOAT + + +shipped_quantity +FLOAT + + +is_paid +TINYINT + + +is_shipped +TINYINT + + + +ordersummary:se->company:n + + + - - -shipping - - - -shipping - - -id -INT -PK - - -manifest_id -INT -FK - - -carrier_id -INT -FK - - -number -NVARCHAR(100) - - -tracking_code? -NVARCHAR(255) - - -type -NVARCHAR(100) - - -state -NVARCHAR(100) - - - -shipping:sw->manifest:n - - - + + +ordersummary:e->entity:n + + + - - -carrier - - - -carrier - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -sort -INT - - -has_packages -BIT - - -is_reverse -BIT - - - -shipping:e->carrier:n - - - + + +ordersummary:w->manifest:n + + + - + quotesummary - - -quotesummary - - -id -INT -PK - - -manifest_id -INT -FK - - -company_id -INT -FK - - -entity_id -? -INT -FK - - -quote_number -NVARCHAR(100) - - -quote_date -DATETIME2 - - -created_at -DATETIME2 - - -customer_name? -NVARCHAR(255) - - -positions -INT - - -gross_total -FLOAT - - -total_quantity -FLOAT + + +quotesummary + + +id +INT +PK + + +company_id +INT +FK + + +entity_id +? +INT +FK + + +manifest_id +INT +FK + + +quote_number +NVARCHAR(100) + + +quote_date +DATETIME2 + + +created_at +DATETIME2 + + +customer_name? +NVARCHAR(255) + + +positions +INT + + +gross_total +FLOAT + + +total_quantity +FLOAT -quotesummary:e->company:n +quotesummary:se->company:n - - + + @@ -2373,376 +2183,102 @@ quotesummary:e->entity:n - - + + -quotesummary:sw->manifest:n +quotesummary:w->manifest:n - - - - - - - -ordersummary - - -ordersummary - - -id -INT -PK - - -manifest_id -INT -FK - - -company_id -INT -FK - - -entity_id -? -INT -FK - - -order_number -NVARCHAR(100) - - -order_date -DATETIME2 - - -created_at -DATETIME2 - - -customer_name? -NVARCHAR(255) - - -positions -INT - - -gross_total -FLOAT - - -paid_total -FLOAT - - -ordered_quantity -FLOAT - - -shipped_quantity -FLOAT - - -is_paid -TINYINT - - -is_shipped -TINYINT - - - -ordersummary:sw->company:n - - - - - - - - -ordersummary:w->entity:n - - - - - - - - -ordersummary:e->manifest:n - - - - - - - - -package - - -package - - -id -INT -PK - - -shipping_id -INT -FK - - -entityaddress_id -INT -FK - - -number -NVARCHAR(100) - - -type -NVARCHAR(100) - - -state -NVARCHAR(100) - - -details? -NVARCHAR(MAX) - - - -package:w->entityaddress:n - - - - - - - - -package:w->shipping:n - - - - - - - - -deliverysummary - - -deliverysummary - - -id -INT -PK - - -manifest_id -INT -FK - - -company_id -INT -FK - - -supplier_id -? -INT -FK - - -delivery_number -NVARCHAR(100) - - -external_number? -NVARCHAR(100) - - -delivery_date -DATETIME2 - - -created_at -DATETIME2 - - -supplier_name? -NVARCHAR(255) - - -positions -INT - - -gross_total -FLOAT - - -net_total -FLOAT - - -total_quantity -FLOAT - - -stock_positions -INT - - -booked_positions -INT - - -unbooked_positions -INT - - -stock_quantity -FLOAT - - -booked_quantity -FLOAT - - -unbooked_quantity -FLOAT - - -is_booked -TINYINT - - - -deliverysummary:sw->company:n - - - - - - - - -deliverysummary:w->entity:n - - - - - - - - -deliverysummary:e->manifest:n - - - + + - + shipmentsummary - - -shipmentsummary - - -id -INT -PK - - -manifest_id -INT -FK - - -company_id -INT -FK - - -entity_id -? -INT -FK - - -shipment_number -NVARCHAR(100) - - -shipment_date -DATETIME2 - - -created_at -DATETIME2 - - -order_id? -INT - - -order_number? -NVARCHAR(100) - - -customer_name? -NVARCHAR(255) - - -positions -INT - - -total_quantity -FLOAT - - -package_count -INT - - -carrier? -NVARCHAR(100) - - -tracking_code? -NVARCHAR(255) - - -state -NVARCHAR(50) + + +shipmentsummary + + +id +INT +PK + + +company_id +INT +FK + + +entity_id +? +INT +FK + + +manifest_id +INT +FK + + +shipment_number +NVARCHAR(100) + + +shipment_date +DATETIME2 + + +created_at +DATETIME2 + + +order_id? +INT + + +order_number? +NVARCHAR(100) + + +customer_name? +NVARCHAR(255) + + +positions +INT + + +total_quantity +FLOAT + + +package_count +INT + + +carrier? +NVARCHAR(100) + + +tracking_code? +NVARCHAR(255) + + +state +NVARCHAR(50) -shipmentsummary:ne->company:n +shipmentsummary:se->company:n - - + + @@ -2750,8 +2286,8 @@ shipmentsummary:e->entity:n - - + + @@ -2759,312 +2295,782 @@ shipmentsummary:w->manifest:n - - + + - - -price - - -price - - -id -INT -PK - - -article_id -INT -FK - - -tax_id -INT -FK - - -customergroup_id -INT -FK - - -minmultiplier -DECIMAL(18,4) - - -net -FLOAT + + +package + + +package + + +id +INT +PK + + +entityaddress_id +INT +FK + + +shipping_id +INT +FK + + +number +NVARCHAR(100) + + +type +NVARCHAR(100) + + +state +NVARCHAR(100) + + +details? +NVARCHAR(MAX) - - -price:e->customergroup:n - - - + + +package:e->entityaddress:n + + + - - -price:sw->article:n - - - + + +shipping + + + +shipping + + +id +INT +PK + + +carrier_id +INT +FK + + +manifest_id +INT +FK + + +number +NVARCHAR(100) + + +tracking_code? +NVARCHAR(255) + + +type +NVARCHAR(100) + + +state +NVARCHAR(100) + + + +package:e->shipping:n + + + - - -price:e->tax:n - - - + + +manifestarticle + + + +manifestarticle + + +id +INT +PK + + +manifest_id +INT +FK + + +sku? +NVARCHAR(100) + + +name? +NVARCHAR(255) + + +pu +FLOAT + + +amount +FLOAT + + +net +FLOAT + + +comment? +NVARCHAR(MAX) + + +rebate +FLOAT + + +taxrate +FLOAT + + +shippable +TINYINT + + + +manifestarticle:sw->manifest:n + + + - - -account - - - -account - - -id -INT -PK - - -company_id -INT -FK - - -type -NVARCHAR(100) - - -name -NVARCHAR(255) + + +manifest:w->company:n + + + + - - -account:e->company:n - - - + + + +manifest:e->entity:n + + + + + + + + +manifestattachment + + +manifestattachment + + +id +INT +PK + + +manifest_id +INT +FK + + +file_id +INT +FK + + +sort +INT + + + +manifestattachment:w->file:n + + + + + + + + +manifestattachment:ne->manifest:n + + + + + + + + +shipping:sw->manifest:n + + + + + + + + +carrier + + + +carrier + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +sort +INT + + +has_packages +BIT + + +is_reverse +BIT + + + +shipping:e->carrier:n + + + + + + + + +warehouse + + + + +warehouse + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +sort +INT + + + +warehouse:e->company:n + + + + + + + + +ledger + + +ledger + + +id +INT +PK + + +manifestarticle_id +INT +FK + + +warehouse_id +? +INT +FK + + +transaction_type +NVARCHAR(100) + + +amount +FLOAT + + +transaction_text +NVARCHAR(MAX) + + +hash_version +INT + + +prev_hash? +NVARCHAR(128) + + +created_at +DATETIME2 + + + +ledger:w->manifestarticle:n + + + + + + + + +ledger:sw->warehouse:n + + + + + + + + +articlewarehousesummary + + +articlewarehousesummary + + +id +INT +PK + + +warehouse_id +INT +FK + + +article_id +INT +FK + + +stock +FLOAT + + + +articlewarehousesummary:sw->article:n + + + + + + + + +articlewarehousesummary:se->warehouse:n + + + - + payment - - -payment - - -id -INT -PK - - -account_id -INT -FK - - -manifest_id -INT -FK - - -type -NVARCHAR(100) - - -amount -FLOAT + + +payment + + +id +INT +PK + + +manifest_id +INT +FK + + +account_id +INT +FK + + +type +NVARCHAR(100) + + +amount +FLOAT payment:e->manifest:n - - + + + + +account + + + +account + + +id +INT +PK + + +company_id +INT +FK + + +type +NVARCHAR(100) + + +name +NVARCHAR(255) + payment:w->account:n - - + + + + + + + +account:w->company:n + + + + + + + + +price + + +price + + +id +INT +PK + + +customergroup_id +INT +FK + + +tax_id +INT +FK + + +article_id +INT +FK + + +minmultiplier +DECIMAL(18,4) + + +net +FLOAT + + + +price:e->customergroup:n + + + + + + + + +price:nw->article:n + + + + + + + + +price:w->tax:n + + + -unit:w->company:n +unit:e->company:n - - - - - - - -posterminalcategory - - -posterminalcategory - - -id -INT -PK - - -category_id -INT -FK - - -posterminal_id -INT -FK - - - -posterminalcategory:w->category:n - - - - - - - - -posterminal - - - -posterminal - - -id -INT -PK - - -root_category_id -? -INT -FK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -token? -NVARCHAR(255) - - -pairingpin? -NVARCHAR(50) - - -paired_at? -DATETIME2 - - -clientserial? -NVARCHAR(255) - - -maxknowntombstoneid? -INT - - -sync_root_articles -BIT - - -lastseen_at? -DATETIME2 - - -updated_at -DATETIME2 - - - -posterminalcategory:se->posterminal:n - - - + + - + printer - - -printer - - -id -INT -PK - - -company_id -INT -FK - - -address -NVARCHAR(255) - - -type -NVARCHAR(50) - - -model? -NVARCHAR(255) - - -serial? -NVARCHAR(255) - - -sort -INT - - -desc? -NVARCHAR(MAX) + + +printer + + +id +INT +PK + + +company_id +INT +FK + + +address +NVARCHAR(255) + + +type +NVARCHAR(50) + + +model? +NVARCHAR(255) + + +serial? +NVARCHAR(255) + + +sort +INT + + +desc? +NVARCHAR(MAX) -printer:e->company:n +printer:w->company:n - - + + + + + + + +labeltemplate + + +labeltemplate + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +width +INT + + +height +INT + + +dpi +INT + + +type +NVARCHAR(50) + + +content +NVARCHAR(MAX) + + +thumb? +VARBINARY(MAX) + + + +labeltemplate:e->company:n + + + + + + + + +posterminalobituary + + +posterminalobituary + + +id +INT +PK + + +posterminal_id +INT +FK + + +entity_type +NVARCHAR(50) + + +entity_id +INT + + +created_at +DATETIME2 + + + +posterminal + + + + +posterminal + + +id +INT +PK + + +company_id +INT +FK + + +root_category_id +? +INT +FK + + +name +NVARCHAR(255) + + +token? +NVARCHAR(255) + + +pairingpin? +NVARCHAR(50) + + +paired_at? +DATETIME2 + + +clientserial? +NVARCHAR(255) + + +maxknownobituaryid? +INT + + +sync_root_articles +BIT + + +lastseen_at? +DATETIME2 + + +updated_at +DATETIME2 + + + +posterminalobituary:se->posterminal:n + + + @@ -3072,8 +3078,8 @@ posterminal:e->company:n - - + + @@ -3081,448 +3087,254 @@ posterminal:w->category:n - - + + - + -labeltemplate - - -labeltemplate - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -width -INT - - -height -INT - - -dpi -INT - - -type -NVARCHAR(50) - - -content -NVARCHAR(MAX) - - -thumb? -VARBINARY(MAX) +posterminalcategory + + +posterminalcategory + + +id +INT +PK + + +posterminal_id +INT +FK + + +category_id +INT +FK - - -labeltemplate:e->company:n - - - + + +posterminalcategory:w->category:n + + + + + + + + +posterminalcategory:se->posterminal:n + + + modelvfs - - -modelvfs - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -mime -NVARCHAR(100) - - -content -VARBINARY(MAX) - - -meta -NVARCHAR(MAX) - - -created_at -DATETIME2 - - -updated_at -DATETIME2 + + +modelvfs + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +mime +NVARCHAR(100) + + +content +VARBINARY(MAX) + + +meta +NVARCHAR(MAX) + + +created_at +DATETIME2 + + +updated_at +DATETIME2 -modelvfs:se->company:n +modelvfs:sw->company:n - - + + subagentschedule - - -subagentschedule - - -id -INT -PK - - -company_id -INT -FK - - -desc? -NVARCHAR(MAX) - - -prompt -NVARCHAR(MAX) - - -skills? -NVARCHAR(MAX) - - -lastagentnote? -NVARCHAR(MAX) - - -max_itr -INT - - -cron -NVARCHAR(100) - - -created_at -DATETIME2 - - -lastrun_at? -DATETIME2 + + +subagentschedule + + +id +INT +PK + + +company_id +INT +FK + + +desc? +NVARCHAR(MAX) + + +prompt +NVARCHAR(MAX) + + +skills? +NVARCHAR(MAX) + + +lastagentnote? +NVARCHAR(MAX) + + +max_itr +INT + + +cron +NVARCHAR(100) + + +created_at +DATETIME2 + + +lastrun_at? +DATETIME2 -subagentschedule:se->company:n +subagentschedule:sw->company:n - - + + modelconversation - - - -modelconversation - - -id -INT -PK - - -companyuser_id -INT -FK - - -provider -NVARCHAR(100) - - -model -NVARCHAR(255) - - -created_at -DATETIME2 - - -updated_at -DATETIME2 - - -state -NVARCHAR(20) - - -started_by? -INT + + + +modelconversation + + +id +INT +PK + + +companyuser_id +INT +FK + + +provider +NVARCHAR(100) + + +model +NVARCHAR(255) + + +created_at +DATETIME2 + + +updated_at +DATETIME2 + + +state +NVARCHAR(20) + + +started_by? +INT modelconversation:w->companyuser:n - - + + modelmessage - - -modelmessage - - -id -INT -PK - - -conversation_id -INT -FK - - -created_at -DATETIME2 - - -role -NVARCHAR(20) - - -message -NVARCHAR(MAX) + + +modelmessage + + +id +INT +PK + + +conversation_id +INT +FK + + +created_at +DATETIME2 + + +role +NVARCHAR(20) + + +message +NVARCHAR(MAX) -modelmessage:sw->modelconversation:n +modelmessage:se->modelconversation:n - - - - - - - -propertyname - - - - -propertyname - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -sort -INT - - -exclusive -BIT - - - -propertyname:e->company:n - - - + + -attributevalue:e->attributename:n +attributevalue:se->attributename:n - - - - - - - -categoryproperty - - -categoryproperty - - -id -INT -PK - - -property_id -INT -FK - - -category_id -INT -FK - - -value -NVARCHAR(MAX) - - -sort -INT - - - -categoryproperty:e->category:n - - - - - - - - -categoryproperty:w->propertyname:n - - - - - - - - -categoryattributevalue - - -categoryattributevalue - - -id -INT -PK - - -attributevalue_id -INT -FK - - -category_id -INT -FK - - -sort -INT - - - -categoryattributevalue:e->category:n - - - - - - - - -categoryattributevalue:w->attributevalue:n - - - - - - - - -articleproperty - - -articleproperty - - -id -INT -PK - - -property_id -INT -FK - - -article_id -INT -FK - - -value -NVARCHAR(MAX) - - -sort -INT - - - -articleproperty:w->article:n - - - - - - - - -articleproperty:w->propertyname:n - - - + + @@ -3530,243 +3342,443 @@ attributename:e->company:n - - + + + + + + + +propertyname + + + + +propertyname + + +id +INT +PK + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +sort +INT + + +exclusive +BIT + + + +propertyname:e->company:n + + + + + + + + +categoryproperty + + +categoryproperty + + +id +INT +PK + + +property_id +INT +FK + + +category_id +INT +FK + + +value +NVARCHAR(MAX) + + +sort +INT + + + +categoryproperty:w->category:n + + + + + + + + +categoryproperty:e->propertyname:n + + + + + + + + +categoryattributevalue + + +categoryattributevalue + + +id +INT +PK + + +attributevalue_id +INT +FK + + +category_id +INT +FK + + +sort +INT + + + +categoryattributevalue:w->category:n + + + + + + + + +categoryattributevalue:e->attributevalue:n + + + + + + + + +articleproperty + + +articleproperty + + +id +INT +PK + + +property_id +INT +FK + + +article_id +INT +FK + + +value +NVARCHAR(MAX) + + +sort +INT + + + +articleproperty:w->article:n + + + + + + + + +articleproperty:e->propertyname:n + + + articleattributevalue - - -articleattributevalue - - -id -INT -PK - - -attributevalue_id -INT -FK - - -article_id -INT -FK - - -sort -INT + + +articleattributevalue + + +id +INT +PK + + +attributevalue_id +INT +FK + + +article_id +INT +FK + + +sort +INT articleattributevalue:e->article:n - - + + -articleattributevalue:w->attributevalue:n +articleattributevalue:e->attributevalue:n - - + + -carrier:e->company:n +carrier:w->company:n - - + + - - -mcp_client - - -mcp_client - - -id -INT -PK - - -client_id -NVARCHAR(100) - - -client_secret? -NVARCHAR(255) - - -client_name -NVARCHAR(255) - - -redirect_uris -NVARCHAR(MAX) - - -grant_types? -NVARCHAR(255) - - -response_types? -NVARCHAR(255) - - -scope? -NVARCHAR(255) - - -created_at -DATETIME2 - - + mcp_auth_code - - -mcp_auth_code - - -code -NVARCHAR(128) -PK - - -google_auth_id -INT -FK - - -client_id -NVARCHAR(100) - - -redirect_uri -NVARCHAR(2048) - - -code_challenge -NVARCHAR(255) - - -code_challenge_method -NVARCHAR(32) - - -scope? -NVARCHAR(255) - - -expires_at -DATETIME2 - - -used -TINYINT - - -created_at -DATETIME2 + + +mcp_auth_code + + +code +NVARCHAR(128) +PK + + +google_auth_id +INT +FK + + +client_id +NVARCHAR(100) + + +redirect_uri +NVARCHAR(2048) + + +code_challenge +NVARCHAR(255) + + +code_challenge_method +NVARCHAR(32) + + +scope? +NVARCHAR(255) + + +expires_at +DATETIME2 + + +used +TINYINT + + +created_at +DATETIME2 -mcp_auth_code:sw->google_auth:n +mcp_auth_code:se->google_auth:n - - + + - + mcp_token - - -mcp_token - - -id -INT -PK - - -google_auth_id -INT -FK - - -refresh_token -NVARCHAR(128) - - -client_id -NVARCHAR(100) - - -scope? -NVARCHAR(255) - - -expires_at -DATETIME2 - - -revoked -TINYINT - - -created_at -DATETIME2 + + +mcp_token + + +id +INT +PK + + +google_auth_id +INT +FK + + +refresh_token +NVARCHAR(128) + + +client_id +NVARCHAR(100) + + +scope? +NVARCHAR(255) + + +expires_at +DATETIME2 + + +revoked +TINYINT + + +created_at +DATETIME2 mcp_token:w->google_auth:n - - + + - + + +mcp_client + + +mcp_client + + +id +INT +PK + + +client_id +NVARCHAR(100) + + +client_secret? +NVARCHAR(255) + + +client_name +NVARCHAR(255) + + +redirect_uris +NVARCHAR(MAX) + + +grant_types? +NVARCHAR(255) + + +response_types? +NVARCHAR(255) + + +scope? +NVARCHAR(255) + + +created_at +DATETIME2 + + +healthcheck + + +healthcheck + + +id +INT +PK + + +sequence +BIGINT + + +updated_at +DATETIME2 + + + __legend - - - -Legend - -PK - -primary key - -FK - -foreign key - -? - -nullable column - -— - -FOREIGN KEY constraint - -- - - -naming convention only, no constraint + + + +Legend + +PK + +primary key + +FK + +foreign key + +? + +nullable column + +— + +FOREIGN KEY constraint + +- - + +naming convention only, no constraint diff --git a/scripts/test-category-delete-recursive.js b/scripts/test-category-delete-recursive.js index ae2e3a6..cb655bf 100644 --- a/scripts/test-category-delete-recursive.js +++ b/scripts/test-category-delete-recursive.js @@ -174,8 +174,8 @@ async function run() { () => store.article.getBySku(googleAuthId, artOnlySub.sku), /Article not found/ ); - // tombstone for artOnlySub exists - const t1 = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artOnlySub.id); + // obituary for artOnlySub exists + const t1 = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artOnlySub.id); assert.equal(t1.length, 1); // artParent and its child artChild: both deleted @@ -187,8 +187,8 @@ async function run() { () => store.article.getBySku(googleAuthId, artChild.article.sku), /Article not found/ ); - const tParent = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artParent.id); - const tChild = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artChild.article.id); + const tParent = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artParent.id); + const tChild = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artChild.article.id); assert.equal(tParent.length, 1); assert.equal(tChild.length, 1); diff --git a/scripts/test-tombstone.js b/scripts/test-obituary.js similarity index 58% rename from scripts/test-tombstone.js rename to scripts/test-obituary.js index 9e3768c..b1994de 100644 --- a/scripts/test-tombstone.js +++ b/scripts/test-obituary.js @@ -6,9 +6,9 @@ import LibDashStore from '../src/index.js'; import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js'; async function run() { - console.log('--- Testing posterminaltombstone table and deletion flow ---'); + console.log('--- Testing posterminalobituary table and deletion flow ---'); - const tempDir = mkdtempSync(join(tmpdir(), 'test-tombstone-')); + const tempDir = mkdtempSync(join(tmpdir(), 'test-obituary-')); const dbFile = join(tempDir, 'test.db'); const storageDir = join(tempDir, 'storage'); @@ -21,11 +21,11 @@ async function run() { const store = await new LibDashStore(provider); try { - // 1. Verify posterminaltombstone table exists and has expected columns - console.log('1. Checking posterminaltombstone schema...'); - const tableInfo = provider.db.pragma('table_info("posterminaltombstone")'); + // 1. Verify posterminalobituary table exists and has expected columns + console.log('1. Checking posterminalobituary schema...'); + const tableInfo = provider.db.pragma('table_info("posterminalobituary")'); const colNames = tableInfo.map((c) => c.name); - console.log('posterminaltombstone columns:', colNames); + console.log('posterminalobituary columns:', colNames); assert.deepEqual(colNames, [ 'id', 'posterminal_id', @@ -36,9 +36,9 @@ async function run() { // Setup company first console.log('2. Setting up base data...'); - const googleAuthId = await store.google_auth.add('tombstone-tester@example.com'); + const googleAuthId = await store.google_auth.add('obituary-tester@example.com'); const company = await store.company.create({ - name: 'Tombstone Corp', + name: 'Obituary Corp', iso639: 'de', taxrate: 19, reducedtaxrate: 7, @@ -58,7 +58,7 @@ async function run() { }); // 3. Test article deletion flow - console.log('3. Testing article deletion tombstone...'); + console.log('3. Testing article deletion obituary...'); const article = await store.article.createUnderParent({ googleAuthId, parentId: company.rootCategoryId, @@ -67,7 +67,7 @@ async function run() { await store.article.delete(googleAuthId, article.sku); // 4. Test category deletion flow - console.log('4. Testing category deletion tombstone...'); + console.log('4. Testing category deletion obituary...'); const cat = await store.category.createUnderParent({ googleAuthId, parentId: company.rootCategoryId, @@ -76,7 +76,7 @@ async function run() { await store.category.delete({ googleAuthId, id: cat.id }); // 5. Test customer deletion flow - console.log('5. Testing customer deletion tombstone...'); + console.log('5. Testing customer deletion obituary...'); const customer = await store.entity.create(googleAuthId, { name: 'Mustermann', firstName: 'Max', @@ -85,31 +85,31 @@ async function run() { await store.entity.delete(googleAuthId, customer.id); // 6. Test customer group deletion flow - console.log('6. Testing customer group deletion tombstone...'); + console.log('6. Testing customer group deletion obituary...'); const cg = await store.customergroup.create(googleAuthId, { name: 'VIP Guests', }); await store.customergroup.delete(googleAuthId, cg.id); - // 7. Verify all tombstones exist in posterminaltombstone - console.log('7. Verifying tombstones in database...'); - const allTombstones = provider.db - .prepare('SELECT * FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC') + // 7. Verify all obituaries exist in posterminalobituary + console.log('7. Verifying obituaries in database...'); + const allObituaries = provider.db + .prepare('SELECT * FROM posterminalobituary WHERE posterminal_id = ? ORDER BY id ASC') .all(terminal.id); - console.log('Created tombstones:', allTombstones); - assert.equal(allTombstones.length, 4); + console.log('Created obituaries:', allObituaries); + assert.equal(allObituaries.length, 4); - assert.equal(allTombstones[0].entity_type, 'article'); - assert.equal(allTombstones[0].entity_id, article.id); + assert.equal(allObituaries[0].entity_type, 'article'); + assert.equal(allObituaries[0].entity_id, article.id); - assert.equal(allTombstones[1].entity_type, 'category'); - assert.equal(allTombstones[1].entity_id, cat.id); + assert.equal(allObituaries[1].entity_type, 'category'); + assert.equal(allObituaries[1].entity_id, cat.id); - assert.equal(allTombstones[2].entity_type, 'customer'); - assert.equal(allTombstones[2].entity_id, customer.id); + assert.equal(allObituaries[2].entity_type, 'customer'); + assert.equal(allObituaries[2].entity_id, customer.id); - assert.equal(allTombstones[3].entity_type, 'customergroup'); - assert.equal(allTombstones[3].entity_id, cg.id); + assert.equal(allObituaries[3].entity_type, 'customergroup'); + assert.equal(allObituaries[3].entity_id, cg.id); // 8. Test getDeletedEntityCount & getDeletedEntityList APIs console.log('8. Testing posterminal.getDeletedEntityCount & getDeletedEntityList...'); @@ -132,7 +132,7 @@ async function run() { assert.equal(list[3].entityType, 'customergroup'); // Test cursor pagination - const cursor = allTombstones[1].id; + const cursor = allObituaries[1].id; const countAfterCursor = await store.posterminal.getDeletedEntityCount({ posterminalId: terminal.id, cursor, @@ -145,16 +145,16 @@ async function run() { limit: 10, }); assert.equal(listAfterCursor.length, 2); - assert.equal(listAfterCursor[0].id, allTombstones[2].id); - assert.equal(listAfterCursor[1].id, allTombstones[3].id); + assert.equal(listAfterCursor[0].id, allObituaries[2].id); + assert.equal(listAfterCursor[1].id, allObituaries[3].id); - // 9. Test maxknowntombstoneid - console.log('9. Testing maxknowntombstoneid...'); - await store.posterminal.setMaxKnownTombstoneId(terminal.id, allTombstones[3].id); + // 9. Test maxknownobituaryid + console.log('9. Testing maxknownobituaryid...'); + await store.posterminal.setMaxKnownObituaryId(terminal.id, allObituaries[3].id); const updatedTerminal = await store.posterminal.findByToken('pos-token-123'); - assert.equal(updatedTerminal.maxknowntombstoneid, allTombstones[3].id); + assert.equal(updatedTerminal.maxknownobituaryid, allObituaries[3].id); - // 10. Test setOff category & orphaned article tombstone generation + // 10. Test setOff category & orphaned article obituary generation console.log('10. Testing setOff with orphaned and non-orphaned articles...'); // Create Cat A and Cat B const catA = await store.category.createUnderParent({ @@ -187,60 +187,60 @@ async function run() { await store.posterminal.setOn(googleAuthId, terminal.id, catA.id); await store.posterminal.setOn(googleAuthId, terminal.id, catB.id); - // Clear previous tombstones to test cleanly - provider.db.prepare('DELETE FROM posterminaltombstone WHERE posterminal_id = ?').run(terminal.id); + // Clear previous obituaries to test cleanly + provider.db.prepare('DELETE FROM posterminalobituary WHERE posterminal_id = ?').run(terminal.id); // Turn off Cat A: - // - Cat A should get a tombstone - // - Art A should get a tombstone (orphaned on this terminal) - // - Art AB should NOT get a tombstone (still has active Cat B on this terminal) + // - Cat A should get an obituary + // - Art A should get an obituary (orphaned on this terminal) + // - Art AB should NOT get an obituary (still has active Cat B on this terminal) await store.posterminal.setOff(googleAuthId, terminal.id, catA.id); - const tombstonesAfterSetOff = provider.db - .prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC') + const obituariesAfterSetOff = provider.db + .prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ? ORDER BY id ASC') .all(terminal.id); - console.log('Tombstones after setOff(Cat A):', tombstonesAfterSetOff); - assert.equal(tombstonesAfterSetOff.length, 2); - assert.deepEqual(tombstonesAfterSetOff, [ + console.log('Obituaries after setOff(Cat A):', obituariesAfterSetOff); + assert.equal(obituariesAfterSetOff.length, 2); + assert.deepEqual(obituariesAfterSetOff, [ { entity_type: 'category', entity_id: catA.id }, { entity_type: 'article', entity_id: artA.id }, ]); - // 11. Test setOn category clears pending tombstones for that category and its articles - console.log('11. Testing setOn clears pending category and article tombstones...'); + // 11. Test setOn category clears pending obituaries for that category and its articles + console.log('11. Testing setOn clears pending category and article obituaries...'); await store.posterminal.setOn(googleAuthId, terminal.id, catA.id); - const tombstonesAfterSetOn = provider.db - .prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?') + const obituariesAfterSetOn = provider.db + .prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ?') .all(terminal.id); - console.log('Tombstones after setOn(Cat A):', tombstonesAfterSetOn); - assert.equal(tombstonesAfterSetOn.length, 0); + console.log('Obituaries after setOn(Cat A):', obituariesAfterSetOn); + assert.equal(obituariesAfterSetOn.length, 0); - // 12. Test setOffAll generates tombstones for all active categories and all their articles - console.log('12. Testing setOffAll tombstones...'); + // 12. Test setOffAll generates obituaries for all active categories and all their articles + console.log('12. Testing setOffAll obituaries...'); await store.posterminal.setOffAll(googleAuthId, terminal.id); - const tombstonesAfterSetOffAll = provider.db - .prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC') + const obituariesAfterSetOffAll = provider.db + .prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ? ORDER BY id ASC') .all(terminal.id); - console.log('Tombstones after setOffAll:', tombstonesAfterSetOffAll); + console.log('Obituaries after setOffAll:', obituariesAfterSetOffAll); // Cat A, Cat B, Art A, Art AB - const catTombstones = tombstonesAfterSetOffAll.filter((t) => t.entity_type === 'category').map((t) => t.entity_id); - const artTombstones = tombstonesAfterSetOffAll.filter((t) => t.entity_type === 'article').map((t) => t.entity_id); - assert(catTombstones.includes(catA.id)); - assert(catTombstones.includes(catB.id)); - assert(artTombstones.includes(artA.id)); - assert(artTombstones.includes(artAB.id)); + const catObituaries = obituariesAfterSetOffAll.filter((t) => t.entity_type === 'category').map((t) => t.entity_id); + const artObituaries = obituariesAfterSetOffAll.filter((t) => t.entity_type === 'article').map((t) => t.entity_id); + assert(catObituaries.includes(catA.id)); + assert(catObituaries.includes(catB.id)); + assert(artObituaries.includes(artA.id)); + assert(artObituaries.includes(artAB.id)); - // 13. Test setOnAll clears category and article tombstones - console.log('13. Testing setOnAll clears all category & article tombstones...'); + // 13. Test setOnAll clears category and article obituaries + console.log('13. Testing setOnAll clears all category & article obituaries...'); await store.posterminal.setOnAll(googleAuthId, terminal.id); - const tombstonesAfterSetOnAll = provider.db - .prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?') + const obituariesAfterSetOnAll = provider.db + .prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ?') .all(terminal.id); - console.log('Tombstones after setOnAll:', tombstonesAfterSetOnAll); - assert.equal(tombstonesAfterSetOnAll.length, 0); + console.log('Obituaries after setOnAll:', obituariesAfterSetOnAll); + assert.equal(obituariesAfterSetOnAll.length, 0); - console.log('✅ ALL POSTERMINALTOMBSTONE TESTS PASSED'); + console.log('✅ ALL POSTERMINALOBITUARY TESTS PASSED'); } finally { try { rmSync(tempDir, { recursive: true, force: true }); diff --git a/src/index.js b/src/index.js index d1be9d8..95b1ec7 100644 --- a/src/index.js +++ b/src/index.js @@ -127,11 +127,11 @@ import posterminalGetCustomerGroupList from './store/posterminal/getCustomerGrou import posterminalGetCompositeProductCount from './store/posterminal/getCompositeProductCount.js'; import posterminalGetDeletedEntityCount from './store/posterminal/getDeletedEntityCount.js'; import posterminalGetDeletedEntityList from './store/posterminal/getDeletedEntityList.js'; -import posterminalRecordTombstone from './store/posterminal/recordTombstone.js'; +import posterminalRecordObituary from './store/posterminal/recordObituary.js'; import posterminalGetMaxOrderIdCount from './store/posterminal/getMaxOrderIdCount.js'; import posterminalGetCategoryList from './store/posterminal/getCategoryList.js'; import posterminalGetProductList from './store/posterminal/getProductList.js'; -import posterminalSetMaxKnownTombstoneId from './store/posterminal/setMaxKnownTombstoneId.js'; +import posterminalSetMaxKnownObituaryId from './store/posterminal/setMaxKnownObituaryId.js'; import posterminalTouchLastseen from './store/posterminal/touchLastseen.js'; import langCreate from './store/lang/create.js'; import langDelete from './store/lang/delete.js'; @@ -491,11 +491,11 @@ export default class LibDashStore { getCompositeProductCount: posterminalGetCompositeProductCount(provider), getDeletedEntityCount: posterminalGetDeletedEntityCount(provider), getDeletedEntityList: posterminalGetDeletedEntityList(provider), - recordTombstone: posterminalRecordTombstone(provider), + recordObituary: posterminalRecordObituary(provider), getMaxOrderIdCount: posterminalGetMaxOrderIdCount(provider), getCategoryList: posterminalGetCategoryList(provider), getProductList: posterminalGetProductList(provider), - setMaxKnownTombstoneId: posterminalSetMaxKnownTombstoneId(provider), + setMaxKnownObituaryId: posterminalSetMaxKnownObituaryId(provider), touchLastseen: posterminalTouchLastseen(provider), }; diff --git a/src/providers/mssql/queries/posterminal.js b/src/providers/mssql/queries/posterminal.js index bc6eb70..c3ac97e 100644 --- a/src/providers/mssql/queries/posterminal.js +++ b/src/providers/mssql/queries/posterminal.js @@ -6,7 +6,7 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid, + maxknownobituaryid AS maxknownobituaryid, root_category_id AS rootCategoryId, sync_root_articles AS syncRootArticles, lastseen_at AS lastseenAt, @@ -25,7 +25,7 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid, + maxknownobituaryid AS maxknownobituaryid, root_category_id AS rootCategoryId, sync_root_articles AS syncRootArticles, lastseen_at AS lastseenAt, @@ -43,7 +43,7 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid, + maxknownobituaryid AS maxknownobituaryid, root_category_id AS rootCategoryId, sync_root_articles AS syncRootArticles, lastseen_at AS lastseenAt, @@ -59,14 +59,14 @@ WHERE id = @id `; export const CREATE = ` -INSERT INTO posterminal (company_id, name, token, pairingpin, paired_at, clientserial, maxknowntombstoneid, root_category_id, sync_root_articles, lastseen_at, updated_at) -OUTPUT INSERTED.id, INSERTED.name, INSERTED.token, INSERTED.pairingpin, INSERTED.paired_at AS pairedAt, INSERTED.clientserial AS clientserial, INSERTED.maxknowntombstoneid AS maxknowntombstoneid, INSERTED.root_category_id AS rootCategoryId, INSERTED.sync_root_articles AS syncRootArticles, INSERTED.lastseen_at AS lastseenAt, INSERTED.updated_at AS updatedAt -VALUES (@companyId, @name, @token, @pairingpin, @pairedAt, @clientserial, @maxknowntombstoneid, @rootCategoryId, @syncRootArticles, @lastseenAt, SYSUTCDATETIME()) +INSERT INTO posterminal (company_id, name, token, pairingpin, paired_at, clientserial, maxknownobituaryid, root_category_id, sync_root_articles, lastseen_at, updated_at) +OUTPUT INSERTED.id, INSERTED.name, INSERTED.token, INSERTED.pairingpin, INSERTED.paired_at AS pairedAt, INSERTED.clientserial AS clientserial, INSERTED.maxknownobituaryid AS maxknownobituaryid, INSERTED.root_category_id AS rootCategoryId, INSERTED.sync_root_articles AS syncRootArticles, INSERTED.lastseen_at AS lastseenAt, INSERTED.updated_at AS updatedAt +VALUES (@companyId, @name, @token, @pairingpin, @pairedAt, @clientserial, @maxknownobituaryid, @rootCategoryId, @syncRootArticles, @lastseenAt, SYSUTCDATETIME()) `; export const UPDATE = ` UPDATE posterminal -SET name = @name, token = @token, pairingpin = @pairingpin, paired_at = @pairedAt, clientserial = @clientserial, maxknowntombstoneid = @maxknowntombstoneid, root_category_id = @rootCategoryId, sync_root_articles = @syncRootArticles, lastseen_at = @lastseenAt, updated_at = SYSUTCDATETIME() +SET name = @name, token = @token, pairingpin = @pairingpin, paired_at = @pairedAt, clientserial = @clientserial, maxknownobituaryid = @maxknownobituaryid, root_category_id = @rootCategoryId, sync_root_articles = @syncRootArticles, lastseen_at = @lastseenAt, updated_at = SYSUTCDATETIME() WHERE id = @id AND company_id = @companyId `; @@ -76,9 +76,9 @@ SET lastseen_at = SYSUTCDATETIME() WHERE id = @id `; -export const SET_MAX_KNOWN_TOMBSTONE_ID = ` +export const SET_MAX_KNOWN_OBITUARY_ID = ` UPDATE posterminal -SET maxknowntombstoneid = @maxknowntombstoneid +SET maxknownobituaryid = @maxknownobituaryid WHERE id = @id `; @@ -150,7 +150,7 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid, + maxknownobituaryid AS maxknownobituaryid, root_category_id AS rootCategoryId, sync_root_articles AS syncRootArticles, lastseen_at AS lastseenAt, @@ -483,8 +483,8 @@ WHERE pr.minmultiplier = 1 GROUP BY pr.article_id, pr.customergroup_id `; -export const RECORD_TOMBSTONE = ` -INSERT INTO posterminaltombstone (posterminal_id, entity_type, entity_id) +export const RECORD_OBITUARY = ` +INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id) SELECT pt.id, @entityType, @entityId FROM posterminal pt WHERE pt.company_id = @companyId AND pt.token IS NOT NULL @@ -492,7 +492,7 @@ WHERE pt.company_id = @companyId AND pt.token IS NOT NULL export const COUNT_DELETED_ENTITIES = ` SELECT COUNT(*) AS count -FROM posterminaltombstone +FROM posterminalobituary WHERE posterminal_id = @posterminalId AND id > @cursor `; @@ -501,7 +501,7 @@ SELECT TOP (@limit) id, entity_type AS entityType, entity_id AS entityId -FROM posterminaltombstone +FROM posterminalobituary WHERE posterminal_id = @posterminalId AND id > @cursor ORDER BY id ASC `; diff --git a/src/providers/mssql/schema.js b/src/providers/mssql/schema.js index ff19883..1dd68ba 100644 --- a/src/providers/mssql/schema.js +++ b/src/providers/mssql/schema.js @@ -392,20 +392,20 @@ BEGIN END `; -export const INIT_POSTERMINALTOMBSTONE = ` -IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'posterminaltombstone') +export const INIT_POSTERMINALOBITUARY = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'posterminalobituary') BEGIN - CREATE TABLE posterminaltombstone ( + CREATE TABLE posterminalobituary ( id INT IDENTITY(1,1) PRIMARY KEY, posterminal_id INT NOT NULL, entity_type NVARCHAR(50) NOT NULL, entity_id INT NOT NULL, - created_at DATETIME2 NOT NULL CONSTRAINT DF_posterminaltombstone_created_at DEFAULT SYSUTCDATETIME(), - CONSTRAINT FK_posterminaltombstone_posterminal FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE + created_at DATETIME2 NOT NULL CONSTRAINT DF_posterminalobituary_created_at DEFAULT SYSUTCDATETIME(), + CONSTRAINT FK_posterminalobituary_posterminal FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE ); - CREATE INDEX IX_posterminaltombstone_posterminal_id - ON posterminaltombstone (posterminal_id, id); + CREATE INDEX IX_posterminalobituary_posterminal_id + ON posterminalobituary (posterminal_id, id); END `; @@ -894,7 +894,7 @@ BEGIN pairingpin NVARCHAR(50) NULL, paired_at DATETIME2 NULL, clientserial NVARCHAR(255) NULL, - maxknowntombstoneid INT NULL, + maxknownobituaryid INT NULL, root_category_id INT NULL, sync_root_articles BIT NOT NULL CONSTRAINT DF_posterminal_sync_root_articles DEFAULT 1, lastseen_at DATETIME2 NULL, @@ -1503,7 +1503,7 @@ export const SCHEMA_SCRIPTS = [ INIT_COMPANYSETTING, INIT_POSTERMINAL, INIT_POSTERMINALCATEGORY, - INIT_POSTERMINALTOMBSTONE, + INIT_POSTERMINALOBITUARY, INIT_PRINTER, INIT_LABELTEMPLATE, INIT_FILE, diff --git a/src/providers/sqlite3/index.js b/src/providers/sqlite3/index.js index b10e70c..9ae2071 100644 --- a/src/providers/sqlite3/index.js +++ b/src/providers/sqlite3/index.js @@ -479,8 +479,8 @@ export class BetterSqlite3Provider extends BetterSqlite3Executor { if (posterminalCols.length > 0 && !posterminalCols.includes('clientserial')) { this.db.exec(`ALTER TABLE posterminal ADD COLUMN clientserial TEXT`); } - if (posterminalCols.length > 0 && !posterminalCols.includes('maxknowntombstoneid')) { - this.db.exec(`ALTER TABLE posterminal ADD COLUMN maxknowntombstoneid INTEGER`); + if (posterminalCols.length > 0 && !posterminalCols.includes('maxknownobituaryid')) { + this.db.exec(`ALTER TABLE posterminal ADD COLUMN maxknownobituaryid INTEGER`); } const propertynameCols = this.db.pragma('table_info("propertyname")').map((c) => c.name); diff --git a/src/providers/sqlite3/queries/posterminal.js b/src/providers/sqlite3/queries/posterminal.js index c2faaf6..bccefa1 100644 --- a/src/providers/sqlite3/queries/posterminal.js +++ b/src/providers/sqlite3/queries/posterminal.js @@ -5,11 +5,11 @@ const queries = translateQueries(source, 'posterminal'); export const { CREATE, DELETE_BY_COMPANY_AND_ID, GET_BY_ID, LIST_BY_COMPANY, LIST_CATEGORY_IDS, POSTERMINAL_IDS_BY_COMPANY, SET_OFF, SET_OFF_ALL, UPDATE, - FIND_BY_PAIRINGPIN, PAIR, SET_MAX_KNOWN_TOMBSTONE_ID, + FIND_BY_PAIRINGPIN, PAIR, SET_MAX_KNOWN_OBITUARY_ID, FIND_BY_TOKEN, COUNT_PRODUCTS, COUNT_CATEGORIES, COUNT_CUSTOMERS, COUNT_CUSTOMER_GROUPS, COUNT_COMPOSITE_PRODUCTS, MAX_ORDER_ID, LIST_POS_PRODUCT_CATEGORIES, LIST_POS_CUSTOMER_GROUP_IDS, LIST_POS_PRODUCT_PRICES, - TOUCH_LASTSEEN, RECORD_TOMBSTONE, COUNT_DELETED_ENTITIES, + TOUCH_LASTSEEN, RECORD_OBITUARY, COUNT_DELETED_ENTITIES, } = queries; export const SET_ON = ` @@ -269,7 +269,7 @@ SELECT id, entity_type AS entityType, entity_id AS entityId -FROM posterminaltombstone +FROM posterminalobituary WHERE posterminal_id = @posterminalId AND id > @cursor ORDER BY id ASC LIMIT @limit diff --git a/src/providers/sqlite3/schema.js b/src/providers/sqlite3/schema.js index f9b458a..01f3685 100644 --- a/src/providers/sqlite3/schema.js +++ b/src/providers/sqlite3/schema.js @@ -608,7 +608,7 @@ CREATE TABLE IF NOT EXISTS posterminal ( pairingpin TEXT, paired_at TEXT, clientserial TEXT, - maxknowntombstoneid INTEGER, + maxknownobituaryid INTEGER, root_category_id INTEGER, sync_root_articles INTEGER NOT NULL DEFAULT 1, lastseen_at TEXT, @@ -631,8 +631,8 @@ CREATE TABLE IF NOT EXISTS posterminalcategory ( ); `; -export const INIT_POSTERMINALTOMBSTONE = ` -CREATE TABLE IF NOT EXISTS posterminaltombstone ( +export const INIT_POSTERMINALOBITUARY = ` +CREATE TABLE IF NOT EXISTS posterminalobituary ( id INTEGER PRIMARY KEY AUTOINCREMENT, posterminal_id INTEGER NOT NULL, entity_type TEXT NOT NULL, @@ -640,8 +640,8 @@ CREATE TABLE IF NOT EXISTS posterminaltombstone ( created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE ); -CREATE INDEX IF NOT EXISTS IX_posterminaltombstone_posterminal_id - ON posterminaltombstone (posterminal_id, id); +CREATE INDEX IF NOT EXISTS IX_posterminalobituary_posterminal_id + ON posterminalobituary (posterminal_id, id); `; export const INIT_PRINTER = ` @@ -1119,7 +1119,7 @@ export const SCHEMA_SCRIPTS = [ INIT_COMPANYSETTING, INIT_POSTERMINAL, INIT_POSTERMINALCATEGORY, - INIT_POSTERMINALTOMBSTONE, + INIT_POSTERMINALOBITUARY, INIT_PRINTER, INIT_LABELTEMPLATE, INIT_FILE, diff --git a/src/store/article/delete.js b/src/store/article/delete.js index 86d5c83..e56b322 100644 --- a/src/store/article/delete.js +++ b/src/store/article/delete.js @@ -3,12 +3,12 @@ import * as sqliteQueries from '../../providers/sqlite3/queries/articleDelete.js import * as mssqlArticle from '../../providers/mssql/queries/article.js'; import * as sqliteArticle from '../../providers/sqlite3/queries/article.js'; import resolveArticleBySku from './resolveArticleBySku.js'; -import recordTombstone from '../posterminal/recordTombstone.js'; +import recordObituary from '../posterminal/recordObituary.js'; import makeRunner from '../runner.js'; export default function del(provider) { const resolve = resolveArticleBySku(provider); - const tombstone = recordTombstone(provider); + const recordObit = recordObituary(provider); const isSqlite = provider?.dialect === 'sqlite3'; const queries = isSqlite ? sqliteQueries : mssqlQueries; const articleQueries = isSqlite ? sqliteArticle : mssqlArticle; @@ -45,7 +45,7 @@ export default function del(provider) { const listIds = await runner.query(queries.GET_LIST_IDS, { articleId: id }); const { articlelistId, optionslistId } = listIds.rows[0] ?? {}; - await tombstone({ companyId, entityType: 'article', entityId: id }, runner); + await recordObit({ companyId, entityType: 'article', entityId: id }, runner); await runner.query(queries.DELETE_PICS_BY_ARTICLE, { articleId: id }); diff --git a/src/store/category/delete.js b/src/store/category/delete.js index 90ed1fc..c1ee61f 100644 --- a/src/store/category/delete.js +++ b/src/store/category/delete.js @@ -5,12 +5,12 @@ import * as sqliteArticleDelete from '../../providers/sqlite3/queries/articleDel import * as mssqlArticle from '../../providers/mssql/queries/article.js'; import * as sqliteArticle from '../../providers/sqlite3/queries/article.js'; import resolveCategoryAccess from './resolveCategoryAccess.js'; -import recordTombstone from '../posterminal/recordTombstone.js'; +import recordObituary from '../posterminal/recordObituary.js'; import makeRunner from '../runner.js'; export default function del(provider) { const access = resolveCategoryAccess(provider); - const tombstone = recordTombstone(provider); + const recordObit = recordObituary(provider); const isSqlite = provider?.dialect === 'sqlite3'; const sql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE; const articleDeleteQueries = isSqlite ? sqliteArticleDelete : mssqlArticleDelete; @@ -67,7 +67,7 @@ export default function del(provider) { try { await runner.query(sql, { id }); - await tombstone({ companyId, entityType: 'category', entityId: id }, runner); + await recordObit({ companyId, entityType: 'category', entityId: id }, runner); } catch (err) { if ( err.message?.includes('FOREIGN KEY constraint failed') || @@ -149,7 +149,7 @@ export default function del(provider) { const listIds = await runner.query(articleDeleteQueries.GET_LIST_IDS, { articleId: artId }); const { articlelistId, optionslistId } = listIds.rows[0] ?? {}; - await tombstone({ companyId, entityType: 'article', entityId: artId }, runner); + await recordObit({ companyId, entityType: 'article', entityId: artId }, runner); await runner.query(articleDeleteQueries.DELETE_PICS_BY_ARTICLE, { articleId: artId }); const deleted = await runner.query(articleDeleteQueries.DELETE_BY_ID, { articleId: artId }); @@ -218,7 +218,7 @@ export default function del(provider) { const reversedIds = [...subtreeIds].reverse(); for (const catId of reversedIds) { await runner.query(sql, { id: catId }); - await tombstone({ companyId, entityType: 'category', entityId: catId }, runner); + await recordObit({ companyId, entityType: 'category', entityId: catId }, runner); } }; diff --git a/src/store/customergroup/delete.js b/src/store/customergroup/delete.js index 6f4b2a7..d71ff7d 100644 --- a/src/store/customergroup/delete.js +++ b/src/store/customergroup/delete.js @@ -2,12 +2,12 @@ import { DELETE_BY_COMPANY_AND_ID as MSSQL_DELETE_BY_COMPANY_AND_ID } from '../. import { DELETE_BY_COMPANY_AND_ID as SQLITE_DELETE_BY_COMPANY_AND_ID } from '../../providers/sqlite3/queries/customergroup.js'; import { isForeignKeyConstraintError } from '../../providers/provider.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; -import recordTombstone from '../posterminal/recordTombstone.js'; +import recordObituary from '../posterminal/recordObituary.js'; import makeRunner from '../runner.js'; export default function del(provider) { const access = resolveSelectedCompanyAccess(provider); - const tombstone = recordTombstone(provider); + const recordObit = recordObituary(provider); const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE_BY_COMPANY_AND_ID @@ -43,7 +43,7 @@ export default function del(provider) { throw new Error('Customer group not found'); } - await tombstone({ companyId, entityType: 'customergroup', entityId: id }, runner); + await recordObit({ companyId, entityType: 'customergroup', entityId: id }, runner); } catch (err) { if (isForeignKeyConstraintError(err)) { throw new Error('Customer group in use'); diff --git a/src/store/entity/delete.js b/src/store/entity/delete.js index b22eb10..3856226 100644 --- a/src/store/entity/delete.js +++ b/src/store/entity/delete.js @@ -9,12 +9,12 @@ import { GET_BY_COMPANY_AND_ID as SQLITE_GET_BY_ID, } from '../../providers/sqlite3/queries/entity.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; -import recordTombstone from '../posterminal/recordTombstone.js'; +import recordObituary from '../posterminal/recordObituary.js'; import makeRunner from '../runner.js'; export default function del(provider) { const access = resolveSelectedCompanyAccess(provider); - const tombstone = recordTombstone(provider); + const recordObit = recordObituary(provider); const isSqlite = provider?.dialect === 'sqlite3'; const sql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE; const checkInUseSql = isSqlite ? SQLITE_CHECK_IN_USE : MSSQL_CHECK_IN_USE; @@ -66,7 +66,7 @@ export default function del(provider) { throw new Error('Entity not found'); } - await tombstone({ companyId, entityType: 'customer', entityId: numericId }, runner); + await recordObit({ companyId, entityType: 'customer', entityId: numericId }, runner); }; } diff --git a/src/store/posterminal/findByPairingpin.js b/src/store/posterminal/findByPairingpin.js index 4452286..f95e933 100644 --- a/src/store/posterminal/findByPairingpin.js +++ b/src/store/posterminal/findByPairingpin.js @@ -10,7 +10,7 @@ export default function findByPairingpin(provider) { * * @param {string} pairingpin - The pairing pin to search for. * @param {object} [tx] - Optional transaction to run within. - * @returns {Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>} The posterminal, or null if not found. + * @returns {Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>} The posterminal, or null if not found. */ return async (pairingpin, tx) => { if (!pairingpin) return null; diff --git a/src/store/posterminal/findByToken.js b/src/store/posterminal/findByToken.js index f40b43a..8bd67bd 100644 --- a/src/store/posterminal/findByToken.js +++ b/src/store/posterminal/findByToken.js @@ -10,7 +10,7 @@ export default function findByToken(provider) { * * @param {string} token - The auth token to search for. * @param {object} [tx] - Optional transaction to run within. - * @returns {Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknowntombstoneid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>} The posterminal, or null if not found. + * @returns {Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}|null>} The posterminal, or null if not found. */ return async (token, tx) => { const trimmed = String(token ?? '').trim(); diff --git a/src/store/posterminal/getDeletedEntityCount.js b/src/store/posterminal/getDeletedEntityCount.js index 982838a..da2959c 100644 --- a/src/store/posterminal/getDeletedEntityCount.js +++ b/src/store/posterminal/getDeletedEntityCount.js @@ -10,7 +10,7 @@ export default function getDeletedEntityCount(provider) { * * @param {object} input * @param {number} input.posterminalId - The POS terminal id. - * @param {number} [input.cursor=0] - The highest synced tombstone ID. + * @param {number} [input.cursor=0] - The highest synced obituary ID. * @param {object} [tx] - Optional transaction. * @returns {Promise} Count of deleted entities. */ diff --git a/src/store/posterminal/getDeletedEntityList.js b/src/store/posterminal/getDeletedEntityList.js index b42c9e9..b199cb3 100644 --- a/src/store/posterminal/getDeletedEntityList.js +++ b/src/store/posterminal/getDeletedEntityList.js @@ -10,7 +10,7 @@ export default function getDeletedEntityList(provider) { * * @param {object} input * @param {number} input.posterminalId - The POS terminal id. - * @param {number} [input.cursor=0] - The highest synced tombstone ID. + * @param {number} [input.cursor=0] - The highest synced obituary ID. * @param {number} [input.limit=200] - Max items to return. * @param {object} [tx] - Optional transaction. * @returns {Promise>} diff --git a/src/store/posterminal/list.js b/src/store/posterminal/list.js index 02505a8..00b4add 100644 --- a/src/store/posterminal/list.js +++ b/src/store/posterminal/list.js @@ -12,11 +12,11 @@ export default function list(provider) { * * @param {number} googleAuthId - The id of the Google auth user. * @param {object} [tx] - Optional transaction to run within. - * @returns {Promise>} The posterminals. + * @returns {Promise>} The posterminals. * * @example * const terminals = await store.posterminal.list(42); - * // => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] + * // => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] */ return async (googleAuthId, tx) => { const { companyId } = await access(googleAuthId, tx); diff --git a/src/store/posterminal/recordTombstone.js b/src/store/posterminal/recordObituary.js similarity index 72% rename from src/store/posterminal/recordTombstone.js rename to src/store/posterminal/recordObituary.js index 72d202a..2a930f0 100644 --- a/src/store/posterminal/recordTombstone.js +++ b/src/store/posterminal/recordObituary.js @@ -1,12 +1,12 @@ -import { RECORD_TOMBSTONE as MSSQL_SQL } from '../../providers/mssql/queries/posterminal.js'; -import { RECORD_TOMBSTONE as SQLITE_SQL } from '../../providers/sqlite3/queries/posterminal.js'; +import { RECORD_OBITUARY as MSSQL_SQL } from '../../providers/mssql/queries/posterminal.js'; +import { RECORD_OBITUARY as SQLITE_SQL } from '../../providers/sqlite3/queries/posterminal.js'; import makeRunner from '../runner.js'; -export default function recordTombstone(provider) { +export default function recordObituary(provider) { const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL; /** - * Records a tombstone for all active paired POS terminals of a company. + * Records an obituary for all active paired POS terminals of a company. * * @param {object} input * @param {number} input.companyId - The company id. diff --git a/src/store/posterminal/setMaxKnownObituaryId.js b/src/store/posterminal/setMaxKnownObituaryId.js new file mode 100644 index 0000000..5158c23 --- /dev/null +++ b/src/store/posterminal/setMaxKnownObituaryId.js @@ -0,0 +1,27 @@ +import { SET_MAX_KNOWN_OBITUARY_ID as MSSQL_SET } from '../../providers/mssql/queries/posterminal.js'; +import { SET_MAX_KNOWN_OBITUARY_ID as SQLITE_SET } from '../../providers/sqlite3/queries/posterminal.js'; +import makeRunner from '../runner.js'; + +export default function setMaxKnownObituaryId(provider) { + const sql = provider?.dialect === 'sqlite3' ? SQLITE_SET : MSSQL_SET; + + /** + * Updates the max known obituary ID for a POS terminal. + * + * @param {number} id - The posterminal id. + * @param {number|null} maxknownobituaryid - The highest synced obituary ID. + * @param {object} [tx] - Optional transaction to run within. + * @returns {Promise<{id: number, maxknownobituaryid: number|null}>} + */ + return async (id, maxknownobituaryid, tx) => { + await makeRunner(provider, tx).query(sql, { + id, + maxknownobituaryid: maxknownobituaryid != null ? Number(maxknownobituaryid) : null, + }); + + return { + id, + maxknownobituaryid: maxknownobituaryid != null ? Number(maxknownobituaryid) : null, + }; + }; +} diff --git a/src/store/posterminal/setMaxKnownTombstoneId.js b/src/store/posterminal/setMaxKnownTombstoneId.js deleted file mode 100644 index c960225..0000000 --- a/src/store/posterminal/setMaxKnownTombstoneId.js +++ /dev/null @@ -1,27 +0,0 @@ -import { SET_MAX_KNOWN_TOMBSTONE_ID as MSSQL_SET } from '../../providers/mssql/queries/posterminal.js'; -import { SET_MAX_KNOWN_TOMBSTONE_ID as SQLITE_SET } from '../../providers/sqlite3/queries/posterminal.js'; -import makeRunner from '../runner.js'; - -export default function setMaxKnownTombstoneId(provider) { - const sql = provider?.dialect === 'sqlite3' ? SQLITE_SET : MSSQL_SET; - - /** - * Updates the max known tombstone ID for a POS terminal. - * - * @param {number} id - The posterminal id. - * @param {number|null} maxknowntombstoneid - The highest synced tombstone ID. - * @param {object} [tx] - Optional transaction to run within. - * @returns {Promise<{id: number, maxknowntombstoneid: number|null}>} - */ - return async (id, maxknowntombstoneid, tx) => { - await makeRunner(provider, tx).query(sql, { - id, - maxknowntombstoneid: maxknowntombstoneid != null ? Number(maxknowntombstoneid) : null, - }); - - return { - id, - maxknowntombstoneid: maxknowntombstoneid != null ? Number(maxknowntombstoneid) : null, - }; - }; -} diff --git a/src/store/posterminal/setOff.js b/src/store/posterminal/setOff.js index f508d68..f6651cd 100644 --- a/src/store/posterminal/setOff.js +++ b/src/store/posterminal/setOff.js @@ -21,13 +21,13 @@ export default function setOff(provider) { ? SQLITE_LIST_CATEGORY_IDS : MSSQL_LIST_CATEGORY_IDS; - const addCategoryTombstoneSql = ` - INSERT INTO posterminaltombstone (posterminal_id, entity_type, entity_id) + const addCategoryObituarySql = ` + INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id) VALUES (@posterminalId, 'category', @categoryId) `; - const addArticleTombstonesSql = ` - INSERT INTO posterminaltombstone (posterminal_id, entity_type, entity_id) + const addArticleObituariesSql = ` + INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id) SELECT DISTINCT @posterminalId, 'article', ca.article_id FROM categoryarticle ca WHERE ca.category_id = @categoryId @@ -69,12 +69,12 @@ export default function setOff(provider) { throw new Error('Posterminal not found'); } - await runner.query(addCategoryTombstoneSql, { + await runner.query(addCategoryObituarySql, { posterminalId, categoryId, }); - await runner.query(addArticleTombstonesSql, { + await runner.query(addArticleObituariesSql, { posterminalId, categoryId, }); diff --git a/src/store/posterminal/setOffAll.js b/src/store/posterminal/setOffAll.js index e7719d0..895e405 100644 --- a/src/store/posterminal/setOffAll.js +++ b/src/store/posterminal/setOffAll.js @@ -21,15 +21,15 @@ export default function setOffAll(provider) { ? SQLITE_LIST_CATEGORY_IDS : MSSQL_LIST_CATEGORY_IDS; - const addCategoryTombstonesSql = ` - INSERT INTO posterminaltombstone (posterminal_id, entity_type, entity_id) + const addCategoryObituariesSql = ` + INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id) SELECT posterminal_id, 'category', category_id FROM posterminalcategory WHERE posterminal_id = @posterminalId `; - const addArticleTombstonesSql = ` - INSERT INTO posterminaltombstone (posterminal_id, entity_type, entity_id) + const addArticleObituariesSql = ` + INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id) SELECT DISTINCT pc.posterminal_id, 'article', ca.article_id FROM posterminalcategory pc INNER JOIN categoryarticle ca ON ca.category_id = pc.category_id @@ -64,8 +64,8 @@ export default function setOffAll(provider) { throw new Error('Posterminal not found'); } - await runner.query(addCategoryTombstonesSql, { posterminalId }); - await runner.query(addArticleTombstonesSql, { posterminalId }); + await runner.query(addCategoryObituariesSql, { posterminalId }); + await runner.query(addArticleObituariesSql, { posterminalId }); await runner.query(setOffAllSql, { posterminalId }); diff --git a/src/store/posterminal/setOn.js b/src/store/posterminal/setOn.js index 6de2c01..84849d6 100644 --- a/src/store/posterminal/setOn.js +++ b/src/store/posterminal/setOn.js @@ -35,8 +35,8 @@ export default function setOn(provider) { SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id = @categoryId )`; - const clearTombstonesSql = ` - DELETE FROM posterminaltombstone + const clearObituariesSql = ` + DELETE FROM posterminalobituary WHERE posterminal_id = @posterminalId AND ( (entity_type = 'category' AND entity_id = @categoryId) @@ -79,7 +79,7 @@ export default function setOn(provider) { categoryId, }); - await runner.query(clearTombstonesSql, { + await runner.query(clearObituariesSql, { posterminalId, categoryId, }); diff --git a/src/store/posterminal/setOnAll.js b/src/store/posterminal/setOnAll.js index 05f198c..9637b2c 100644 --- a/src/store/posterminal/setOnAll.js +++ b/src/store/posterminal/setOnAll.js @@ -47,8 +47,8 @@ export default function setOnAll(provider) { SET updated_at = SYSUTCDATETIME() WHERE company_id = @companyId`; - const clearTombstonesSql = ` - DELETE FROM posterminaltombstone + const clearObituariesSql = ` + DELETE FROM posterminalobituary WHERE posterminal_id = @posterminalId AND entity_type IN ('category', 'article') `; @@ -94,7 +94,7 @@ export default function setOnAll(provider) { rootCategoryId, }); - await runner.query(clearTombstonesSql, { + await runner.query(clearObituariesSql, { posterminalId, }); diff --git a/src/store/posterminal/upsert.js b/src/store/posterminal/upsert.js index ac9d70f..f4f3002 100644 --- a/src/store/posterminal/upsert.js +++ b/src/store/posterminal/upsert.js @@ -63,10 +63,10 @@ export default function upsert(provider) { ? (input.pairingpin ? String(input.pairingpin).trim() : null) : (existing.rows[0].pairingpin ?? null); - const maxknowntombstoneid = - input.maxknowntombstoneid !== undefined - ? input.maxknowntombstoneid - : (existing.rows[0].maxknowntombstoneid ?? null); + const maxknownobituaryid = + input.maxknownobituaryid !== undefined + ? input.maxknownobituaryid + : (existing.rows[0].maxknownobituaryid ?? null); const rootCategoryId = input.rootCategoryId !== undefined @@ -91,7 +91,7 @@ export default function upsert(provider) { pairingpin, pairedAt, clientserial, - maxknowntombstoneid, + maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, @@ -104,7 +104,7 @@ export default function upsert(provider) { pairingpin, pairedAt, clientserial, - maxknowntombstoneid, + maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, @@ -112,7 +112,7 @@ export default function upsert(provider) { } const pairingpin = input.pairingpin ? String(input.pairingpin).trim() : null; - const maxknowntombstoneid = input.maxknowntombstoneid ?? null; + const maxknownobituaryid = input.maxknownobituaryid ?? null; const rootCategoryId = input.rootCategoryId != null ? Number(input.rootCategoryId) : null; const syncRootArticles = input.syncRootArticles !== undefined ? (input.syncRootArticles ? 1 : 0) : 1; const lastseenAt = input.lastseenAt ?? null; @@ -124,7 +124,7 @@ export default function upsert(provider) { pairingpin, pairedAt, clientserial, - maxknowntombstoneid, + maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, @@ -137,7 +137,7 @@ export default function upsert(provider) { pairingpin, pairedAt, clientserial, - maxknowntombstoneid, + maxknownobituaryid, rootCategoryId, syncRootArticles, lastseenAt, @@ -150,7 +150,7 @@ export default function upsert(provider) { pairingpin: row.pairingpin ?? null, pairedAt: row.pairedAt ?? null, clientserial: row.clientserial ?? null, - maxknowntombstoneid: row.maxknowntombstoneid ?? null, + maxknownobituaryid: row.maxknownobituaryid ?? null, rootCategoryId: row.rootCategoryId ?? null, syncRootArticles: row.syncRootArticles !== undefined ? (row.syncRootArticles ? 1 : 0) : 1, lastseenAt: row.lastseenAt ?? null,