From f3674edcb79f5988e9bd248332a962edfa64fabc Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 9 Oct 2026 10:41:17 +0200 Subject: [PATCH] u --- API.account.md | 84 +++++++++++++++++ API.md | 16 ++++ API.package.md | 84 +++++++++++++++++ API.payment.md | 83 +++++++++++++++++ API.shipping.md | 82 +++++++++++++++++ src/index.js | 36 ++++++++ src/providers/mssql/purgeSql.js | 4 + src/providers/mssql/queries/logistics.js | 100 +++++++++++++++++++++ src/providers/mssql/schema.js | 63 +++++++++++++ src/providers/sqlite3/queries/logistics.js | 21 +++++ src/providers/sqlite3/schema.js | 51 +++++++++++ src/store/account/create.js | 43 +++++++++ src/store/account/delete.js | 27 ++++++ src/store/account/list.js | 30 +++++++ src/store/logistics/helpers.js | 25 ++++++ src/store/package/create.js | 93 +++++++++++++++++++ src/store/package/delete.js | 26 ++++++ src/store/package/listByShippingId.js | 41 +++++++++ src/store/payment/create.js | 75 ++++++++++++++++ src/store/payment/delete.js | 26 ++++++ src/store/payment/listByManifestId.js | 37 ++++++++ src/store/shipping/create.js | 71 +++++++++++++++ src/store/shipping/delete.js | 26 ++++++ src/store/shipping/listByManifestId.js | 37 ++++++++ 24 files changed, 1181 insertions(+) create mode 100644 API.account.md create mode 100644 API.package.md create mode 100644 API.payment.md create mode 100644 API.shipping.md create mode 100644 src/providers/mssql/queries/logistics.js create mode 100644 src/providers/sqlite3/queries/logistics.js create mode 100644 src/store/account/create.js create mode 100644 src/store/account/delete.js create mode 100644 src/store/account/list.js create mode 100644 src/store/logistics/helpers.js create mode 100644 src/store/package/create.js create mode 100644 src/store/package/delete.js create mode 100644 src/store/package/listByShippingId.js create mode 100644 src/store/payment/create.js create mode 100644 src/store/payment/delete.js create mode 100644 src/store/payment/listByManifestId.js create mode 100644 src/store/shipping/create.js create mode 100644 src/store/shipping/delete.js create mode 100644 src/store/shipping/listByManifestId.js diff --git a/API.account.md b/API.account.md new file mode 100644 index 0000000..7d077f2 --- /dev/null +++ b/API.account.md @@ -0,0 +1,84 @@ +# account + +This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`. + +## `account.create` + +*Source: `src/store/account/create.js`* + +Creates an account for the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `input` | `object` | Account input. | +| `input.type` | `string` | Account type. | +| `input.name` | `string` | Account name. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise<{id: number, companyId: number, type: string, name: string}>` + +**Throws** + +`Error` — If type or name is missing. + +**Example** + +```js +const account = await store.account.create(googleAuthId, { type: 'bank', name: 'Main' }); +``` + +## `account.delete` + +*Source: `src/store/account/delete.js`* + +Deletes an account of the user's selected company. Its payments are removed by cascade. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `id` | `number` | The account id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise` + +**Throws** + +`Error` — If the account id is invalid. + +**Example** + +```js +await store.account.delete(googleAuthId, 3); +``` + +## `account.list` + +*Source: `src/store/account/list.js`* + +Lists accounts for the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise>` + +**Example** + +```js +const accounts = await store.account.list(googleAuthId); +``` diff --git a/API.md b/API.md index b56a045..4e1db4f 100644 --- a/API.md +++ b/API.md @@ -275,6 +275,10 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `getById(googleAuthId: number, id: number, tx?: object): Promise<{id: number, company_id: number, name: string, width: number, height: number, dpi: number, type: string, content: object, thumb: Buffer|null}|undefined>` - `list(googleAuthId: number, tx?: object): Promise>` - `update(googleAuthId: number, id: number, input: {name?: string, width?: number, height?: number, dpi?: number, type?: string, content?: object, thumb?: Buffer|null}, tx?: object): Promise<{id: number, company_id: number, name: string, width: number, height: number, dpi: number, type: string, content: object, thumb: Buffer|null}>` +- [account](API.account.md) + - `create(googleAuthId: number, input: {type: string, name: string}, tx?: object): Promise<{id: number, companyId: number, type: string, name: string}>` + - `delete(googleAuthId: number, id: number, tx?: object): Promise` + - `list(googleAuthId: number, tx?: object): Promise>` - [articlelist](API.articlelist.md) - `getItemsByArticleSku(googleAuthId: number, sku: string, tx?: object): Promise>` - `setItemsByArticleSku(googleAuthId: number, sku: string, items?: Array<{articleId?: number, sku?: string, count?: number, sort?: number}>, tx?: object): Promise>` @@ -303,5 +307,17 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - [optionslist](API.optionslist.md) - `getOptionsByArticleSku(googleAuthId: number, sku: string, tx?: object): Promise>` - `setOptionsByArticleSku(googleAuthId: number, sku: string, options?: Array<{articleId?: number, sku?: string, count?: number, sort?: number, mandated?: boolean}>, tx?: object): Promise>` +- [package](API.package.md) + - `create(googleAuthId: number, input: {shippingId: number, entityaddressId: number, type: string, state: string, details?: string}, tx?: object): Promise<{id: number, shippingId: number, entityaddressId: number, number: string, type: string, state: string, details: string|null}>` + - `delete(googleAuthId: number, id: number, tx?: object): Promise` + - `listByShippingId(googleAuthId: number, shippingId: number, tx?: object): Promise>` +- [payment](API.payment.md) + - `create(googleAuthId: number, input: {accountId: number, manifestId: number, type: string, amount: number}, tx?: object): Promise<{id: number, accountId: number, manifestId: number, type: string, amount: number}>` + - `delete(googleAuthId: number, id: number, tx?: object): Promise` + - `listByManifestId(googleAuthId: number, manifestId: number, tx?: object): Promise>` - [runner.js](API.runner.js.md) - `runner(provider: import('../providers/provider.js').DatabaseProvider, tx?: object): ((sql: string, params?: object) => Promise) & { query: Function, dialect?: string }` +- [shipping](API.shipping.md) + - `create(googleAuthId: number, input: {manifestId: number, type: string, state: string}, tx?: object): Promise<{id: number, manifestId: number, number: string, type: string, state: string}>` + - `delete(googleAuthId: number, id: number, tx?: object): Promise` + - `listByManifestId(googleAuthId: number, manifestId: number, tx?: object): Promise>` diff --git a/API.package.md b/API.package.md new file mode 100644 index 0000000..76b8ed6 --- /dev/null +++ b/API.package.md @@ -0,0 +1,84 @@ +# package + +This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`. + +## `package.create` + +*Source: `src/store/package/create.js`* + +Creates a package for a shipping. The number is allocated from the `package` numbers sequence (own prefix + counter). The package must target an entity address. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `input` | `object` | Package input. | +| `input.shippingId` | `number` | The shipping id. | +| `input.entityaddressId` | `number` | The target entity address id (required). | +| `input.type` | `string` | Package type. | +| `input.state` | `string` | Package state. | +| `[input.details]` | `string` | Optional details. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise<{id: number, shippingId: number, entityaddressId: number, number: string, type: string, state: string, details: string|null}>` + +**Throws** + +`Error` — If shipping or entity address is not found, or input is invalid. + +**Example** + +```js +await store.package.create(googleAuthId, { shippingId: 9, entityaddressId: 3, type: 'box', state: 'packed' }); +``` + +## `package.delete` + +*Source: `src/store/package/delete.js`* + +Deletes a package of the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `id` | `number` | The package id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise` + +**Example** + +```js +await store.package.delete(googleAuthId, 12); +``` + +## `package.listByShippingId` + +*Source: `src/store/package/listByShippingId.js`* + +Lists packages of a shipping in the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `shippingId` | `number` | The shipping id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise>` + +**Example** + +```js +const packages = await store.package.listByShippingId(googleAuthId, 9); +``` diff --git a/API.payment.md b/API.payment.md new file mode 100644 index 0000000..7264984 --- /dev/null +++ b/API.payment.md @@ -0,0 +1,83 @@ +# payment + +This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`. + +## `payment.create` + +*Source: `src/store/payment/create.js`* + +Adds a payment to a manifest (order) using an account of the selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `input` | `object` | Payment input. | +| `input.accountId` | `number` | The account id. | +| `input.manifestId` | `number` | The manifest (order) id. | +| `input.type` | `string` | Payment type. | +| `input.amount` | `number` | Payment amount. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise<{id: number, accountId: number, manifestId: number, type: string, amount: number}>` + +**Throws** + +`Error` — If account or manifest is not found, or input is invalid. + +**Example** + +```js +await store.payment.create(googleAuthId, { accountId: 1, manifestId: 42, type: 'cash', amount: 19.9 }); +``` + +## `payment.delete` + +*Source: `src/store/payment/delete.js`* + +Deletes a payment belonging to a manifest of the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `id` | `number` | The payment id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise` + +**Example** + +```js +await store.payment.delete(googleAuthId, 7); +``` + +## `payment.listByManifestId` + +*Source: `src/store/payment/listByManifestId.js`* + +Lists payments of a manifest (order) in the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `manifestId` | `number` | The manifest id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise>` + +**Example** + +```js +const payments = await store.payment.listByManifestId(googleAuthId, 42); +``` diff --git a/API.shipping.md b/API.shipping.md new file mode 100644 index 0000000..77744d7 --- /dev/null +++ b/API.shipping.md @@ -0,0 +1,82 @@ +# shipping + +This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`. + +## `shipping.create` + +*Source: `src/store/shipping/create.js`* + +Creates a shipping for a manifest (order). The number is allocated from the `shipping` numbers sequence (own prefix + counter). + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `input` | `object` | Shipping input. | +| `input.manifestId` | `number` | The manifest (order) id. | +| `input.type` | `string` | Shipping type. | +| `input.state` | `string` | Shipping state. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise<{id: number, manifestId: number, number: string, type: string, state: string}>` + +**Throws** + +`Error` — If manifest is not found or input is invalid. + +**Example** + +```js +await store.shipping.create(googleAuthId, { manifestId: 42, type: 'parcel', state: 'open' }); +``` + +## `shipping.delete` + +*Source: `src/store/shipping/delete.js`* + +Deletes a shipping of the user's selected company. Its packages are removed by cascade. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `id` | `number` | The shipping id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise` + +**Example** + +```js +await store.shipping.delete(googleAuthId, 9); +``` + +## `shipping.listByManifestId` + +*Source: `src/store/shipping/listByManifestId.js`* + +Lists shippings of a manifest (order) in the user's selected company. + +**Parameters** + +| Name | Type | Description | +| --- | --- | --- | +| `googleAuthId` | `number` | The id of the Google auth user. | +| `manifestId` | `number` | The manifest id. | +| `[tx]` | `object` | Optional transaction to run within. | + +**Returns** + +`Promise>` + +**Example** + +```js +const shippings = await store.shipping.listByManifestId(googleAuthId, 42); +``` diff --git a/src/index.js b/src/index.js index a360c0b..05a69d9 100644 --- a/src/index.js +++ b/src/index.js @@ -172,6 +172,18 @@ import modelvfsRead from './store/modelvfs/read.js'; import modelvfsList from './store/modelvfs/list.js'; import modelvfsDelete from './store/modelvfs/delete.js'; import modelvfsReset from './store/modelvfs/reset.js'; +import accountCreate from './store/account/create.js'; +import accountList from './store/account/list.js'; +import accountDelete from './store/account/delete.js'; +import paymentCreate from './store/payment/create.js'; +import paymentListByManifestId from './store/payment/listByManifestId.js'; +import paymentDelete from './store/payment/delete.js'; +import shippingCreate from './store/shipping/create.js'; +import shippingListByManifestId from './store/shipping/listByManifestId.js'; +import shippingDelete from './store/shipping/delete.js'; +import packageCreate from './store/package/create.js'; +import packageListByShippingId from './store/package/listByShippingId.js'; +import packageDelete from './store/package/delete.js'; import labeltemplateCreate from './store/labeltemplate/create.js'; import labeltemplateGetById from './store/labeltemplate/getById.js'; @@ -418,6 +430,30 @@ export default class LibDashStore { touchLastseen: posterminalTouchLastseen(provider), }; + this.account = { + create: accountCreate(provider), + list: accountList(provider), + delete: accountDelete(provider), + }; + + this.payment = { + create: paymentCreate(provider), + listByManifestId: paymentListByManifestId(provider), + delete: paymentDelete(provider), + }; + + this.shipping = { + create: shippingCreate(provider), + listByManifestId: shippingListByManifestId(provider), + delete: shippingDelete(provider), + }; + + this.package = { + create: packageCreate(provider), + listByShippingId: packageListByShippingId(provider), + delete: packageDelete(provider), + }; + this.google_auth = { add: googleAuthAdd(provider), getByEmail: googleAuthGetByEmail(provider), diff --git a/src/providers/mssql/purgeSql.js b/src/providers/mssql/purgeSql.js index 57d6841..9bed341 100644 --- a/src/providers/mssql/purgeSql.js +++ b/src/providers/mssql/purgeSql.js @@ -1,5 +1,9 @@ /** Drop order = reverse of schema create dependency order. */ export const TABLES = [ + 'package', + 'shipping', + 'payment', + 'account', 'articleattributevalue', 'articleproperty', 'attributevalue', diff --git a/src/providers/mssql/queries/logistics.js b/src/providers/mssql/queries/logistics.js new file mode 100644 index 0000000..0a617f3 --- /dev/null +++ b/src/providers/mssql/queries/logistics.js @@ -0,0 +1,100 @@ +export const CHECK_ACCOUNT_COMPANY = ` +SELECT id +FROM account +WHERE id = @accountId AND company_id = @companyId +`; + +export const CHECK_ENTITYADDRESS_COMPANY = ` +SELECT ea.id +FROM entityaddress ea +INNER JOIN entity e ON e.id = ea.entity_id +INNER JOIN customergroup cg ON cg.id = e.customergroup_id +WHERE ea.id = @entityaddressId AND cg.company_id = @companyId +`; + +export const CHECK_SHIPPING_COMPANY = ` +SELECT s.id +FROM shipping s +INNER JOIN manifest m ON m.id = s.manifest_id +WHERE s.id = @shippingId AND m.company_id = @companyId +`; + +export const ACCOUNT_CREATE = ` +INSERT INTO account (company_id, [type], [name]) +OUTPUT INSERTED.id, INSERTED.company_id, INSERTED.[type], INSERTED.[name] +VALUES (@companyId, @type, @name) +`; + +export const ACCOUNT_LIST = ` +SELECT id, company_id, [type], [name] +FROM account +WHERE company_id = @companyId +ORDER BY [name] ASC, id ASC +`; + +export const ACCOUNT_DELETE = ` +DELETE FROM account +WHERE id = @id AND company_id = @companyId +`; + +export const PAYMENT_CREATE = ` +INSERT INTO payment (account_id, manifest_id, [type], amount) +OUTPUT INSERTED.id, INSERTED.account_id, INSERTED.manifest_id, INSERTED.[type], INSERTED.amount +VALUES (@accountId, @manifestId, @type, @amount) +`; + +export const PAYMENT_LIST_BY_MANIFEST = ` +SELECT id, account_id, manifest_id, [type], amount +FROM payment +WHERE manifest_id = @manifestId +ORDER BY id ASC +`; + +export const PAYMENT_DELETE = ` +DELETE FROM payment +WHERE id = @id + AND manifest_id IN (SELECT m.id FROM manifest m WHERE m.company_id = @companyId) +`; + +export const SHIPPING_CREATE = ` +INSERT INTO shipping (manifest_id, [number], [type], [state]) +OUTPUT INSERTED.id, INSERTED.manifest_id, INSERTED.[number], INSERTED.[type], INSERTED.[state] +VALUES (@manifestId, @number, @type, @state) +`; + +export const SHIPPING_LIST_BY_MANIFEST = ` +SELECT id, manifest_id, [number], [type], [state] +FROM shipping +WHERE manifest_id = @manifestId +ORDER BY id ASC +`; + +export const SHIPPING_DELETE = ` +DELETE FROM shipping +WHERE id = @id + AND manifest_id IN (SELECT m.id FROM manifest m WHERE m.company_id = @companyId) +`; + +export const PACKAGE_CREATE = ` +INSERT INTO package (shipping_id, entityaddress_id, [number], [type], [state], details) +OUTPUT INSERTED.id, INSERTED.shipping_id, INSERTED.entityaddress_id, INSERTED.[number], INSERTED.[type], INSERTED.[state], INSERTED.details +VALUES (@shippingId, @entityaddressId, @number, @type, @state, @details) +`; + +export const PACKAGE_LIST_BY_SHIPPING = ` +SELECT id, shipping_id, entityaddress_id, [number], [type], [state], details +FROM package +WHERE shipping_id = @shippingId +ORDER BY id ASC +`; + +export const PACKAGE_DELETE = ` +DELETE FROM package +WHERE id = @id + AND shipping_id IN ( + SELECT s.id + FROM shipping s + INNER JOIN manifest m ON m.id = s.manifest_id + WHERE m.company_id = @companyId + ) +`; diff --git a/src/providers/mssql/schema.js b/src/providers/mssql/schema.js index eb45263..6882502 100644 --- a/src/providers/mssql/schema.js +++ b/src/providers/mssql/schema.js @@ -1094,6 +1094,65 @@ BEGIN END `; +export const INIT_ACCOUNT = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'account') +BEGIN + CREATE TABLE account ( + id INT IDENTITY(1,1) PRIMARY KEY, + company_id INT NOT NULL, + [type] NVARCHAR(100) NOT NULL, + [name] NVARCHAR(255) NOT NULL, + CONSTRAINT FK_account_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE + ); +END +`; + +export const INIT_PAYMENT = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'payment') +BEGIN + CREATE TABLE payment ( + id INT IDENTITY(1,1) PRIMARY KEY, + account_id INT NOT NULL, + manifest_id INT NOT NULL, + [type] NVARCHAR(100) NOT NULL, + amount FLOAT NOT NULL, + CONSTRAINT FK_payment_account FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE, + CONSTRAINT FK_payment_manifest FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE + ); +END +`; + +export const INIT_SHIPPING = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'shipping') +BEGIN + CREATE TABLE shipping ( + id INT IDENTITY(1,1) PRIMARY KEY, + manifest_id INT NOT NULL, + [number] NVARCHAR(100) NOT NULL, + [type] NVARCHAR(100) NOT NULL, + [state] NVARCHAR(100) NOT NULL, + CONSTRAINT FK_shipping_manifest FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE + ); +END +`; + +export const INIT_PACKAGE = ` +IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'package') +BEGIN + CREATE TABLE package ( + id INT IDENTITY(1,1) PRIMARY KEY, + shipping_id INT NOT NULL, + entityaddress_id INT NOT NULL, + [number] NVARCHAR(100) NOT NULL, + [type] NVARCHAR(100) NOT NULL, + [state] NVARCHAR(100) NOT NULL, + details NVARCHAR(MAX) NULL, + CONSTRAINT FK_package_shipping FOREIGN KEY (shipping_id) REFERENCES shipping(id) ON DELETE CASCADE, + CONSTRAINT FK_package_entityaddress FOREIGN KEY (entityaddress_id) REFERENCES entityaddress(id) ON DELETE NO ACTION + ); +END +`; + /** DDL scripts in dependency order for schema init. */ export const SCHEMA_SCRIPTS = [ INIT_META, @@ -1156,5 +1215,9 @@ export const SCHEMA_SCRIPTS = [ INIT_FILE, INIT_MANIFESTATTACHMENT, INIT_MANIFESTATTACHMENT_TRIGGER, + INIT_ACCOUNT, + INIT_PAYMENT, + INIT_SHIPPING, + INIT_PACKAGE, ]; diff --git a/src/providers/sqlite3/queries/logistics.js b/src/providers/sqlite3/queries/logistics.js new file mode 100644 index 0000000..dc3fe59 --- /dev/null +++ b/src/providers/sqlite3/queries/logistics.js @@ -0,0 +1,21 @@ +import * as source from '../../mssql/queries/logistics.js'; +import { translateQueries } from './translate.js'; + +const queries = translateQueries(source, 'logistics'); +export const { + CHECK_ACCOUNT_COMPANY, + CHECK_ENTITYADDRESS_COMPANY, + CHECK_SHIPPING_COMPANY, + ACCOUNT_CREATE, + ACCOUNT_LIST, + ACCOUNT_DELETE, + PAYMENT_CREATE, + PAYMENT_LIST_BY_MANIFEST, + PAYMENT_DELETE, + SHIPPING_CREATE, + SHIPPING_LIST_BY_MANIFEST, + SHIPPING_DELETE, + PACKAGE_CREATE, + PACKAGE_LIST_BY_SHIPPING, + PACKAGE_DELETE, +} = queries; diff --git a/src/providers/sqlite3/schema.js b/src/providers/sqlite3/schema.js index 56be07e..10fb1d2 100644 --- a/src/providers/sqlite3/schema.js +++ b/src/providers/sqlite3/schema.js @@ -777,6 +777,53 @@ CREATE TABLE IF NOT EXISTS categoryattributevalue ( ); `; +export const INIT_ACCOUNT = ` +CREATE TABLE IF NOT EXISTS account ( + id INTEGER PRIMARY KEY, + company_id INTEGER NOT NULL, + "type" TEXT NOT NULL, + "name" TEXT NOT NULL, + FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE +); +`; + +export const INIT_PAYMENT = ` +CREATE TABLE IF NOT EXISTS payment ( + id INTEGER PRIMARY KEY, + account_id INTEGER NOT NULL, + manifest_id INTEGER NOT NULL, + "type" TEXT NOT NULL, + amount REAL NOT NULL, + FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE, + FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE +); +`; + +export const INIT_SHIPPING = ` +CREATE TABLE IF NOT EXISTS shipping ( + id INTEGER PRIMARY KEY, + manifest_id INTEGER NOT NULL, + "number" TEXT NOT NULL, + "type" TEXT NOT NULL, + "state" TEXT NOT NULL, + FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE +); +`; + +export const INIT_PACKAGE = ` +CREATE TABLE IF NOT EXISTS package ( + id INTEGER PRIMARY KEY, + shipping_id INTEGER NOT NULL, + entityaddress_id INTEGER NOT NULL, + "number" TEXT NOT NULL, + "type" TEXT NOT NULL, + "state" TEXT NOT NULL, + details TEXT, + FOREIGN KEY (shipping_id) REFERENCES shipping(id) ON DELETE CASCADE, + FOREIGN KEY (entityaddress_id) REFERENCES entityaddress(id) ON DELETE NO ACTION +); +`; + /** DDL scripts in dependency order for SQLite schema initialization. */ export const SCHEMA_SCRIPTS = [ INIT_META, @@ -836,4 +883,8 @@ export const SCHEMA_SCRIPTS = [ INIT_FILE, INIT_MANIFESTATTACHMENT, INIT_MANIFESTATTACHMENT_TRIGGER, + INIT_ACCOUNT, + INIT_PAYMENT, + INIT_SHIPPING, + INIT_PACKAGE, ]; diff --git a/src/store/account/create.js b/src/store/account/create.js new file mode 100644 index 0000000..1151e01 --- /dev/null +++ b/src/store/account/create.js @@ -0,0 +1,43 @@ +import { queriesFor, requireText } from '../logistics/helpers.js'; +import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; +import makeRunner from '../runner.js'; + +function shape(row) { + return { + id: row.id, + companyId: row.company_id, + type: row.type, + name: row.name, + }; +} + +export default function create(provider) { + const access = resolveSelectedCompanyAccess(provider); + const q = queriesFor(provider); + + /** + * Creates an account for the user's selected company. + * + * @param {number} googleAuthId - The id of the Google auth user. + * @param {object} input - Account input. + * @param {string} input.type - Account type. + * @param {string} input.name - Account name. + * @param {object} [tx] - Optional transaction to run within. + * @returns {Promise<{id: number, companyId: number, type: string, name: string}>} + * @throws {Error} If type or name is missing. + * + * @example + * const account = await store.account.create(googleAuthId, { type: 'bank', name: 'Main' }); + */ + return async (googleAuthId, input = {}, tx) => { + const type = requireText(input.type, 'Account type'); + const name = requireText(input.name, 'Account name'); + + const runner = makeRunner(provider, tx); + const { companyId } = await access(googleAuthId, runner); + + const result = await runner.query(q.ACCOUNT_CREATE, { companyId, type, name }); + const row = result.rows[0] ?? { id: result.insertId, company_id: companyId, type, name }; + return shape(row); + }; +} diff --git a/src/store/account/delete.js b/src/store/account/delete.js new file mode 100644 index 0000000..6fb82b4 --- /dev/null +++ b/src/store/account/delete.js @@ -0,0 +1,27 @@ +import { queriesFor, requireId } from '../logistics/helpers.js'; +import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; +import makeRunner from '../runner.js'; + +/** + * Deletes an account of the user's selected company. Its payments are removed by cascade. + * + * @param {number} googleAuthId - The id of the Google auth user. + * @param {number} id - The account id. + * @param {object} [tx] - Optional transaction to run within. + * @returns {Promise} + * @throws {Error} If the account id is invalid. + * + * @example + * await store.account.delete(googleAuthId, 3); + */ +export default function del(provider) { + const access = resolveSelectedCompanyAccess(provider); + const q = queriesFor(provider); + + return async (googleAuthId, id, tx) => { + const accountId = requireId(id, 'Account'); + const runner = makeRunner(provider, tx); + const { companyId } = await access(googleAuthId, runner); + await runner.query(q.ACCOUNT_DELETE, { id: accountId, companyId }); + }; +} diff --git a/src/store/account/list.js b/src/store/account/list.js new file mode 100644 index 0000000..9ebc36c --- /dev/null +++ b/src/store/account/list.js @@ -0,0 +1,30 @@ +import { queriesFor } from '../logistics/helpers.js'; +import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; +import makeRunner from '../runner.js'; + +/** + * Lists accounts for the user's selected company. + * + * @param {number} googleAuthId - The id of the Google auth user. + * @param {object} [tx] - Optional transaction to run within. + * @returns {Promise>} + * + * @example + * const accounts = await store.account.list(googleAuthId); + */ +export default function list(provider) { + const access = resolveSelectedCompanyAccess(provider); + const q = queriesFor(provider); + + return async (googleAuthId, tx) => { + const runner = makeRunner(provider, tx); + const { companyId } = await access(googleAuthId, runner); + const result = await runner.query(q.ACCOUNT_LIST, { companyId }); + return result.rows.map((row) => ({ + id: row.id, + companyId: row.company_id, + type: row.type, + name: row.name, + })); + }; +} diff --git a/src/store/logistics/helpers.js b/src/store/logistics/helpers.js new file mode 100644 index 0000000..d20bcda --- /dev/null +++ b/src/store/logistics/helpers.js @@ -0,0 +1,25 @@ +import * as mssqlQueries from '../../providers/mssql/queries/logistics.js'; +import * as sqliteQueries from '../../providers/sqlite3/queries/logistics.js'; + +/** Selects the dialect-specific logistics queries for a provider. */ +export function queriesFor(provider) { + return provider?.dialect === 'sqlite3' ? sqliteQueries : mssqlQueries; +} + +/** Trims a required string; throws `