From 69eb2c9a0da4591fef122f4fedc425a65ec1d208 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 8 Oct 2026 01:37:26 +0200 Subject: [PATCH] u --- API.md | 10 +- API.posterminal.md | 25 +- FEATURE_PLAN_EXPORT.md | 3 +- generate-api-doc.js | 3 +- generate-schema-graph.js | 1 - schema-graph.dot | 65 +- schema-graph.svg | 2585 +++++++++--------- src/index.js | 2 + src/providers/mssql/purgeSql.js | 1 - src/providers/mssql/queries/posterminal.js | 40 +- src/providers/mssql/schema.js | 32 +- src/providers/sqlite3/queries/posterminal.js | 1 + src/providers/sqlite3/schema.js | 20 +- src/store/posterminal/findByPairingpin.js | 2 +- src/store/posterminal/findByToken.js | 2 +- src/store/posterminal/list.js | 4 +- src/store/posterminal/touchLastseen.js | 19 + src/store/posterminal/upsert.js | 67 +- 18 files changed, 1479 insertions(+), 1403 deletions(-) create mode 100644 src/store/posterminal/touchLastseen.js diff --git a/API.md b/API.md index f5199b1..11b018b 100644 --- a/API.md +++ b/API.md @@ -48,12 +48,11 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - **optionslist**: `id PK` - **optionslistarticle**: `id PK, optionslist_id->optionslist, article_id->article, count:i=1, sort:i=0, mandated:b=0, UQ(optionslist_id, article_id), UQ(optionslist_id, sort)` - **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)` +- **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` - **posterminalcategory**: `id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)` - **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)` -- **syncpos**: `id PK, company_id->company, paircode:s(50) UQ, token?:s(255) UQ` - **tax**: `id PK, rate:d(18,4) UQ` - **unit**: `id PK, company_id->company, si:s(50), basesi:s(50), basesifactor:f, UQ(company_id, si)` - **unittext**: `id PK, unit_id->unit, language_id->language, symbol:s(50), name:s(255), UQ(unit_id, language_id)` @@ -204,8 +203,8 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `adjust(googleAuthId: number, input: {sku?: string, warehouseId?: number, amount?: number, text?: string, externalNumber?: string, date?: string|Date, lines?: Array}, tx?: object): Promise<{manifest: {id: number, number: string, type: string, date: string, createdAt: string}, lines: Array, ledger: Array}>` - [posterminal](API.posterminal.md) - `delete(googleAuthId: number, id: number, tx?: object): Promise` - - `findByPairingpin(pairingpin: string, tx?: object): Promise` - - `findByToken(token: string, 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>` - `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` @@ -215,13 +214,14 @@ 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}>` - `setMaxKnownTombstoneId(id: number, maxknowntombstoneid: number|null, tx?: object): Promise<{id: number, maxknowntombstoneid: 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}>` - `setOnAll(googleAuthId: number, posterminalId: number, tx?: object): Promise<{id: number, categoryIds: Array}>` + - `touchLastseen(id: number, tx?: object): Promise<{id: number}>` - `upsert(googleAuthId: number, input: {name: string, pairingpin: string, token?: string, id?: number}, tx?: object): Promise<{id: number, name: string, token: string, pairingpin: string}>` - [printer](API.printer.md) - `create(googleAuthId: number, input: {address: string, type: string, model?: string, serial?: string, sort?: number, desc?: string}, tx?: object): Promise<{id: number, company_id: number, address: string, type: string, model: string|null, serial: string|null, sort: number, desc: string|null}>` diff --git a/API.posterminal.md b/API.posterminal.md index 8113172..2737f9d 100644 --- a/API.posterminal.md +++ b/API.posterminal.md @@ -45,7 +45,7 @@ Finds a posterminal by its pairingpin. **Returns** -`Promise` — The posterminal row, or null if not found. +`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. ## `posterminal.findByToken` @@ -62,7 +62,7 @@ Finds a posterminal by its auth token. **Returns** -`Promise` — The posterminal row, or null if not found. +`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. ## `posterminal.getCategoryCount` @@ -250,13 +250,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 }] +// => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] ``` ## `posterminal.pair` @@ -416,6 +416,23 @@ const result = await store.posterminal.setOnAll(42, 5); // => { id, categoryIds: [...] } ``` +## `posterminal.touchLastseen` + +*Source: `src/store/posterminal/touchLastseen.js`* + +Updates lastseen_at for a POS terminal to the current timestamp. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `id` | `number` | The posterminal id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise<{id: number}>` + ## `posterminal.upsert` *Source: `src/store/posterminal/upsert.js`* diff --git a/FEATURE_PLAN_EXPORT.md b/FEATURE_PLAN_EXPORT.md index 85d91f8..e5ec5f0 100644 --- a/FEATURE_PLAN_EXPORT.md +++ b/FEATURE_PLAN_EXPORT.md @@ -111,7 +111,7 @@ Abgeleitet aus den Schemata (Eltern vor Kindern). Die Registry speichert sie exp 6. `article` (Selbstreferenz), `articletext`, `articleean`, `articlepic`, `articleproperty`, `articleattributevalue`, `articlelistarticle`, `optionslistarticle`, `brandpic`, `categoryarticle`, `categorypic`, `categorytext` 7. `price`, `articlesupplier` 8. `manifest`, `manifestarticle`, `file`, `manifestattachment`, `warehouse`, `ledger` -9. `numbers`, `companyuser`, `articlehistory`, `entityhistory`, `syncpos`, `companysetting`, `posterminal`, `posterminalcategory`, `printer`, `labeltemplate` +9. `numbers`, `companyuser`, `articlehistory`, `entityhistory`, `companysetting`, `posterminal`, `posterminalcategory`, `printer`, `labeltemplate` Selbstreferenzen (`category.parent_id`, `article.parentarticle_id`): Der Export sortiert nach `id`. Beim Import wird die FK-Prüfung zurückgestellt (§6.3), ein Zwei-Pass-Update ist nicht nötig. @@ -315,7 +315,6 @@ Betroffene Felder (Registry-Flag `secret`): - `google_auth`: `email`, `sub`, `picture`, `picturebinary` (personenbezogen) - `posterminal`: `token`, `pairingpin` -- `syncpos`: `paircode`, `token` - `companysetting`: Zeilen mit `writeonly = 1` (z. B. API-Schlüssel) Regeln: diff --git a/generate-api-doc.js b/generate-api-doc.js index 51afd59..c51ffac 100644 --- a/generate-api-doc.js +++ b/generate-api-doc.js @@ -359,12 +359,11 @@ const SCHEMA_TABLES = [ ['optionslist', 'id PK'], ['optionslistarticle', 'id PK, optionslist_id->optionslist, article_id->article, count:i=1, sort:i=0, mandated:b=0, UQ(optionslist_id, article_id), UQ(optionslist_id, sort)'], ['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)'], + ['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'], ['posterminalcategory', 'id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)'], ['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)'], - ['syncpos', 'id PK, company_id->company, paircode:s(50) UQ, token?:s(255) UQ'], ['tax', 'id PK, rate:d(18,4) UQ'], ['unit', 'id PK, company_id->company, si:s(50), basesi:s(50), basesifactor:f, UQ(company_id, si)'], ['unittext', 'id PK, unit_id->unit, language_id->language, symbol:s(50), name:s(255), UQ(unit_id, language_id)'], diff --git a/generate-schema-graph.js b/generate-schema-graph.js index bc78402..fe29108 100644 --- a/generate-schema-graph.js +++ b/generate-schema-graph.js @@ -328,7 +328,6 @@ const CLUSTERS = [ 'meta', 'google_auth', 'companyuser', - 'syncpos', 'company', 'companyhistory', 'companysetting', diff --git a/schema-graph.dot b/schema-graph.dot index 74cb587..4f0884d 100644 --- a/schema-graph.dot +++ b/schema-graph.dot @@ -11,7 +11,7 @@ digraph schema { fontcolor="#e2e8f0"; margin=14; meta [label=<
meta
keyNVARCHAR(255)
valueNVARCHAR(MAX)
>]; 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)
>]; + 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)
>]; 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
>]; companyhistory [label=<
companyhistory
idINT PK
company_idINT FK
companyuser_id?INT FK
dateDATETIME2
textNVARCHAR(MAX)
>]; entity [label=<
entity
idINT PK
customergroup_idINT FK
first_name?NVARCHAR(255)
nameNVARCHAR(255)
number?NVARCHAR(100)
created_atDATETIME2
updated_atDATETIME2
>]; @@ -19,7 +19,6 @@ digraph schema { 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)
>]; - syncpos [label=<
syncpos
idINT PK
company_idINT FK
paircodeNVARCHAR(50)
token?NVARCHAR(255)
>]; companysetting [label=<
companysetting
idINT PK
company_idINT FK
keyNVARCHAR(255)
valueNVARCHAR(MAX)
frontendBIT
writeonlyBIT
>]; google_auth [label=<
google_auth
idINT PK
selected_company?INT FK
emailNVARCHAR(320)
picture?NVARCHAR(2048)
picturebinary?VARBINARY(MAX)
sub?NVARCHAR(255)
created_atDATETIME2
>]; } @@ -39,11 +38,11 @@ digraph schema { 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
>]; brand [label=<
brand
idINT PK
company_idINT FK
nameNVARCHAR(255)
gsprpinfo?NVARCHAR(MAX)
>]; categoryarticle [label=<
categoryarticle
idINT PK
category_idINT FK
article_idINT FK
>]; - category [label=<
category
idINT PK
parent_id?INT FK
sortINT
updated_atDATETIME2
>]; + 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)
>]; articleean [label=<
articleean
idINT PK
article_idINT FK
eanNVARCHAR(50)
>]; article [label=<
article
idINT PK
parentattributename_id?INT FK
brand_id?INT FK
parentarticle_id?INT FK
articlelist_id?INT FK
optionslist_id?INT FK
unit_idINT FK
company_idINT FK
sku?NVARCHAR(100)
unitamountFLOAT
weightFLOAT
track_stockBIT
is_parentBIT
parentsortINT
created_atDATETIME2
updated_atDATETIME2
>]; - articlesupplier [label=<
articlesupplier
idINT PK
article_idINT FK
price_id?INT FK
entity_idINT FK
sku?NVARCHAR(100)
stock?FLOAT
puFLOAT
sortINT
>]; + articlesupplier [label=<
articlesupplier
idINT PK
article_idINT FK
tax_id?INT FK
entity_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
>]; @@ -73,8 +72,8 @@ digraph schema { label="Pricing"; 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
>]; + 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
>]; } subgraph cluster_units { label="Units"; labeljust="l"; fontsize=15; @@ -88,7 +87,7 @@ digraph schema { fontcolor="#e2e8f0"; margin=14; printer [label=<
printer
idINT PK
company_idINT FK
addressNVARCHAR(255)
typeNVARCHAR(50)
model?NVARCHAR(255)
serial?NVARCHAR(255)
sortINT
desc?NVARCHAR(MAX)
>]; labeltemplate [label=<
labeltemplate
idINT PK
company_idINT FK
nameNVARCHAR(255)
widthINT
heightINT
dpiINT
typeNVARCHAR(50)
contentNVARCHAR(MAX)
thumb?VARBINARY(MAX)
>]; - posterminal [label=<
posterminal
idINT PK
company_idINT FK
nameNVARCHAR(255)
token?NVARCHAR(255)
pairingpinNVARCHAR(50)
paired_at?DATETIME2
clientserial?NVARCHAR(255)
maxknowntombstoneid?INT
>]; + 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
>]; posterminalcategory [label=<
posterminalcategory
idINT PK
category_idINT FK
posterminal_idINT FK
>]; } subgraph cluster_ai { @@ -114,13 +113,13 @@ digraph schema { __legend [label=<
Legend
PKprimary key
FKforeign key
?nullable column
—FOREIGN KEY constraint
- -naming convention only, no constraint
>]; - google_auth:selected_company:w -> company:in17:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_google_auth_selected_company", weight=3]; + google_auth:selected_company:w -> company:in14: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:e -> category:in7:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_company_root_category", weight=3]; + company:root_category_id:e -> category:in8:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_company_root_category", weight=3]; company:default_language_id:w -> language:in3:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_company_default_language", constraint=false, weight=1]; - company:taxrate:e -> tax:in3:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_company_taxrate", constraint=false, weight=1]; - company:reducedtaxrate:e -> tax:in1:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_company_reducedtaxrate", constraint=false, weight=1]; - company:taxfreerate:e -> tax:in2:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_company_taxfreerate", constraint=false, weight=1]; + company:taxrate:e -> tax:in4:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_company_taxrate", constraint=false, weight=1]; + company:reducedtaxrate:e -> tax:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_company_reducedtaxrate", constraint=false, weight=1]; + company:taxfreerate:e -> tax:in3:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_company_taxfreerate", constraint=false, weight=1]; customergroup:company_id:sw -> company:in7:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_customergroup_company", weight=3]; company:poscustomergroup_id:nw -> customergroup:in2:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_company_poscustomergroup", constraint=false, weight=1]; entity:customergroup_id:nw -> customergroup:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_entity_customergroup", weight=3]; @@ -129,11 +128,11 @@ digraph schema { entityhistory:entity_id:sw -> entity:in3:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_entityhistory_entity", weight=3]; entityhistory:companyuser_id:se -> companyuser:in2:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_entityhistory_companyuser", constraint=false, weight=1]; unit:company_id:w -> company:in5:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_unit_company", weight=3]; - unittext:unit_id:w -> unit:in0:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_unittext_unit", weight=3]; + unittext:unit_id:w -> unit:in1:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_unittext_unit", weight=3]; unittext:language_id:w -> language:in2:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_unittext_language", constraint=false, weight=1]; brand:company_id:e -> company:in3:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_brand_company", weight=3]; article:company_id:e -> company:in4:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_article_company", weight=3]; - article:unit_id:w -> unit:in1:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_article_unit", constraint=false, weight=1]; + article:unit_id:w -> unit:in0:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_article_unit", constraint=false, weight=1]; article:brand_id:e -> brand:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_article_brand", constraint=false, weight=1]; article:articlelist_id:e -> articlelist:in0:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_article_articlelist", constraint=false, weight=1]; article:optionslist_id:e -> optionslist:in0:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_article_optionslist", constraint=false, weight=1]; @@ -142,7 +141,7 @@ digraph schema { article:parentattributename_id:sw -> attributename:in2: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:w -> companyuser:in3:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlehistory_companyuser", constraint=false, weight=1]; - companyhistory:company_id:sw -> company:in10:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_companyhistory_company", weight=3]; + companyhistory:company_id:sw -> company:in9: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]; articletombstone:company_id:e -> company:in2:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articletombstone_company", weight=3]; articleean:article_id:se -> article:in6:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleean_article", weight=3]; @@ -154,39 +153,39 @@ digraph schema { articlelistarticle:article_id:sw -> article:in7:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_articlelistarticle_article", constraint=false, weight=1]; optionslistarticle:optionslist_id:se -> optionslist:in1:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_optionslistarticle_optionslist", weight=3]; optionslistarticle:article_id:e -> article:in11:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_optionslistarticle_article", constraint=false, weight=1]; - categoryarticle:category_id:ne -> category:in5:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_categoryarticle_category", weight=3]; + categoryarticle:category_id:nw -> category:in4:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_categoryarticle_category", weight=3]; categoryarticle:article_id:w -> article:in2:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_categoryarticle_article", constraint=false, weight=1]; categorypic:category_id:w -> category:in2:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_categorypic_category", weight=3]; categorypic:pic_id:w -> pic:in2:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_categorypic_pic", constraint=false, weight=1]; - categorytext:category_id:w -> category:in4:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_categorytext_category", weight=3]; + categorytext:category_id:w -> category:in5:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_categorytext_category", weight=3]; categorytext:language_id:e -> language:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_categorytext_language", constraint=false, weight=1]; - articletext:article_id:e -> article:in9:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_articletext_article", weight=3]; - articletext:language_id:w -> language:in1:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_articletext_language", constraint=false, weight=1]; - price:tax_id:w -> tax:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_price_tax", constraint=false, weight=1]; + articletext:article_id:w -> article:in9:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_articletext_article", weight=3]; + articletext:language_id:e -> language:in1:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_articletext_language", constraint=false, weight=1]; + price:tax_id:e -> tax:in2:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_price_tax", constraint=false, weight=1]; price:article_id:e -> article:in8:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_price_article", weight=3]; price:customergroup_id:e -> customergroup:in0:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_price_customergroup", constraint=false, weight=1]; articlesupplier:article_id:sw -> article:in10:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlesupplier_article", weight=3]; articlesupplier:entity_id:e -> entity:in2:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_articlesupplier_entity", constraint=false, weight=1]; - articlesupplier:price_id:e -> price:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articlesupplier_price", constraint=false, weight=1]; - manifest:company_id:w -> company:in18:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_manifest_company", weight=3]; + articlesupplier:tax_id:e -> tax:in1:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articlesupplier_tax", constraint=false, weight=1]; + manifest:company_id:w -> company:in16:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_manifest_company", weight=3]; manifest:entity_id:e -> entity:in4:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_manifest_entity", constraint=false, weight=1]; manifestarticle:manifest_id:sw -> manifest:in0:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_manifestarticle_manifest", weight=3]; - warehouse:company_id:w -> company:in16:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_warehouse_company", weight=3]; + warehouse:company_id:w -> company:in11:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_warehouse_company", weight=3]; ledger:manifestarticle_id:sw -> manifestarticle:in0:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_ledger_manifestarticle", weight=3]; ledger:warehouse_id:w -> warehouse:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_ledger_warehouse", constraint=false, weight=1]; - numbers:company_id:nw -> company:in9:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_numbers_company", weight=3]; + numbers:company_id:se -> company:in8:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_numbers_company", weight=3]; companyuser:google_auth_id:e -> google_auth:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_companyuser_google_auth", constraint=false, weight=1]; - companyuser:company_id:w -> company:in11:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_companyuser_company", weight=3]; + companyuser:company_id:w -> company:in13:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_companyuser_company", weight=3]; modelconversation:companyuser_id:w -> companyuser:in1:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_modelconversation_companyuser", weight=3]; - modelvfs:company_id:w -> company:in13:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_modelvfs_company", weight=3]; + modelvfs:company_id:w -> company:in17:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_modelvfs_company", weight=3]; modelmessage:conversation_id:se -> modelconversation:in0:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_modelmessage_conversation", weight=3]; - syncpos:company_id:w -> company:in14:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_syncpos_company", weight=3]; - companysetting:company_id:w -> company:in15:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_companysetting_company", weight=3]; - posterminal:company_id:se -> company:in12:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_posterminal_company", weight=3]; + companysetting:company_id:w -> company:in15:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_companysetting_company", weight=3]; + posterminal:company_id:se -> company:in12:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_posterminal_company", weight=3]; + posterminal:root_category_id:w -> category:in6:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_posterminal_root_category", constraint=false, weight=1]; posterminalcategory:posterminal_id:se -> posterminal:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_posterminalcategory_posterminal", weight=3]; - posterminalcategory:category_id:w -> category:in6:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_posterminalcategory_category", constraint=false, weight=1]; + posterminalcategory:category_id:w -> category:in7:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_posterminalcategory_category", constraint=false, weight=1]; printer:company_id:se -> company:in6:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_printer_company", weight=3]; - labeltemplate:company_id:se -> company:in8:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_labeltemplate_company", weight=3]; + labeltemplate:company_id:se -> company:in10:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_labeltemplate_company", weight=3]; manifestattachment:manifest_id:sw -> manifest:in1:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_manifestattachment_manifest", weight=3]; manifestattachment:file_id:w -> file:in0:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_manifestattachment_file", constraint=false, weight=1]; propertyname:company_id:e -> company:in0:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_propertyname_company", weight=3]; @@ -196,8 +195,8 @@ digraph schema { attributevalue:attribute_id:se -> attributename:in0:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_attributevalue_attribute", weight=3]; articleattributevalue:article_id:w -> article:in1:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_articleattributevalue_article", weight=3]; articleattributevalue:attributevalue_id:w -> attributevalue:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_articleattributevalue_attributevalue", constraint=false, weight=1]; - categoryproperty:category_id:w -> category:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_categoryproperty_category", weight=3]; + categoryproperty:category_id:w -> category:in0:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_categoryproperty_category", weight=3]; categoryproperty:property_id:w -> propertyname:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_categoryproperty_property", constraint=false, weight=1]; - categoryattributevalue:category_id:w -> category:in0:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_categoryattributevalue_category", weight=3]; + categoryattributevalue:category_id:w -> category:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_categoryattributevalue_category", weight=3]; categoryattributevalue:attributevalue_id:w -> attributevalue:in1:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_categoryattributevalue_attributevalue", constraint=false, weight=1]; } \ No newline at end of file diff --git a/schema-graph.svg b/schema-graph.svg index f57eed2..80662af 100644 --- a/schema-graph.svg +++ b/schema-graph.svg @@ -4,30 +4,30 @@ - + schema - + cluster_identity - + Identity & Company cluster_i18n - -Localization + +Localization cluster_catalog - -Catalog + +Catalog cluster_media - -Media + +Media cluster_manifests @@ -36,18 +36,18 @@ cluster_commerce - -Pricing + +Pricing cluster_units - -Units + +Units cluster_pos - -POS + +POS cluster_ai @@ -110,79 +110,78 @@ 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 + + +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) customergroup:sw->company:n - - + + @@ -190,109 +189,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:e->category:n - - + + - + tax - - - - - - -tax - - -id -INT -PK - - -rate -DECIMAL(18,4) + + + + + + + +tax + + +id +INT +PK + + +rate +DECIMAL(18,4) company:e->tax:n - - + + @@ -300,8 +301,8 @@ company:e->tax:n - - + + @@ -309,8 +310,8 @@ company:e->tax:n - - + + @@ -453,8 +454,8 @@ companyhistory:sw->company:n - - + + @@ -537,10 +538,10 @@ -numbers:nw->company:n +numbers:se->company:n - - + + @@ -586,56 +587,56 @@ 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 + + + +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 - - + + @@ -688,79 +689,45 @@ - - -syncpos - - -syncpos - - -id -INT -PK - - -company_id -INT -FK - - -paircode -NVARCHAR(50) - - -token? -NVARCHAR(255) - - - -syncpos:w->company:n - - - - - - - + companysetting - - -companysetting - - -id -INT -PK - - -company_id -INT -FK - - -key -NVARCHAR(255) - - -value -NVARCHAR(MAX) - - -frontend -BIT - - -writeonly -BIT + + +companysetting + + +id +INT +PK + + +company_id +INT +FK + + +key +NVARCHAR(255) + + +value +NVARCHAR(MAX) + + +frontend +BIT + + +writeonly +BIT - + companysetting:w->company:n - - - + + + @@ -768,55 +735,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 - - + + @@ -824,356 +791,356 @@ 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 +articletext:e->language:n - - + + - + article - - - - - - - - - - - - - - -article - - -id -INT -PK - - -parentattributename_id -? -INT -FK - - -brand_id -? -INT -FK - - -parentarticle_id -? -INT -FK - - -articlelist_id -? -INT -FK - - -optionslist_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 + + +parentattributename_id +? +INT +FK + + +brand_id +? +INT +FK + + +parentarticle_id +? +INT +FK + + +articlelist_id +? +INT +FK + + +optionslist_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 -articletext:e->article:n +articletext:w->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 - - + + - + 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:w->unit: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 + + +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 - - + + - + 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) brand:e->company: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:ne->category:n +categoryarticle:nw->category:n - - + + @@ -1181,8 +1148,8 @@ categoryarticle:w->article:n - - + + @@ -1190,47 +1157,47 @@ category:e->category:e - - + + - + articlehistory - - -articlehistory - - -id -INT -PK - - -article_id -INT -FK - - -companyuser_id -? -INT -FK - - -date -DATETIME2 - - -text -NVARCHAR(MAX) + + +articlehistory + + +id +INT +PK + + +article_id +INT +FK + + +companyuser_id +? +INT +FK + + +date +DATETIME2 + + +text +NVARCHAR(MAX) articlehistory:w->companyuser:n - + @@ -1239,38 +1206,38 @@ articlehistory:se->article: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:se->article:n - - + + @@ -1278,8 +1245,8 @@ article:e->company:n - - + + @@ -1287,8 +1254,8 @@ article:e->brand:n - - + + @@ -1296,54 +1263,54 @@ article:e->article:e - - + + - + articlelist - - - - -articlelist - - -id -INT -PK + + + + +articlelist + + +id +INT +PK article:e->articlelist:n - - + + - + optionslist - - - - -optionslist - - -id -INT -PK + + + + +optionslist + + +id +INT +PK article:e->optionslist:n - - + + @@ -1351,13 +1318,13 @@ article:w->unit:n - - + + - + attributename @@ -1392,7 +1359,7 @@ article:sw->attributename:n - + @@ -1401,61 +1368,65 @@ article:sw->attributename:n - + - + articlesupplier - - -articlesupplier - - -id -INT -PK - - -article_id -INT -FK - - -price_id -? -INT -FK - - -entity_id -INT -FK - - -sku? -NVARCHAR(100) - - -stock? -FLOAT - - -pu -FLOAT - - -sort -INT + + +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:e->entity:n - - + + @@ -1463,92 +1434,56 @@ articlesupplier:sw->article:n - - + + - - -price - - - -price - - -id -INT -PK - - -article_id -INT -FK - - -tax_id -INT -FK - - -customergroup_id -INT -FK - - -minmultiplier -DECIMAL(18,4) - - -net -FLOAT - - + -articlesupplier:e->price: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:sw->article:n - - + + @@ -1556,51 +1491,51 @@ articlelistarticle:sw->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:e->article:n - - + + @@ -1608,98 +1543,98 @@ optionslistarticle:se->optionslist:n - - + + - + pic - - - - - -pic - - -id -INT -PK - - -w -INT - - -h -INT - - -size -BIGINT - - -hash -NVARCHAR(64) - - -thumbw -INT - - -thumbh -INT - - -thumbhash -NVARCHAR(64) - - -source -NVARCHAR(MAX) - - -fullbinary -VARBINARY(MAX) - - -thumbbinary -VARBINARY(MAX) + + + + + +pic + + +id +INT +PK + + +w +INT + + +h +INT + + +size +BIGINT + + +hash +NVARCHAR(64) + + +thumbw +INT + + +thumbh +INT + + +thumbhash +NVARCHAR(64) + + +source +NVARCHAR(MAX) + + +fullbinary +VARBINARY(MAX) + + +thumbbinary +VARBINARY(MAX) - + brandpic - - -brandpic - - -id -INT -PK - - -brand_id -INT -FK - - -pic_id -INT -FK - - -sort -INT + + +brandpic + + +id +INT +PK + + +brand_id +INT +FK + + +pic_id +INT +FK + + +sort +INT brandpic:w->brand:n - - + + @@ -1707,43 +1642,43 @@ brandpic:e->pic: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:w->category:n - - + + @@ -1751,43 +1686,43 @@ categorypic:w->pic:n - - + + - + articlepic - - -articlepic - - -id -INT -PK - - -article_id -INT -FK - - -pic_id -INT -FK - - -sort -INT + + +articlepic + + +id +INT +PK + + +article_id +INT +FK + + +pic_id +INT +FK + + +sort +INT articlepic:se->article:n - - + + @@ -1795,70 +1730,70 @@ articlepic: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) - + warehouse @@ -1887,13 +1822,13 @@ warehouse:w->company:n - - + + - + manifestarticle @@ -1943,7 +1878,7 @@ FLOAT - + manifest @@ -2000,8 +1935,8 @@ manifest:w->company:n - - + + @@ -2015,7 +1950,7 @@ - + ledger @@ -2080,7 +2015,7 @@ - + manifestattachment @@ -2109,8 +2044,8 @@ manifestattachment:w->file:n - - + + @@ -2123,11 +2058,46 @@ + + +price + + +price + + +id +INT +PK + + +article_id +INT +FK + + +tax_id +INT +FK + + +customergroup_id +INT +FK + + +minmultiplier +DECIMAL(18,4) + + +net +FLOAT + price:e->customergroup:n - + @@ -2136,17 +2106,17 @@ price:e->article:n - - + + -price:w->tax:n +price:e->tax:n - - + + @@ -2154,194 +2124,221 @@ unit:w->company: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:se->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 + + +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:se->company:n - - + + - + posterminal - - - -posterminal - - -id -INT -PK - - -company_id -INT -FK - - -name -NVARCHAR(255) - - -token? -NVARCHAR(255) - - -pairingpin -NVARCHAR(50) - - -paired_at? -DATETIME2 - - -clientserial? -NVARCHAR(255) - - -maxknowntombstoneid? -INT + + + +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 - + posterminal:se->company:n - - - + + + + + + + + +posterminal:w->category:n + + + - + posterminalcategory - - -posterminalcategory - - -id -INT -PK - - -category_id -INT -FK - - -posterminal_id -INT -FK + + +posterminalcategory + + +id +INT +PK + + +category_id +INT +FK + + +posterminal_id +INT +FK posterminalcategory:w->category:n - - + + @@ -2349,13 +2346,13 @@ posterminalcategory:se->posterminal:n - - + + - + modelmessage @@ -2384,7 +2381,7 @@ NVARCHAR(MAX) - + modelconversation @@ -2440,7 +2437,7 @@ - + modelvfs @@ -2484,13 +2481,13 @@ modelvfs:w->company:n - - + + - + attributevalue @@ -2526,7 +2523,7 @@ - + propertyname @@ -2560,8 +2557,8 @@ propertyname:e->company:n - - + + @@ -2569,47 +2566,47 @@ attributename:e->company:n - - + + - + categoryproperty - - -categoryproperty - - -id -INT -PK - - -property_id -INT -FK - - -category_id -INT -FK - - -value -NVARCHAR(MAX) - - -sort -INT + + +categoryproperty + + +id +INT +PK + + +property_id +INT +FK + + +category_id +INT +FK + + +value +NVARCHAR(MAX) + + +sort +INT categoryproperty:w->category:n - - + + @@ -2617,43 +2614,43 @@ categoryproperty:w->propertyname:n - + - + categoryattributevalue - - -categoryattributevalue - - -id -INT -PK - - -attributevalue_id -INT -FK - - -category_id -INT -FK - - -sort -INT + + +categoryattributevalue + + +id +INT +PK + + +attributevalue_id +INT +FK + + +category_id +INT +FK + + +sort +INT categoryattributevalue:w->category:n - - + + @@ -2661,13 +2658,13 @@ categoryattributevalue:w->attributevalue:n - - + + - + articleproperty @@ -2700,8 +2697,8 @@ articleproperty:w->article:n - - + + @@ -2715,7 +2712,7 @@ - + articleattributevalue @@ -2744,8 +2741,8 @@ articleattributevalue:w->article:n - - + + @@ -2759,32 +2756,32 @@ - + __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/src/index.js b/src/index.js index a006355..a360c0b 100644 --- a/src/index.js +++ b/src/index.js @@ -117,6 +117,7 @@ import posterminalGetMaxOrderIdCount from './store/posterminal/getMaxOrderIdCoun import posterminalGetCategoryList from './store/posterminal/getCategoryList.js'; import posterminalGetProductList from './store/posterminal/getProductList.js'; import posterminalSetMaxKnownTombstoneId from './store/posterminal/setMaxKnownTombstoneId.js'; +import posterminalTouchLastseen from './store/posterminal/touchLastseen.js'; import langCreate from './store/lang/create.js'; import langDelete from './store/lang/delete.js'; import langList from './store/lang/list.js'; @@ -414,6 +415,7 @@ export default class LibDashStore { getCategoryList: posterminalGetCategoryList(provider), getProductList: posterminalGetProductList(provider), setMaxKnownTombstoneId: posterminalSetMaxKnownTombstoneId(provider), + touchLastseen: posterminalTouchLastseen(provider), }; this.google_auth = { diff --git a/src/providers/mssql/purgeSql.js b/src/providers/mssql/purgeSql.js index 4858e98..57d6841 100644 --- a/src/providers/mssql/purgeSql.js +++ b/src/providers/mssql/purgeSql.js @@ -11,7 +11,6 @@ export const TABLES = [ 'modelmessage', 'modelconversation', 'companyuser', - 'syncpos', 'companysetting', 'posterminalcategory', 'posterminal', diff --git a/src/providers/mssql/queries/posterminal.js b/src/providers/mssql/queries/posterminal.js index 94a76cb..0c695f7 100644 --- a/src/providers/mssql/queries/posterminal.js +++ b/src/providers/mssql/queries/posterminal.js @@ -6,7 +6,11 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid + maxknowntombstoneid AS maxknowntombstoneid, + root_category_id AS rootCategoryId, + sync_root_articles AS syncRootArticles, + lastseen_at AS lastseenAt, + updated_at AS updatedAt FROM posterminal WHERE company_id = @companyId ORDER BY id @@ -21,7 +25,11 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid + maxknowntombstoneid AS maxknowntombstoneid, + root_category_id AS rootCategoryId, + sync_root_articles AS syncRootArticles, + lastseen_at AS lastseenAt, + updated_at AS updatedAt FROM posterminal WHERE id = @id `; @@ -35,29 +43,39 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid + maxknowntombstoneid AS maxknowntombstoneid, + root_category_id AS rootCategoryId, + sync_root_articles AS syncRootArticles, + lastseen_at AS lastseenAt, + updated_at AS updatedAt FROM posterminal WHERE pairingpin = @pairingpin `; export const PAIR = ` UPDATE posterminal -SET token = @token, paired_at = @pairedAt, clientserial = @clientserial, pairingpin = '' +SET token = @token, paired_at = @pairedAt, clientserial = @clientserial, pairingpin = NULL, lastseen_at = @pairedAt, updated_at = SYSUTCDATETIME() WHERE id = @id `; export const CREATE = ` -INSERT INTO posterminal (company_id, name, token, pairingpin, paired_at, clientserial, maxknowntombstoneid) -OUTPUT INSERTED.id, INSERTED.name, INSERTED.token, INSERTED.pairingpin, INSERTED.paired_at AS pairedAt, INSERTED.clientserial AS clientserial, INSERTED.maxknowntombstoneid AS maxknowntombstoneid -VALUES (@companyId, @name, @token, @pairingpin, @pairedAt, @clientserial, @maxknowntombstoneid) +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()) `; export const UPDATE = ` UPDATE posterminal -SET name = @name, token = @token, pairingpin = @pairingpin, paired_at = @pairedAt, clientserial = @clientserial, maxknowntombstoneid = @maxknowntombstoneid +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() WHERE id = @id AND company_id = @companyId `; +export const TOUCH_LASTSEEN = ` +UPDATE posterminal +SET lastseen_at = SYSUTCDATETIME() +WHERE id = @id +`; + export const SET_MAX_KNOWN_TOMBSTONE_ID = ` UPDATE posterminal SET maxknowntombstoneid = @maxknowntombstoneid @@ -132,7 +150,11 @@ SELECT pairingpin, paired_at AS pairedAt, clientserial AS clientserial, - maxknowntombstoneid AS maxknowntombstoneid + maxknowntombstoneid AS maxknowntombstoneid, + root_category_id AS rootCategoryId, + sync_root_articles AS syncRootArticles, + lastseen_at AS lastseenAt, + updated_at AS updatedAt FROM posterminal WHERE token = @token `; diff --git a/src/providers/mssql/schema.js b/src/providers/mssql/schema.js index ae7e1ae..49b0169 100644 --- a/src/providers/mssql/schema.js +++ b/src/providers/mssql/schema.js @@ -840,21 +840,6 @@ BEGIN END `; -export const INIT_SYNCPOS = ` -IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'syncpos') -BEGIN - CREATE TABLE syncpos ( - id INT IDENTITY(1,1) PRIMARY KEY, - company_id INT NOT NULL, - paircode NVARCHAR(50) NOT NULL, - token NVARCHAR(255) NULL, - CONSTRAINT FK_syncpos_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, - CONSTRAINT UQ_syncpos_paircode UNIQUE (paircode), - CONSTRAINT UQ_syncpos_token UNIQUE (token) - ); -END -`; - export const INIT_COMPANYSETTING = ` IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'companysetting') BEGIN @@ -879,21 +864,19 @@ BEGIN company_id INT NOT NULL, name NVARCHAR(255) NOT NULL, token NVARCHAR(255) NULL, - pairingpin NVARCHAR(50) NOT NULL, + pairingpin NVARCHAR(50) NULL, paired_at DATETIME2 NULL, clientserial NVARCHAR(255) NULL, maxknowntombstoneid INT NULL, - CONSTRAINT FK_posterminal_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE + root_category_id INT NULL, + sync_root_articles BIT NOT NULL CONSTRAINT DF_posterminal_sync_root_articles DEFAULT 1, + lastseen_at DATETIME2 NULL, + updated_at DATETIME2 NOT NULL CONSTRAINT DF_posterminal_updated_at DEFAULT SYSUTCDATETIME(), + CONSTRAINT FK_posterminal_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, + CONSTRAINT FK_posterminal_root_category FOREIGN KEY (root_category_id) REFERENCES category(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX UQ_posterminal_token ON posterminal(token) WHERE token IS NOT NULL; END -ELSE -BEGIN - IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('posterminal') AND name = 'maxknowntombstoneid') - BEGIN - ALTER TABLE posterminal ADD maxknowntombstoneid INT NULL; - END -END `; export const INIT_POSTERMINALCATEGORY = ` @@ -1163,7 +1146,6 @@ export const SCHEMA_SCRIPTS = [ INIT_ARTICLETOMBSTONE, INIT_ENTITYHISTORY, INIT_COMPANYHISTORY, - INIT_SYNCPOS, INIT_COMPANYSETTING, INIT_POSTERMINAL, INIT_POSTERMINALCATEGORY, diff --git a/src/providers/sqlite3/queries/posterminal.js b/src/providers/sqlite3/queries/posterminal.js index 9d6ae66..4464daa 100644 --- a/src/providers/sqlite3/queries/posterminal.js +++ b/src/providers/sqlite3/queries/posterminal.js @@ -9,6 +9,7 @@ export const { 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, } = queries; export const SET_ON = ` diff --git a/src/providers/sqlite3/schema.js b/src/providers/sqlite3/schema.js index 5cfb7c8..c6ca976 100644 --- a/src/providers/sqlite3/schema.js +++ b/src/providers/sqlite3/schema.js @@ -578,16 +578,6 @@ CREATE TABLE IF NOT EXISTS entityhistory ( ); `; -export const INIT_SYNCPOS = ` -CREATE TABLE IF NOT EXISTS syncpos ( - id INTEGER PRIMARY KEY, - company_id INTEGER NOT NULL, - paircode TEXT NOT NULL UNIQUE, - token TEXT UNIQUE, - FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE -); -`; - export const INIT_COMPANYSETTING = ` CREATE TABLE IF NOT EXISTS companysetting ( id INTEGER PRIMARY KEY, @@ -607,11 +597,16 @@ CREATE TABLE IF NOT EXISTS posterminal ( company_id INTEGER NOT NULL, name TEXT NOT NULL, token TEXT, - pairingpin TEXT NOT NULL, + pairingpin TEXT, paired_at TEXT, clientserial TEXT, maxknowntombstoneid INTEGER, - FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE + root_category_id INTEGER, + sync_root_articles INTEGER NOT NULL DEFAULT 1, + lastseen_at TEXT, + updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), + FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, + FOREIGN KEY (root_category_id) REFERENCES category(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_posterminal_token ON posterminal(token) WHERE token IS NOT NULL; @@ -831,7 +826,6 @@ export const SCHEMA_SCRIPTS = [ INIT_ARTICLETOMBSTONE, INIT_ENTITYHISTORY, INIT_COMPANYHISTORY, - INIT_SYNCPOS, INIT_COMPANYSETTING, INIT_POSTERMINAL, INIT_POSTERMINALCATEGORY, diff --git a/src/store/posterminal/findByPairingpin.js b/src/store/posterminal/findByPairingpin.js index 5cb62c6..4452286 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} The posterminal row, 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, maxknowntombstoneid: 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 c040c13..f40b43a 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} The posterminal row, 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, maxknowntombstoneid: 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/list.js b/src/store/posterminal/list.js index d40ad46..02505a8 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 }] + * // => [{ id, name, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid, rootCategoryId, syncRootArticles, lastseenAt, updatedAt }] */ return async (googleAuthId, tx) => { const { companyId } = await access(googleAuthId, tx); diff --git a/src/store/posterminal/touchLastseen.js b/src/store/posterminal/touchLastseen.js new file mode 100644 index 0000000..32d3c30 --- /dev/null +++ b/src/store/posterminal/touchLastseen.js @@ -0,0 +1,19 @@ +import { TOUCH_LASTSEEN as MSSQL_TOUCH } from '../../providers/mssql/queries/posterminal.js'; +import { TOUCH_LASTSEEN as SQLITE_TOUCH } from '../../providers/sqlite3/queries/posterminal.js'; +import makeRunner from '../runner.js'; + +export default function touchLastseen(provider) { + const sql = provider?.dialect === 'sqlite3' ? SQLITE_TOUCH : MSSQL_TOUCH; + + /** + * Updates lastseen_at for a POS terminal to the current timestamp. + * + * @param {number} id - The posterminal id. + * @param {object} [tx] - Optional transaction to run within. + * @returns {Promise<{id: number}>} + */ + return async (id, tx) => { + await makeRunner(provider, tx).query(sql, { id: Number(id) }); + return { id: Number(id) }; + }; +} diff --git a/src/store/posterminal/upsert.js b/src/store/posterminal/upsert.js index 4e379f3..ac9d70f 100644 --- a/src/store/posterminal/upsert.js +++ b/src/store/posterminal/upsert.js @@ -37,16 +37,12 @@ export default function upsert(provider) { * // => { id, name, token, pairingpin } */ return async (googleAuthId, input = {}, tx) => { - const name = input.name?.trim(); - if (!name) { - throw new Error('Invalid posterminal'); - } - const pairingpin = input.pairingpin?.trim(); - if (!pairingpin) { + const id = input.id ?? null; + const name = input.name !== undefined ? input.name?.trim() : undefined; + if (name === '' || (!name && !id)) { throw new Error('Invalid posterminal'); } const token = input.token ?? null; - const id = input.id ?? null; const pairedAt = input.pairedAt ?? null; const clientserial = input.clientserial ?? null; @@ -60,26 +56,67 @@ export default function upsert(provider) { throw new Error('Posterminal not found'); } + const nameVal = name !== undefined ? name : existing.rows[0].name; + + const pairingpin = + input.pairingpin !== undefined + ? (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 rootCategoryId = + input.rootCategoryId !== undefined + ? (input.rootCategoryId != null ? Number(input.rootCategoryId) : null) + : (existing.rows[0].rootCategoryId ?? null); + + const syncRootArticles = + input.syncRootArticles !== undefined + ? (input.syncRootArticles ? 1 : 0) + : (existing.rows[0].syncRootArticles !== undefined ? (existing.rows[0].syncRootArticles ? 1 : 0) : 1); + + const lastseenAt = + input.lastseenAt !== undefined + ? input.lastseenAt + : (existing.rows[0].lastseenAt ?? null); + await runner.query(updateSql, { id, companyId, - name, + name: nameVal, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid, + rootCategoryId, + syncRootArticles, + lastseenAt, }); - return { id, name, token, pairingpin, pairedAt, clientserial, maxknowntombstoneid }; + return { + id, + name: nameVal, + token, + pairingpin, + pairedAt, + clientserial, + maxknowntombstoneid, + rootCategoryId, + syncRootArticles, + lastseenAt, + }; } + const pairingpin = input.pairingpin ? String(input.pairingpin).trim() : null; const maxknowntombstoneid = input.maxknowntombstoneid ?? 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; + const created = await runner.query(createSql, { companyId, name, @@ -88,6 +125,9 @@ export default function upsert(provider) { pairedAt, clientserial, maxknowntombstoneid, + rootCategoryId, + syncRootArticles, + lastseenAt, }); const row = created.rows[0] ?? { @@ -98,16 +138,23 @@ export default function upsert(provider) { pairedAt, clientserial, maxknowntombstoneid, + rootCategoryId, + syncRootArticles, + lastseenAt, }; return { id: row.id, name: row.name, token: row.token, - pairingpin: row.pairingpin, + pairingpin: row.pairingpin ?? null, pairedAt: row.pairedAt ?? null, clientserial: row.clientserial ?? null, maxknowntombstoneid: row.maxknowntombstoneid ?? null, + rootCategoryId: row.rootCategoryId ?? null, + syncRootArticles: row.syncRootArticles !== undefined ? (row.syncRootArticles ? 1 : 0) : 1, + lastseenAt: row.lastseenAt ?? null, + updatedAt: row.updatedAt ?? null, }; }; }