diff --git a/API.company.md b/API.company.md index 8ee7529..24dc7e4 100644 --- a/API.company.md +++ b/API.company.md @@ -2,6 +2,36 @@ This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`. +## `company.addHistory` + +*Source: `src/store/company/addHistory.js`* + +Adds an entry to the company history for the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `input` | `object|string` | The history input object or text string. | +| `[input.text]` | `string` | The history entry text. | +| `[tx]` | `object` | Optional transaction. | + +**Returns** + +`Promise<{id: number, companyuserId: number|null, date: string, text: string}>` — The inserted entry. + +**Throws** + +`Error` — If text is missing or user is not authorized. + +**Example** + +```js +const entry = await store.company.addHistory(42, { text: 'API suggestion: add barcode scanner endpoint' }); +// => { id, companyuserId, date, text } +``` + ## `company.create` *Source: `src/store/company/create.js`* @@ -112,6 +142,35 @@ const company = await store.company.getByName('Acme'); // => { id, name, ... } ``` +## `company.getHistory` + +*Source: `src/store/company/getHistory.js`* + +Returns the company history for the user's selected company, newest first. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `[opts]` | `object` | Optional options. | +| `[opts.limit]` | `number` | Maximum number of entries to return (newest first). | +| `[tx]` | `object` | Optional transaction. | + +**Returns** + +`Promise>` — The company history entries. + +**Example** + +```js +const history = await store.company.getHistory(42); +// => [{ id, companyuserId, date, text }] + +const recent = await store.company.getHistory(42, { limit: 5 }); +// => up to 5 most recent entries +``` + ## `company.list` *Source: `src/store/company/list.js`* diff --git a/API.md b/API.md index 066d5ee..1c6e75a 100644 --- a/API.md +++ b/API.md @@ -27,6 +27,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - **categorypic**: `id PK, category_id->category, pic_id->pic, sort:i=0, UQ(category_id, pic_id), UQ(category_id, sort)` - **categorytext**: `id PK, category_id->category, language_id->language, name:s(255), slug:s(255), seo?:txt, desc?:txt, UQ(category_id, language_id)` - **company**: `id PK, name:s(255) UQ, root_category_id?->category, default_language_id?->language, taxrate?->tax, reducedtaxrate?->tax, taxfreerate?->tax, poscustomergroup_id->customergroup` +- **companyhistory**: `id PK, company_id->company, companyuser_id?->companyuser, date:dt, text:txt` - **companysetting**: `id PK, company_id->company, key:s(255), value:txt, frontend:b=0, writeonly:b=0, UQ(company_id, key)` - **companyuser**: `id PK, google_auth_id->google_auth, company_id->company, UQ(google_auth_id, company_id)` - **customergroup**: `id PK, name:s(255), sort:i=0, company_id?->company` @@ -65,10 +66,12 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `delete(id: number, tx?: object): Promise` - `getByEmail(email: string, tx?: object): Promise>` - [company](API.company.md) + - `addHistory(googleAuthId: number, input: {text?: string}, tx?: object): Promise<{id: number, companyuserId: number|null, date: string, text: string}>` - `create(input: {iso639: string, name: string, taxrate: number, reducedtaxrate: number, googleAuthId: number}, tx?: object): Promise<{id: number, rootCategoryId: number, languageId: number, taxrateId: number, reducedtaxrateId: number, taxfreerateId: number, posCustomerGroupId: number}>` - `delete(companyId: number, tx?: object): Promise` - `getById(id: number, tx?: object): Promise` - `getByName(name: string, tx?: object): Promise` + - `getHistory(googleAuthId: number, opts?: {limit?: number}, tx?: object): Promise>` - `list(googleAuthId: number, tx?: object): Promise>` - `update(id: number, input: {iso639: string, name: string, taxrate: number, reducedtaxrate: number}, tx?: object): Promise<{id: number, rootCategoryId: number, languageId: number, taxrateId: number, reducedtaxrateId: number, taxfreerateId: number}>` - [category](API.category.md) diff --git a/generate-api-doc.js b/generate-api-doc.js index 8453ad8..93ce7bd 100644 --- a/generate-api-doc.js +++ b/generate-api-doc.js @@ -338,6 +338,7 @@ const SCHEMA_TABLES = [ ['categorypic', 'id PK, category_id->category, pic_id->pic, sort:i=0, UQ(category_id, pic_id), UQ(category_id, sort)'], ['categorytext', 'id PK, category_id->category, language_id->language, name:s(255), slug:s(255), seo?:txt, desc?:txt, UQ(category_id, language_id)'], ['company', 'id PK, name:s(255) UQ, root_category_id?->category, default_language_id?->language, taxrate?->tax, reducedtaxrate?->tax, taxfreerate?->tax, poscustomergroup_id->customergroup'], + ['companyhistory', 'id PK, company_id->company, companyuser_id?->companyuser, date:dt, text:txt'], ['companysetting', 'id PK, company_id->company, key:s(255), value:txt, frontend:b=0, writeonly:b=0, UQ(company_id, key)'], ['companyuser', 'id PK, google_auth_id->google_auth, company_id->company, UQ(google_auth_id, company_id)'], ['customergroup', 'id PK, name:s(255), sort:i=0, company_id?->company'], diff --git a/generate-schema-graph.js b/generate-schema-graph.js index 258f645..bc78402 100644 --- a/generate-schema-graph.js +++ b/generate-schema-graph.js @@ -330,6 +330,7 @@ const CLUSTERS = [ 'companyuser', 'syncpos', 'company', + 'companyhistory', 'companysetting', 'customergroup', 'entity', diff --git a/schema-graph.dot b/schema-graph.dot index 12eac50..6926180 100644 --- a/schema-graph.dot +++ b/schema-graph.dot @@ -11,14 +11,15 @@ 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)
>]; - numbers [label=<
numbers
idINT PK
company_idINT FK
typeNVARCHAR(100)
prefixNVARCHAR(50)
paddingINT
nextINT
>]; + 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
>]; - companyuser [label=<
companyuser
idINT PK
company_idINT FK
google_auth_idINT FK
>]; + numbers [label=<
numbers
idINT PK
company_idINT FK
typeNVARCHAR(100)
prefixNVARCHAR(50)
paddingINT
nextINT
>]; entitycontact [label=<
entitycontact
idINT PK
entity_idINT FK
contacttypeNVARCHAR(50)
contactNVARCHAR(255)
sortINT
>]; - syncpos [label=<
syncpos
idINT PK
company_idINT FK
paircodeNVARCHAR(50)
token?NVARCHAR(255)
>]; + 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
>]; } @@ -113,7 +114,7 @@ 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:in16:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_google_auth_selected_company", weight=3]; + google_auth:selected_company:w -> company:in17: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:default_language_id:w -> language:in3:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_company_default_language", constraint=false, weight=1]; @@ -126,13 +127,13 @@ digraph schema { entityaddress:entity_id:ne -> entity:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_entityaddress_entity", weight=3]; entitycontact:entity_id:sw -> entity:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_entitycontact_entity", weight=3]; entityhistory:entity_id:sw -> entity:in3:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_entityhistory_entity", weight=3]; - entityhistory:companyuser_id:se -> companyuser:in0:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_entityhistory_companyuser", constraint=false, weight=1]; + 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:in1:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_unittext_unit", weight=3]; + unittext:unit_id:w -> unit:in0: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:in0:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_article_unit", constraint=false, weight=1]; + article:unit_id:w -> unit:in1: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]; @@ -140,61 +141,63 @@ digraph schema { article:fatherattributename_id:sw -> attributename:in2:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_fatherattributename", constraint=false, weight=1]; article:fatherattributename_id:sw -> attributename:in2:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_article_fatherattributename", 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:in2:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlehistory_companyuser", constraint=false, weight=1]; - articletombstone:company_id:e -> company:in2:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_articletombstone_company", weight=3]; - articleean:article_id:se -> article:in6:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articleean_article", weight=3]; - articlepic:article_id:se -> article:in4:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articlepic_article", weight=3]; - articlepic:pic_id:w -> pic:in1:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articlepic_pic", constraint=false, weight=1]; - brandpic:brand_id:w -> brand:in1:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_brandpic_brand", weight=3]; - brandpic:pic_id:e -> pic:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_brandpic_pic", constraint=false, weight=1]; - articlelistarticle:articlelist_id:sw -> articlelist:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_articlelistarticle_articlelist", weight=3]; - articlelistarticle:article_id:sw -> article:in8:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_articlelistarticle_article", constraint=false, weight=1]; - optionslistarticle:optionslist_id:se -> optionslist:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_optionslistarticle_optionslist", weight=3]; - optionslistarticle:article_id:e -> article:in11:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_optionslistarticle_article", constraint=false, weight=1]; - categoryarticle:category_id:nw -> category:in4:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_categoryarticle_category", weight=3]; - categoryarticle:article_id:w -> article:in2:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_categoryarticle_article", constraint=false, weight=1]; - categorypic:category_id:w -> category:in2:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_categorypic_category", weight=3]; - categorypic:pic_id:w -> pic:in2:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_categorypic_pic", constraint=false, weight=1]; - categorytext:category_id:w -> category:in5:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_categorytext_category", weight=3]; - categorytext:language_id:e -> language:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_categorytext_language", constraint=false, weight=1]; - articletext:article_id:w -> article:in9:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_articletext_article", weight=3]; - articletext:language_id:e -> language:in1:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_articletext_language", constraint=false, weight=1]; - price:tax_id:w -> tax:in0:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_price_tax", constraint=false, weight=1]; - price:article_id:e -> article:in7:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_price_article", weight=3]; - price:customergroup_id:e -> customergroup:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_price_customergroup", constraint=false, weight=1]; - articlesupplier:article_id:sw -> article:in10:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_articlesupplier_article", weight=3]; - articlesupplier:entity_id:e -> entity:in2:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_articlesupplier_entity", constraint=false, weight=1]; - articlesupplier:price_id:e -> price:in0:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articlesupplier_price", constraint=false, weight=1]; - manifest:company_id:w -> company:in17:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_manifest_company", weight=3]; - manifest:entity_id:e -> entity:in4:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_manifest_entity", constraint=false, weight=1]; - manifestarticle:manifest_id:sw -> manifest:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_manifestarticle_manifest", weight=3]; - warehouse:company_id:w -> company:in15:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_warehouse_company", weight=3]; - ledger:manifestarticle_id:sw -> manifestarticle:in0:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_ledger_manifestarticle", weight=3]; - ledger:warehouse_id:w -> warehouse:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_ledger_warehouse", constraint=false, weight=1]; - numbers:company_id:se -> company:in8:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_numbers_company", weight=3]; - companyuser:google_auth_id:e -> google_auth:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_companyuser_google_auth", constraint=false, weight=1]; - companyuser:company_id:sw -> company:in10:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_companyuser_company", weight=3]; - modelconversation:companyuser_id:w -> companyuser:in1:n [color="#a98cff", fontcolor="#a98cff", tooltip="FK_modelconversation_companyuser", weight=3]; - modelvfs:company_id:w -> company:in11:n [color="#ff6f6f", fontcolor="#ff6f6f", tooltip="FK_modelvfs_company", weight=3]; - modelmessage:conversation_id:se -> modelconversation:in0:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="FK_modelmessage_conversation", weight=3]; - syncpos:company_id:e -> company:in13:n [color="#5aa7e6", fontcolor="#5aa7e6", tooltip="FK_syncpos_company", weight=3]; - companysetting:company_id:w -> company:in14:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="FK_companysetting_company", weight=3]; - posterminal:company_id:se -> company:in12:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="FK_posterminal_company", weight=3]; - posterminalcategory:posterminal_id:se -> posterminal:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="FK_posterminalcategory_posterminal", weight=3]; - posterminalcategory:category_id:w -> category:in6:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="FK_posterminalcategory_category", constraint=false, weight=1]; - printer:company_id:se -> company:in6:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="FK_printer_company", weight=3]; - labeltemplate:company_id:se -> company:in9:n [color="#56d68a", fontcolor="#56d68a", tooltip="FK_labeltemplate_company", weight=3]; - manifestattachment:manifest_id:sw -> manifest:in1:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="FK_manifestattachment_manifest", weight=3]; - manifestattachment:file_id:w -> file:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_manifestattachment_file", constraint=false, weight=1]; - propertyname:company_id:e -> company:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="FK_propertyname_company", weight=3]; - articleproperty:article_id:w -> article:in0:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="FK_articleproperty_article", weight=3]; - articleproperty:property_id:w -> propertyname:in1:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="FK_articleproperty_property", constraint=false, weight=1]; - attributename:company_id:e -> company:in1:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_attributename_company", weight=3]; - attributevalue:attribute_id:se -> attributename:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_attributevalue_attribute", weight=3]; - articleattributevalue:article_id:w -> article:in1:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_articleattributevalue_article", weight=3]; - articleattributevalue:attributevalue_id:w -> attributevalue:in0:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="FK_articleattributevalue_attributevalue", constraint=false, weight=1]; - categoryproperty:category_id:w -> category:in0:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_categoryproperty_category", weight=3]; - categoryproperty:property_id:w -> propertyname:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="FK_categoryproperty_property", constraint=false, weight=1]; - categoryattributevalue:category_id:w -> category:in1:n [color="#58d18a", fontcolor="#58d18a", tooltip="FK_categoryattributevalue_category", weight=3]; - categoryattributevalue:attributevalue_id:w -> attributevalue:in1:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_categoryattributevalue_attributevalue", constraint=false, weight=1]; + 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: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]; + articlepic:article_id:se -> article:in4:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="FK_articlepic_article", weight=3]; + articlepic:pic_id:w -> pic:in1: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:pic_id:e -> pic:in0:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="FK_brandpic_pic", constraint=false, weight=1]; + articlelistarticle:articlelist_id:sw -> articlelist:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="FK_articlelistarticle_articlelist", weight=3]; + articlelistarticle:article_id:sw -> article:in8: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: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: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]; + price:article_id:e -> article:in7: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]; + 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]; + 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]; + 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]; + 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]; + 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]; + 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]; + 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]; + 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]; + articleproperty:article_id:w -> article:in0:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="FK_articleproperty_article", weight=3]; + articleproperty:property_id:w -> propertyname:in1:n [color="#c79bff", fontcolor="#c79bff", tooltip="FK_articleproperty_property", constraint=false, weight=1]; + attributename:company_id:e -> company:in1:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="FK_attributename_company", weight=3]; + 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: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: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 7e44c4d..e7713c1 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,78 +110,79 @@ 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 - - + + @@ -189,109 +190,109 @@ 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 - - + + @@ -299,8 +300,8 @@ company:e->tax:n - - + + @@ -308,55 +309,13 @@ company:e->tax:n - - - - - - - -numbers - - -numbers - - -id -INT -PK - - -company_id -INT -FK - - -type -NVARCHAR(100) - - -prefix -NVARCHAR(50) - - -padding -INT - - -next -INT - - - -numbers:se->company:n - - - + + - + entityaddress @@ -459,6 +418,81 @@ + + +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 + + + + + + entity:nw->customergroup:n @@ -468,85 +502,45 @@ - + -companyuser - - - - - -companyuser - - -id -INT -PK - - -company_id -INT -FK - - -google_auth_id -INT -FK +numbers + + +numbers + + +id +INT +PK + + +company_id +INT +FK + + +type +NVARCHAR(100) + + +prefix +NVARCHAR(50) + + +padding +INT + + +next +INT - + -companyuser:sw->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 - - - +numbers:nw->company:n + + + @@ -588,37 +582,60 @@ - - -syncpos - - -syncpos - - -id -INT -PK - - -company_id -INT -FK - - -paircode -NVARCHAR(50) - - -token? -NVARCHAR(255) + + +companyuser:w->company:n + + + + - - -syncpos:e->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 + + + @@ -666,50 +683,84 @@ entityhistory:se->companyuser:n - - + + + + + + + +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 - - - + + + @@ -717,421 +768,421 @@ 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 - - - + + + - + 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:e->language:n - - - + +articletext:w->language:n + + + - + article - - - - - - - - - - - - - - -article - - -id -INT -PK - - -fatherattributename_id -? -INT -FK - - -brand_id -? -INT -FK - - -fatherarticle_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_father -BIT - - -fathersort -INT - - -created_at -DATETIME2 - - -updated_at -DATETIME2 + + + + + + + + + + + + + + +article + + +id +INT +PK + + +fatherattributename_id +? +INT +FK + + +brand_id +? +INT +FK + + +fatherarticle_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_father +BIT + + +fathersort +INT + + +created_at +DATETIME2 + + +updated_at +DATETIME2 - -articletext:w->article:n - - - + +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 - - + + - + 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:nw->category:n - - - + +categoryarticle:ne->category:n + + + - + categoryarticle:w->article:n - - - + + + @@ -1139,48 +1190,48 @@ 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 - - + + @@ -1188,38 +1239,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 - - - + + + @@ -1227,8 +1278,8 @@ article:e->company:n - - + + @@ -1236,8 +1287,8 @@ article:e->brand:n - - + + @@ -1245,54 +1296,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 - - + + @@ -1300,13 +1351,13 @@ article:w->unit:n - - + + - + attributename @@ -1341,7 +1392,7 @@ article:sw->attributename:n - + @@ -1350,464 +1401,464 @@ 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 + + +price_id +? +INT +FK + + +entity_id +INT +FK + + +sku? +NVARCHAR(100) + + +stock? +FLOAT + + +pu +FLOAT + + +sort +INT - + articlesupplier:e->entity:n - - - + + + - + 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 + + + +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 - - - + + + - + 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 - - - + + + - + 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 - - - + + + - + 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 - - - + + + - + 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 - - - + + + - + 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 - - - + + + - + 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 @@ -1833,16 +1884,16 @@ INT - + warehouse:w->company:n - - - + + + - + manifestarticle @@ -1892,7 +1943,7 @@ FLOAT - + manifest @@ -1937,34 +1988,34 @@ DATETIME2 - + manifestarticle:sw->manifest:n - - - + + + - + manifest:w->company:n - - - + + + - + manifest:e->entity:n - - - + + + - + ledger @@ -2011,25 +2062,25 @@ DATETIME2 - + ledger:w->warehouse:n - - - + + + - + ledger:sw->manifestarticle:n - - - + + + - + manifestattachment @@ -2055,47 +2106,47 @@ INT - + manifestattachment:w->file:n - - - + + + - + manifestattachment:sw->manifest:n - - - + + + - + price:e->customergroup:n - - - + + + - + price:e->article:n - - - + + + - + price:w->tax:n - - - + + + @@ -2103,208 +2154,208 @@ 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 + + +company_id +INT +FK + + +name +NVARCHAR(255) + + +token? +NVARCHAR(255) + + +pairingpin +NVARCHAR(50) + + +paired_at? +DATETIME2 + + +clientserial? +NVARCHAR(255) + + +maxknowntombstoneid? +INT - + posterminal:se->company: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 - - - + + + - + posterminalcategory:se->posterminal:n - - - + + + - + modelmessage @@ -2333,7 +2384,7 @@ NVARCHAR(MAX) - + modelconversation @@ -2371,25 +2422,25 @@ NVARCHAR(20) - + modelmessage:se->modelconversation:n - - - + + + - + modelconversation:w->companyuser:n - - - + + + - + modelvfs @@ -2430,16 +2481,16 @@ DATETIME2 - + modelvfs:w->company:n - - - + + + - + attributevalue @@ -2466,16 +2517,16 @@ INT - + attributevalue:se->attributename:n - - - + + + - + propertyname @@ -2506,117 +2557,117 @@ BIT - + propertyname:e->company:n - - - + + + - + 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 - - - + + + - + 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 - - - + + + - + categoryattributevalue:w->attributevalue:n - - - + + + - + articleproperty @@ -2646,25 +2697,25 @@ INT - + articleproperty:w->article:n - - - + + + - + articleproperty:w->propertyname:n - - - + + + - + articleattributevalue @@ -2690,50 +2741,50 @@ INT - + articleattributevalue:w->article:n - - - + + + - + articleattributevalue:w->attributevalue:n - - - + + + - + __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 c182da6..11dfc92 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,8 @@ import companyCreate from './store/company/create.js'; import companyUpdate from './store/company/update.js'; import companyDelete from './store/company/delete.js'; import companyList from './store/company/list.js'; +import companyAddHistory from './store/company/addHistory.js'; +import companyGetHistory from './store/company/getHistory.js'; import categoryGetTreeForCompany from './store/category/getTreeForCompany.js'; import categoryGetCategoryArticles from './store/category/getCategoryArticles.js'; import categoryCreateUnderParent from './store/category/createUnderParent.js'; @@ -234,6 +236,8 @@ export default class LibDashStore { update: companyUpdate(provider), delete: companyDelete(provider), list: companyList(provider), + addHistory: companyAddHistory(provider), + getHistory: companyGetHistory(provider), }; this.category = { diff --git a/src/providers/mssql/purgeSql.js b/src/providers/mssql/purgeSql.js index d7b34ed..4858e98 100644 --- a/src/providers/mssql/purgeSql.js +++ b/src/providers/mssql/purgeSql.js @@ -34,6 +34,7 @@ export const TABLES = [ 'articleean', 'articlehistory', 'entityhistory', + 'companyhistory', 'entityaddress', 'entitycontact', 'article', diff --git a/src/providers/mssql/queries/companyhistory.js b/src/providers/mssql/queries/companyhistory.js new file mode 100644 index 0000000..ce9322f --- /dev/null +++ b/src/providers/mssql/queries/companyhistory.js @@ -0,0 +1,19 @@ +export const INSERT = ` +INSERT INTO companyhistory (company_id, companyuser_id, [text]) +OUTPUT INSERTED.id, INSERTED.companyuser_id AS companyuserId, INSERTED.[date], INSERTED.[text] +VALUES (@companyId, @companyuserId, @text) +`; + +export const LIST_BY_COMPANY_ID = ` +SELECT id, companyuser_id AS companyuserId, [date], [text] +FROM companyhistory +WHERE company_id = @companyId +ORDER BY [date] DESC, id DESC +`; + +export const LIST_BY_COMPANY_ID_LIMITED = ` +SELECT TOP (@limit) id, companyuser_id AS companyuserId, [date], [text] +FROM companyhistory +WHERE company_id = @companyId +ORDER BY [date] DESC, id DESC +`; diff --git a/src/providers/mssql/schema.js b/src/providers/mssql/schema.js index a6ebc73..63cdb94 100644 --- a/src/providers/mssql/schema.js +++ b/src/providers/mssql/schema.js @@ -374,6 +374,20 @@ BEGIN ); END `; +export const INIT_COMPANYHISTORY = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'companyhistory') +BEGIN + CREATE TABLE companyhistory ( + id INT IDENTITY(1,1) PRIMARY KEY, + company_id INT NOT NULL, + companyuser_id INT NULL, + [date] DATETIME2 NOT NULL CONSTRAINT DF_companyhistory_date DEFAULT SYSUTCDATETIME(), + [text] NVARCHAR(MAX) NOT NULL, + CONSTRAINT FK_companyhistory_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, + CONSTRAINT FK_companyhistory_companyuser FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE SET NULL + ); +END +`; export const INIT_ARTICLETOMBSTONE = ` IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'articletombstone') @@ -1147,6 +1161,7 @@ export const SCHEMA_SCRIPTS = [ INIT_ARTICLEHISTORY, INIT_ARTICLETOMBSTONE, INIT_ENTITYHISTORY, + INIT_COMPANYHISTORY, INIT_SYNCPOS, INIT_COMPANYSETTING, INIT_POSTERMINAL, diff --git a/src/providers/sqlite3/queries/companyhistory.js b/src/providers/sqlite3/queries/companyhistory.js new file mode 100644 index 0000000..e7b1e2d --- /dev/null +++ b/src/providers/sqlite3/queries/companyhistory.js @@ -0,0 +1,13 @@ +import * as source from '../../mssql/queries/companyhistory.js'; +import { translateQueries } from './translate.js'; + +const queries = translateQueries(source, 'companyhistory'); +export const { INSERT, LIST_BY_COMPANY_ID } = queries; + +export const LIST_BY_COMPANY_ID_LIMITED = ` +SELECT id, companyuser_id AS companyuserId, date, text +FROM companyhistory +WHERE company_id = @companyId +ORDER BY date DESC, id DESC +LIMIT @limit +`; diff --git a/src/providers/sqlite3/schema.js b/src/providers/sqlite3/schema.js index e0a8270..2fe56c1 100644 --- a/src/providers/sqlite3/schema.js +++ b/src/providers/sqlite3/schema.js @@ -536,6 +536,17 @@ CREATE TABLE IF NOT EXISTS articlehistory ( FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE SET NULL ); `; +export const INIT_COMPANYHISTORY = ` +CREATE TABLE IF NOT EXISTS companyhistory ( + id INTEGER PRIMARY KEY, + company_id INTEGER NOT NULL, + companyuser_id INTEGER, + "date" TEXT NOT NULL DEFAULT (${UTC_NOW}), + "text" TEXT NOT NULL, + FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, + FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE SET NULL +); +`; export const INIT_ARTICLETOMBSTONE = ` CREATE TABLE IF NOT EXISTS articletombstone ( @@ -818,6 +829,7 @@ export const SCHEMA_SCRIPTS = [ INIT_ARTICLEHISTORY, INIT_ARTICLETOMBSTONE, INIT_ENTITYHISTORY, + INIT_COMPANYHISTORY, INIT_SYNCPOS, INIT_COMPANYSETTING, INIT_POSTERMINAL, diff --git a/src/store/company/addHistory.js b/src/store/company/addHistory.js new file mode 100644 index 0000000..34a1847 --- /dev/null +++ b/src/store/company/addHistory.js @@ -0,0 +1,54 @@ +import { INSERT as MSSQL_INSERT } from '../../providers/mssql/queries/companyhistory.js'; +import { INSERT as SQLITE_INSERT } from '../../providers/sqlite3/queries/companyhistory.js'; +import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; +import makeRunner from '../runner.js'; + +export default function addHistory(provider) { + const access = resolveSelectedCompanyAccess(provider); + const isSqlite = provider?.dialect === 'sqlite3'; + const sql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT; + + /** + * Adds an entry to the company history for the user's selected company. + * + * @param {number} googleAuthId - The id of the Google auth user. + * @param {object|string} input - The history input object or text string. + * @param {string} [input.text] - The history entry text. + * @param {object} [tx] - Optional transaction. + * @returns {Promise<{id: number, companyuserId: number|null, date: string, text: string}>} The inserted entry. + * @throws {Error} If text is missing or user is not authorized. + * + * @example + * const entry = await store.company.addHistory(42, { text: 'API suggestion: add barcode scanner endpoint' }); + * // => { id, companyuserId, date, text } + */ + return async (googleAuthId, input, tx) => { + let rawText = typeof input === 'string' ? input : input?.text; + const text = typeof rawText === 'string' ? rawText.trim() : ''; + if (!text) { + throw new Error('Text required'); + } + + let resolvedTx = tx; + if (input != null && typeof input === 'object' && input._isTx) { + resolvedTx = input; + } + + const runner = makeRunner(provider, resolvedTx); + const { companyId, companyuserId } = await access(googleAuthId, runner); + + const result = await runner.query(sql, { + companyId, + companyuserId: companyuserId ?? null, + text, + }); + + const row = result.rows[0]; + return { + id: row.id, + companyuserId: row.companyuserId ?? null, + date: row.date, + text: row.text, + }; + }; +} diff --git a/src/store/company/getHistory.js b/src/store/company/getHistory.js new file mode 100644 index 0000000..fc4353e --- /dev/null +++ b/src/store/company/getHistory.js @@ -0,0 +1,54 @@ +import { LIST_BY_COMPANY_ID as MSSQL_QUERY, LIST_BY_COMPANY_ID_LIMITED as MSSQL_QUERY_LIMITED } from '../../providers/mssql/queries/companyhistory.js'; +import { LIST_BY_COMPANY_ID as SQLITE_QUERY, LIST_BY_COMPANY_ID_LIMITED as SQLITE_QUERY_LIMITED } from '../../providers/sqlite3/queries/companyhistory.js'; +import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; +import makeRunner from '../runner.js'; + +export default function getHistory(provider) { + const access = resolveSelectedCompanyAccess(provider); + const isSqlite = provider?.dialect === 'sqlite3'; + const sql = isSqlite ? SQLITE_QUERY : MSSQL_QUERY; + const sqlLimited = isSqlite ? SQLITE_QUERY_LIMITED : MSSQL_QUERY_LIMITED; + + /** + * Returns the company history for the user's selected company, newest first. + * + * @param {number} googleAuthId - The id of the Google auth user. + * @param {object} [opts] - Optional options. + * @param {number} [opts.limit] - Maximum number of entries to return (newest first). + * @param {object} [tx] - Optional transaction. + * @returns {Promise>} The company history entries. + * + * @example + * const history = await store.company.getHistory(42); + * // => [{ id, companyuserId, date, text }] + * + * const recent = await store.company.getHistory(42, { limit: 5 }); + * // => up to 5 most recent entries + */ + return async (googleAuthId, opts, tx) => { + let limit = null; + let resolvedTx = tx; + if (opts != null && typeof opts === 'object' && !opts._isTx) { + limit = opts.limit != null ? Number(opts.limit) : null; + } else if (opts != null) { + resolvedTx = opts; + } + + const runner = makeRunner(provider, resolvedTx); + const { companyId } = await access(googleAuthId, runner); + + let result; + if (limit != null && Number.isInteger(limit) && limit > 0) { + result = await runner.query(sqlLimited, { companyId, limit }); + } else { + result = await runner.query(sql, { companyId }); + } + + return result.rows.map((row) => ({ + id: row.id, + companyuserId: row.companyuserId ?? null, + date: row.date, + text: row.text, + })); + }; +}