x
This commit is contained in:
2
API.md
2
API.md
@@ -66,6 +66,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
- **posterminal**: `id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt`
|
- **posterminal**: `id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt`
|
||||||
- **posterminalcategory**: `id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)`
|
- **posterminalcategory**: `id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)`
|
||||||
- **posterminalobituary**: `id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt`
|
- **posterminalobituary**: `id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt`
|
||||||
|
- **posterminalsyncqueue**: `id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i`
|
||||||
- **price**: `id PK, tax_id->tax, article_id->article, minmultiplier:d(18,4)=1, customergroup_id->customergroup, net:f`
|
- **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`
|
- **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)`
|
- **propertyname**: `id PK, company_id->company, name:s(255), sort:i=0, exclusive:b=0, UQ(company_id, name)`
|
||||||
@@ -272,6 +273,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
- `list(googleAuthId: number, tx?: object): Promise<Array<{id: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}>>`
|
- `list(googleAuthId: number, tx?: object): Promise<Array<{id: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, maxknownobituaryid: number|null, rootCategoryId: number|null, syncRootArticles: boolean|number, lastseenAt: string|null, updatedAt: string}>>`
|
||||||
- `pair(id: number, input: {token: string, clientserial?: string, pairedAt?: string}, tx?: object): Promise<{id: number, token: string, clientserial: string|null, pairedAt: string|null}>`
|
- `pair(id: number, input: {token: string, clientserial?: string, pairedAt?: string}, tx?: object): Promise<{id: number, token: string, clientserial: string|null, pairedAt: string|null}>`
|
||||||
- `recordObituary(input: {companyId: number, entityType: string, entityId: number}, tx?: object): Promise<void>`
|
- `recordObituary(input: {companyId: number, entityType: string, entityId: number}, tx?: object): Promise<void>`
|
||||||
|
- `recordSyncQueue(input: {companyId: number, entityType: string, entityId: number}, tx?: object): Promise<void>`
|
||||||
- `setMaxKnownObituaryId(id: number, maxknownobituaryid: number|null, tx?: object): Promise<{id: number, maxknownobituaryid: number|null}>`
|
- `setMaxKnownObituaryId(id: number, maxknownobituaryid: number|null, tx?: object): Promise<{id: number, maxknownobituaryid: number|null}>`
|
||||||
- `setOff(googleAuthId: number, posterminalId: number, categoryId: number, tx?: object): Promise<{id: number, categoryIds: Array<number>}>`
|
- `setOff(googleAuthId: number, posterminalId: number, categoryId: number, tx?: object): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
- `setOffAll(googleAuthId: number, posterminalId: number, tx?: object): Promise<{id: number, categoryIds: Array<number>}>`
|
- `setOffAll(googleAuthId: number, posterminalId: number, tx?: object): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Finds a posterminal by its auth token.
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCategoryCount.js`*
|
*Source: `src/store/posterminal/getCategoryCount.js`*
|
||||||
|
|
||||||
Counts categories assigned to the POS terminal updated after the given unix timestamp cursor.
|
Counts categories assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ Counts categories assigned to the POS terminal updated after the given unix time
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor of last update. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -87,7 +87,7 @@ Counts categories assigned to the POS terminal updated after the given unix time
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCategoryList.js`*
|
*Source: `src/store/posterminal/getCategoryList.js`*
|
||||||
|
|
||||||
Lists categories for a POS terminal modified after the cursor.
|
Lists categories for a POS terminal queued after the sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ Lists categories for a POS terminal modified after the cursor.
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[input.limit=20]` | `number` | Max items to return. |
|
| `[input.limit=20]` | `number` | Max items to return. |
|
||||||
| `[tx]` | `object` | Optional transaction. |
|
| `[tx]` | `object` | Optional transaction. |
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ Lists categories for a POS terminal modified after the cursor.
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCompositeProductCount.js`*
|
*Source: `src/store/posterminal/getCompositeProductCount.js`*
|
||||||
|
|
||||||
Counts composite products (Stücklisten) assigned to the POS terminal updated after the given unix timestamp cursor.
|
Counts composite products (Stücklisten) assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ Counts composite products (Stücklisten) assigned to the POS terminal updated af
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor of last update. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -126,7 +126,7 @@ Counts composite products (Stücklisten) assigned to the POS terminal updated af
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCustomerCount.js`*
|
*Source: `src/store/posterminal/getCustomerCount.js`*
|
||||||
|
|
||||||
Counts customers of the POS terminal company updated after the given unix timestamp cursor.
|
Counts customers of the POS terminal company queued after the given sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ Counts customers of the POS terminal company updated after the given unix timest
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor of last update. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -145,7 +145,7 @@ Counts customers of the POS terminal company updated after the given unix timest
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCustomerGroupCount.js`*
|
*Source: `src/store/posterminal/getCustomerGroupCount.js`*
|
||||||
|
|
||||||
Counts customer groups of the POS terminal company updated after the given unix timestamp cursor.
|
Counts customer groups of the POS terminal company queued after the given sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ Counts customer groups of the POS terminal company updated after the given unix
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor of last update. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -164,7 +164,7 @@ Counts customer groups of the POS terminal company updated after the given unix
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCustomerGroupList.js`*
|
*Source: `src/store/posterminal/getCustomerGroupList.js`*
|
||||||
|
|
||||||
Lists customer groups for a POS terminal modified after the cursor, excluding 'Lieferanten'.
|
Lists customer groups for a POS terminal queued after the sync queue cursor ID, excluding 'Lieferanten'.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ Lists customer groups for a POS terminal modified after the cursor, excluding 'L
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[input.limit=50]` | `number` | Max items to return. |
|
| `[input.limit=50]` | `number` | Max items to return. |
|
||||||
| `[tx]` | `object` | Optional transaction. |
|
| `[tx]` | `object` | Optional transaction. |
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ Lists customer groups for a POS terminal modified after the cursor, excluding 'L
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getCustomerList.js`*
|
*Source: `src/store/posterminal/getCustomerList.js`*
|
||||||
|
|
||||||
Lists customers for a POS terminal modified after the cursor, excluding 'Lieferanten'.
|
Lists customers for a POS terminal queued after the sync queue cursor ID, excluding 'Lieferanten'.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ Lists customers for a POS terminal modified after the cursor, excluding 'Liefera
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[input.limit=20]` | `number` | Max items to return. |
|
| `[input.limit=20]` | `number` | Max items to return. |
|
||||||
| `[tx]` | `object` | Optional transaction. |
|
| `[tx]` | `object` | Optional transaction. |
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ Returns the maximum order manifest id for the POS terminal company.
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getProductCount.js`*
|
*Source: `src/store/posterminal/getProductCount.js`*
|
||||||
|
|
||||||
Counts products assigned to the POS terminal updated after the given unix timestamp cursor.
|
Counts products assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ Counts products assigned to the POS terminal updated after the given unix timest
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor of last update. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[tx]` | `object` | Optional transaction to run within. |
|
| `[tx]` | `object` | Optional transaction to run within. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -280,7 +280,7 @@ Counts products assigned to the POS terminal updated after the given unix timest
|
|||||||
|
|
||||||
*Source: `src/store/posterminal/getProductList.js`*
|
*Source: `src/store/posterminal/getProductList.js`*
|
||||||
|
|
||||||
Lists products for a POS terminal modified after the cursor.
|
Lists products for a POS terminal queued after the sync queue cursor ID.
|
||||||
|
|
||||||
**Parameters**
|
**Parameters**
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ Lists products for a POS terminal modified after the cursor.
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `input` | `object` | |
|
| `input` | `object` | |
|
||||||
| `input.posterminalId` | `number` | The POS terminal id. |
|
| `input.posterminalId` | `number` | The POS terminal id. |
|
||||||
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
|
| `[input.cursor=0]` | `number` | Sequential ID cursor of last synced posterminalsyncqueue entry. |
|
||||||
| `[input.limit=20]` | `number` | Max items to return. |
|
| `[input.limit=20]` | `number` | Max items to return. |
|
||||||
| `[tx]` | `object` | Optional transaction. |
|
| `[tx]` | `object` | Optional transaction. |
|
||||||
|
|
||||||
@@ -361,6 +361,26 @@ Records an obituary for all active paired POS terminals of a company.
|
|||||||
|
|
||||||
`Promise<void>`
|
`Promise<void>`
|
||||||
|
|
||||||
|
## `posterminal.recordSyncQueue`
|
||||||
|
|
||||||
|
*Source: `src/store/posterminal/recordSyncQueue.js`*
|
||||||
|
|
||||||
|
Enqueues a sync notification for all POS terminals of a company.
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `input` | `object` | |
|
||||||
|
| `input.companyId` | `number` | The company id. |
|
||||||
|
| `input.entityType` | `string` | 'category' | 'article' | 'customer' | 'customergroup' |
|
||||||
|
| `input.entityId` | `number` | The entity's id. |
|
||||||
|
| `[tx]` | `object` | Optional transaction/runner. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
`Promise<void>`
|
||||||
|
|
||||||
## `posterminal.setMaxKnownObituaryId`
|
## `posterminal.setMaxKnownObituaryId`
|
||||||
|
|
||||||
*Source: `src/store/posterminal/setMaxKnownObituaryId.js`*
|
*Source: `src/store/posterminal/setMaxKnownObituaryId.js`*
|
||||||
|
|||||||
@@ -382,6 +382,7 @@ const SCHEMA_TABLES = [
|
|||||||
['posterminal', 'id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt'],
|
['posterminal', 'id PK, company_id->company, name:s(255), token?:s(255) UQ, pairingpin?:s(50), maxknownobituaryid?:i, root_category_id?->category, sync_root_articles:b=1, lastseen_at?:dt, updated_at:dt'],
|
||||||
['posterminalcategory', 'id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)'],
|
['posterminalcategory', 'id PK, posterminal_id->posterminal, category_id->category, UQ(posterminal_id, category_id)'],
|
||||||
['posterminalobituary', 'id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt'],
|
['posterminalobituary', 'id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i, created_at:dt'],
|
||||||
|
['posterminalsyncqueue', 'id PK, posterminal_id->posterminal, entity_type:s(50), entity_id:i'],
|
||||||
['price', 'id PK, tax_id->tax, article_id->article, minmultiplier:d(18,4)=1, customergroup_id->customergroup, net:f'],
|
['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'],
|
['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)'],
|
['propertyname', 'id PK, company_id->company, name:s(255), sort:i=0, exclusive:b=0, UQ(company_id, name)'],
|
||||||
|
|||||||
@@ -170,8 +170,8 @@ function addInferredEdges(tables, edges) {
|
|||||||
const match = column.name.match(/^(.+)_id$/i);
|
const match = column.name.match(/^(.+)_id$/i);
|
||||||
if (!match) continue;
|
if (!match) continue;
|
||||||
|
|
||||||
// Obituary tables store references to deleted entities, not active foreign keys.
|
// Obituary and sync queue tables store polymorphic entity_id references, not active foreign keys to entity.
|
||||||
if (tableName.includes('obituary') || tableName.includes('tombstone')) continue;
|
if (tableName.includes('obituary') || tableName.includes('tombstone') || tableName.includes('syncqueue')) continue;
|
||||||
|
|
||||||
const candidate = match[1];
|
const candidate = match[1];
|
||||||
if (!tables.has(candidate) || candidate === tableName) continue;
|
if (!tables.has(candidate) || candidate === tableName) continue;
|
||||||
@@ -390,7 +390,7 @@ const CLUSTERS = [
|
|||||||
tables: ['tax', 'price', 'account', 'payment'],
|
tables: ['tax', 'price', 'account', 'payment'],
|
||||||
},
|
},
|
||||||
{ id: 'units', label: 'Units', tables: ['unit'] },
|
{ id: 'units', label: 'Units', tables: ['unit'] },
|
||||||
{ id: 'pos', label: 'POS', tables: ['posterminal', 'posterminalcategory', 'posterminalobituary', 'printer', 'labeltemplate'] },
|
{ id: 'pos', label: 'POS', tables: ['posterminal', 'posterminalcategory', 'posterminalobituary', 'posterminalsyncqueue', 'printer', 'labeltemplate'] },
|
||||||
{
|
{
|
||||||
id: 'ai',
|
id: 'ai',
|
||||||
label: 'AI & Models',
|
label: 'AI & Models',
|
||||||
|
|||||||
328
schema-graph.dot
328
schema-graph.dot
File diff suppressed because one or more lines are too long
6837
schema-graph.svg
6837
schema-graph.svg
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 408 KiB After Width: | Height: | Size: 441 KiB |
436
scripts/test-syncqueue.js
Normal file
436
scripts/test-syncqueue.js
Normal file
@@ -0,0 +1,436 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { mkdtempSync, rmSync } from 'node:fs';
|
||||||
|
import { tmpdir } from 'node:os';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import LibDashStore from '../src/index.js';
|
||||||
|
import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
console.log('--- Testing posterminalsyncqueue table and sync queue flow ---');
|
||||||
|
|
||||||
|
const tempDir = mkdtempSync(join(tmpdir(), 'test-syncqueue-'));
|
||||||
|
const dbFile = join(tempDir, 'test.db');
|
||||||
|
const storageDir = join(tempDir, 'storage');
|
||||||
|
|
||||||
|
const provider = new BetterSqlite3Provider({
|
||||||
|
filename: dbFile,
|
||||||
|
storageDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
await provider.initialize();
|
||||||
|
const store = await new LibDashStore(provider);
|
||||||
|
|
||||||
|
const clearQueue = () => {
|
||||||
|
provider.db.prepare('DELETE FROM posterminalsyncqueue').run();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getQueue = () =>
|
||||||
|
provider.db
|
||||||
|
.prepare('SELECT posterminal_id, entity_type, entity_id FROM posterminalsyncqueue ORDER BY id ASC')
|
||||||
|
.all();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Verify posterminalsyncqueue table exists and has expected columns
|
||||||
|
console.log('1. Checking posterminalsyncqueue schema...');
|
||||||
|
const tableInfo = provider.db.pragma('table_info("posterminalsyncqueue")');
|
||||||
|
const colNames = tableInfo.map((c) => c.name);
|
||||||
|
console.log('posterminalsyncqueue columns:', colNames);
|
||||||
|
assert.deepEqual(colNames, [
|
||||||
|
'id',
|
||||||
|
'posterminal_id',
|
||||||
|
'entity_type',
|
||||||
|
'entity_id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 2. Setup company & 2 POS terminals + another company with 1 terminal (to test company scoping)
|
||||||
|
console.log('2. Setting up base data with 2 terminals in company 1 and 1 terminal in company 2...');
|
||||||
|
const googleAuthId = await store.google_auth.add('syncqueue-tester@example.com');
|
||||||
|
const company1 = await store.company.create({
|
||||||
|
name: 'SyncQueue Corp 1',
|
||||||
|
iso639: 'de',
|
||||||
|
taxrate: 19,
|
||||||
|
reducedtaxrate: 7,
|
||||||
|
googleAuthId,
|
||||||
|
});
|
||||||
|
const company2 = await store.company.create({
|
||||||
|
name: 'SyncQueue Corp 2',
|
||||||
|
iso639: 'de',
|
||||||
|
taxrate: 19,
|
||||||
|
reducedtaxrate: 7,
|
||||||
|
googleAuthId,
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.google_auth.setSelectedCompany(googleAuthId, company2.id);
|
||||||
|
const otherTerminal = await store.posterminal.upsert(googleAuthId, {
|
||||||
|
name: 'Other Corp Terminal',
|
||||||
|
pairingpin: '9999',
|
||||||
|
});
|
||||||
|
|
||||||
|
await store.google_auth.setSelectedCompany(googleAuthId, company1.id);
|
||||||
|
const term1 = await store.posterminal.upsert(googleAuthId, {
|
||||||
|
name: 'POS Terminal 1',
|
||||||
|
pairingpin: '1111',
|
||||||
|
});
|
||||||
|
const term2 = await store.posterminal.upsert(googleAuthId, {
|
||||||
|
name: 'POS Terminal 2',
|
||||||
|
pairingpin: '2222',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper to assert that both term1 and term2 received the expected entity_type + entity_id, and otherTerminal did not
|
||||||
|
const assertQueuedForBothTerminals = (entityType, entityId, label) => {
|
||||||
|
const rows = getQueue();
|
||||||
|
const matching = rows.filter((r) => r.entity_type === entityType && r.entity_id === entityId);
|
||||||
|
const termIds = matching.map((r) => r.posterminal_id).sort((a, b) => a - b);
|
||||||
|
assert.deepEqual(
|
||||||
|
termIds,
|
||||||
|
[term1.id, term2.id],
|
||||||
|
`Expected [${term1.id}, ${term2.id}] for ${label} (${entityType}:${entityId}), got ${JSON.stringify(rows)}`,
|
||||||
|
);
|
||||||
|
const otherRows = rows.filter((r) => r.posterminal_id === otherTerminal.id);
|
||||||
|
assert.equal(otherRows.length, 0, `Other company terminal should not receive rows (${label})`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. Test Category operations
|
||||||
|
console.log('3. Testing category operations...');
|
||||||
|
clearQueue();
|
||||||
|
const catA = await store.category.createUnderParent({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: company1.rootCategoryId,
|
||||||
|
name: 'Category A',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'category.createUnderParent');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.category.rename({
|
||||||
|
googleAuthId,
|
||||||
|
id: catA.id,
|
||||||
|
name: 'Category A Renamed',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'category.rename');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
const catLeafId = await store.category.ensureByPath({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: company1.rootCategoryId,
|
||||||
|
path: 'Category B | Subcategory B1',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('category', catLeafId, 'category.ensureByPath');
|
||||||
|
|
||||||
|
const catBRow = provider.db
|
||||||
|
.prepare('SELECT c.id FROM category c WHERE c.parent_id = ? AND c.id != ?')
|
||||||
|
.get(company1.rootCategoryId, catA.id);
|
||||||
|
clearQueue();
|
||||||
|
await store.category.order({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: company1.rootCategoryId,
|
||||||
|
categoryIds: [catBRow.id, catA.id],
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'category.order');
|
||||||
|
assertQueuedForBothTerminals('category', catBRow.id, 'category.order (sibling)');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.category.move({
|
||||||
|
googleAuthId,
|
||||||
|
id: catLeafId,
|
||||||
|
parentId: catA.id,
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('category', catLeafId, 'category.move');
|
||||||
|
|
||||||
|
const prop = await store.propertyname.create(googleAuthId, { name: 'Color', exclusive: false });
|
||||||
|
clearQueue();
|
||||||
|
await store.categoryproperty.setByCategoryId(googleAuthId, catA.id, [
|
||||||
|
{ propertyId: prop.id, value: 'Red' },
|
||||||
|
]);
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'categoryproperty.setByCategoryId');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.categoryproperty.delete(googleAuthId, catA.id, prop.id);
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'categoryproperty.delete');
|
||||||
|
|
||||||
|
const attr = await store.attributename.create(googleAuthId, { name: 'Size', exclusive: true });
|
||||||
|
const attrVal = await store.attributevalue.create(googleAuthId, attr.id, { value: 'XL' });
|
||||||
|
clearQueue();
|
||||||
|
await store.categoryattributevalue.setByCategoryId(googleAuthId, catA.id, [attrVal.id]);
|
||||||
|
assertQueuedForBothTerminals('category', catA.id, 'categoryattributevalue.setByCategoryId');
|
||||||
|
|
||||||
|
// 4. Test Article operations
|
||||||
|
console.log('4. Testing article operations...');
|
||||||
|
clearQueue();
|
||||||
|
const art1 = await store.article.createUnderParent({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: catA.id,
|
||||||
|
name: 'Cola 0.33L',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.createUnderParent');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.article.updateBySku(googleAuthId, art1.sku, { name: 'Cola Classic 0.33L' });
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.updateBySku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setPricesBySku(googleAuthId, art1.sku, [{ net: 1.5, taxRate: 19 }]);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setPricesBySku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setEansBySku(googleAuthId, art1.sku, ['4001234567890']);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setEansBySku');
|
||||||
|
|
||||||
|
const brand = await store.brand.create(googleAuthId, { name: 'ColaBrand' });
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setBrandIdBySku(googleAuthId, art1.sku, brand.id);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setBrandIdBySku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.brand.update(googleAuthId, brand.id, { name: 'ColaBrand Updated' });
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'brand.update');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setWeightBySku(googleAuthId, art1.sku, 0.35);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setWeightBySku');
|
||||||
|
|
||||||
|
const wh = await store.warehouse.create(googleAuthId, { name: 'Main Warehouse' });
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setTrackStockBySku(googleAuthId, art1.sku, true);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setTrackStockBySku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.stock.adjust(googleAuthId, {
|
||||||
|
sku: art1.sku,
|
||||||
|
warehouseId: wh.id,
|
||||||
|
amount: 10,
|
||||||
|
text: 'Initial stock',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'stock.adjust');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setCategoryIdsBySku(googleAuthId, art1.sku, [catA.id, catLeafId]);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'article.setCategoryIdsBySku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.articleproperty.setByArticleSku(googleAuthId, art1.sku, [
|
||||||
|
{ propertyId: prop.id, value: 'Dark' },
|
||||||
|
]);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'articleproperty.setByArticleSku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.articleproperty.delete(googleAuthId, art1.sku, prop.id);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'articleproperty.delete');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.articleattributevalue.setByArticleSku(googleAuthId, art1.sku, [attrVal.id]);
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'articleattributevalue.setByArticleSku');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.attributevalue.update(googleAuthId, attrVal.id, { value: 'XXL' });
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'attributevalue.update');
|
||||||
|
|
||||||
|
// Optionslist & Stückliste
|
||||||
|
const pfand = await store.article.createUnderParent({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: catA.id,
|
||||||
|
name: 'Pfand 0.25',
|
||||||
|
});
|
||||||
|
clearQueue();
|
||||||
|
await store.optionslist.setOptionsByArticleSku(googleAuthId, art1.sku, [
|
||||||
|
{ sku: pfand.sku, count: 1, mandated: true },
|
||||||
|
]);
|
||||||
|
assertQueuedForBothTerminals('article', art1.sku ? art1.id : 0, 'optionslist.setOptionsByArticleSku');
|
||||||
|
|
||||||
|
// Updating option article price should also enqueue parent article!
|
||||||
|
clearQueue();
|
||||||
|
await store.article.setPricesBySku(googleAuthId, pfand.sku, [{ net: 0.25, taxRate: 19 }]);
|
||||||
|
assertQueuedForBothTerminals('article', pfand.id, 'setPricesBySku (option itself)');
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'setPricesBySku (option parent)');
|
||||||
|
|
||||||
|
const bundle = await store.article.createUnderParent({
|
||||||
|
googleAuthId,
|
||||||
|
parentId: catA.id,
|
||||||
|
name: 'Cola Crate',
|
||||||
|
});
|
||||||
|
clearQueue();
|
||||||
|
await store.articlelist.setItemsByArticleSku(googleAuthId, bundle.sku, [
|
||||||
|
{ sku: art1.sku, count: 6 },
|
||||||
|
]);
|
||||||
|
assertQueuedForBothTerminals('article', bundle.id, 'articlelist.setItemsByArticleSku');
|
||||||
|
|
||||||
|
// Adjusting component stock should also enqueue Stückliste parent!
|
||||||
|
clearQueue();
|
||||||
|
await store.stock.adjust(googleAuthId, {
|
||||||
|
sku: art1.sku,
|
||||||
|
warehouseId: wh.id,
|
||||||
|
amount: 2,
|
||||||
|
text: 'Restock component',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('article', art1.id, 'stock.adjust (component)');
|
||||||
|
assertQueuedForBothTerminals('article', bundle.id, 'stock.adjust (Stückliste parent)');
|
||||||
|
|
||||||
|
// 5. Test Customer Group operations
|
||||||
|
console.log('5. Testing customergroup operations...');
|
||||||
|
clearQueue();
|
||||||
|
const cg1 = await store.customergroup.create(googleAuthId, { name: 'B2B' });
|
||||||
|
assertQueuedForBothTerminals('customergroup', cg1.id, 'customergroup.create');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.customergroup.update(googleAuthId, cg1.id, { name: 'B2B Gold' });
|
||||||
|
assertQueuedForBothTerminals('customergroup', cg1.id, 'customergroup.update');
|
||||||
|
|
||||||
|
const allGroups = await store.customergroup.list(googleAuthId);
|
||||||
|
clearQueue();
|
||||||
|
await store.customergroup.order(googleAuthId, {
|
||||||
|
customergroupIds: allGroups.map((g) => g.id).reverse(),
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customergroup', cg1.id, 'customergroup.order');
|
||||||
|
|
||||||
|
// 6. Test Customer (Entity + Address + Contact) operations
|
||||||
|
console.log('6. Testing customer (entity, entityaddress, entitycontact) operations...');
|
||||||
|
clearQueue();
|
||||||
|
const cust = await store.entity.create(googleAuthId, {
|
||||||
|
customergroupId: cg1.id,
|
||||||
|
name: 'Doe',
|
||||||
|
firstName: 'John',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entity.create');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.entity.update(googleAuthId, cust.id, { firstName: 'Johnny' });
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entity.update');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
const addr = await store.entityaddress.create(googleAuthId, cust.id, {
|
||||||
|
addressType: 'billing',
|
||||||
|
street: 'Main St 1',
|
||||||
|
city: 'Berlin',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entityaddress.create');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.entityaddress.update(googleAuthId, cust.id, addr.id, {
|
||||||
|
city: 'Munich',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entityaddress.update');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.entityaddress.delete(googleAuthId, cust.id, addr.id);
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entityaddress.delete');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
const contact = await store.entitycontact.create(googleAuthId, cust.id, {
|
||||||
|
contactType: 'email',
|
||||||
|
contact: 'john@example.com',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entitycontact.create');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.entitycontact.update(googleAuthId, cust.id, contact.id, {
|
||||||
|
contact: 'johnny@example.com',
|
||||||
|
});
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entitycontact.update');
|
||||||
|
|
||||||
|
clearQueue();
|
||||||
|
await store.entitycontact.delete(googleAuthId, cust.id, contact.id);
|
||||||
|
assertQueuedForBothTerminals('customer', cust.id, 'entitycontact.delete');
|
||||||
|
|
||||||
|
// 7. Test CHECK constraint on entity_type
|
||||||
|
console.log('7. Testing entity_type CHECK constraint...');
|
||||||
|
assert.throws(() => {
|
||||||
|
provider.db
|
||||||
|
.prepare('INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id) VALUES (?, ?, ?)')
|
||||||
|
.run(term1.id, 'invalid_type', 1);
|
||||||
|
}, /CHECK constraint failed/);
|
||||||
|
|
||||||
|
// 8. Test POS Sync Cursor (posterminalsyncqueue.id) across counts and lists
|
||||||
|
console.log('8. Testing POS Sync Cursor (posterminalsyncqueue.id) for counts & lists...');
|
||||||
|
// Create a fresh terminal (term3) and enable all categories on it to verify full initial sync + delta cursor
|
||||||
|
const term3 = await store.posterminal.upsert(googleAuthId, {
|
||||||
|
name: 'POS Terminal 3',
|
||||||
|
pairingpin: '3333',
|
||||||
|
});
|
||||||
|
await store.posterminal.setOnAll(googleAuthId, term3.id);
|
||||||
|
|
||||||
|
// Initial sync with cursor = 0
|
||||||
|
const initProductCount = await store.posterminal.getProductCount({ posterminalId: term3.id, cursor: 0 });
|
||||||
|
const initCategoryCount = await store.posterminal.getCategoryCount({ posterminalId: term3.id, cursor: 0 });
|
||||||
|
const initCustomerCount = await store.posterminal.getCustomerCount({ posterminalId: term3.id, cursor: 0 });
|
||||||
|
const initCustomerGroupCount = await store.posterminal.getCustomerGroupCount({ posterminalId: term3.id, cursor: 0 });
|
||||||
|
const initCompositeCount = await store.posterminal.getCompositeProductCount({ posterminalId: term3.id, cursor: 0 });
|
||||||
|
|
||||||
|
assert.ok(initProductCount > 0, `Expected initProductCount > 0, got ${initProductCount}`);
|
||||||
|
assert.ok(initCategoryCount > 0, `Expected initCategoryCount > 0, got ${initCategoryCount}`);
|
||||||
|
assert.ok(initCustomerCount > 0, `Expected initCustomerCount > 0, got ${initCustomerCount}`);
|
||||||
|
assert.ok(initCustomerGroupCount > 0, `Expected initCustomerGroupCount > 0, got ${initCustomerGroupCount}`);
|
||||||
|
assert.ok(initCompositeCount > 0, `Expected initCompositeCount > 0, got ${initCompositeCount}`);
|
||||||
|
|
||||||
|
const products = await store.posterminal.getProductList({ posterminalId: term3.id, cursor: 0, limit: 100 });
|
||||||
|
const categories = await store.posterminal.getCategoryList({ posterminalId: term3.id, cursor: 0, limit: 100 });
|
||||||
|
const customers = await store.posterminal.getCustomerList({ posterminalId: term3.id, cursor: 0, limit: 100 });
|
||||||
|
const customerGroups = await store.posterminal.getCustomerGroupList({ posterminalId: term3.id, cursor: 0, limit: 100 });
|
||||||
|
|
||||||
|
assert.equal(products.length, initProductCount);
|
||||||
|
assert.equal(categories.length, initCategoryCount);
|
||||||
|
assert.equal(customers.length, initCustomerCount);
|
||||||
|
assert.equal(customerGroups.length, initCustomerGroupCount);
|
||||||
|
|
||||||
|
// Advance cursors to max lastChanged
|
||||||
|
const maxProductCursor = Math.max(...products.map((p) => Number(p.lastChanged)));
|
||||||
|
const maxCategoryCursor = Math.max(...categories.map((c) => Number(c.lastChanged)));
|
||||||
|
const maxCustomerCursor = Math.max(...customers.map((c) => Number(c.lastChanged)));
|
||||||
|
const maxCustomerGroupCursor = Math.max(...customerGroups.map((cg) => Number(cg.lastChanged)));
|
||||||
|
|
||||||
|
// Verify all counts and lists are 0 at the current cursors
|
||||||
|
assert.equal(await store.posterminal.getProductCount({ posterminalId: term3.id, cursor: maxProductCursor }), 0);
|
||||||
|
assert.equal(await store.posterminal.getCategoryCount({ posterminalId: term3.id, cursor: maxCategoryCursor }), 0);
|
||||||
|
assert.equal(await store.posterminal.getCustomerCount({ posterminalId: term3.id, cursor: maxCustomerCursor }), 0);
|
||||||
|
assert.equal(await store.posterminal.getCustomerGroupCount({ posterminalId: term3.id, cursor: maxCustomerGroupCursor }), 0);
|
||||||
|
assert.equal(await store.posterminal.getCompositeProductCount({ posterminalId: term3.id, cursor: maxProductCursor }), 0);
|
||||||
|
|
||||||
|
assert.equal((await store.posterminal.getProductList({ posterminalId: term3.id, cursor: maxProductCursor })).length, 0);
|
||||||
|
assert.equal((await store.posterminal.getCategoryList({ posterminalId: term3.id, cursor: maxCategoryCursor })).length, 0);
|
||||||
|
assert.equal((await store.posterminal.getCustomerList({ posterminalId: term3.id, cursor: maxCustomerCursor })).length, 0);
|
||||||
|
assert.equal((await store.posterminal.getCustomerGroupList({ posterminalId: term3.id, cursor: maxCustomerGroupCursor })).length, 0);
|
||||||
|
|
||||||
|
// Now touch one article twice, one category, one customer, one customergroup
|
||||||
|
await store.article.updateBySku(googleAuthId, art1.sku, { name: 'Cola Classic v2' });
|
||||||
|
await store.article.updateBySku(googleAuthId, art1.sku, { name: 'Cola Classic v3' });
|
||||||
|
await store.category.rename({ googleAuthId, id: catA.id, name: 'Category A v2' });
|
||||||
|
await store.entity.update(googleAuthId, cust.id, { firstName: 'John v2' });
|
||||||
|
await store.customergroup.update(googleAuthId, cg1.id, { name: 'B2B Platinum' });
|
||||||
|
|
||||||
|
// Even though art1 was updated twice, count should be 1 (deduplicated by entity_id with MAX(id) > cursor)
|
||||||
|
assert.equal(await store.posterminal.getProductCount({ posterminalId: term3.id, cursor: maxProductCursor }), 1);
|
||||||
|
assert.equal(await store.posterminal.getCategoryCount({ posterminalId: term3.id, cursor: maxCategoryCursor }), 1);
|
||||||
|
assert.equal(await store.posterminal.getCustomerCount({ posterminalId: term3.id, cursor: maxCustomerCursor }), 1);
|
||||||
|
assert.equal(await store.posterminal.getCustomerGroupCount({ posterminalId: term3.id, cursor: maxCustomerGroupCursor }), 1);
|
||||||
|
|
||||||
|
const deltaProducts = await store.posterminal.getProductList({ posterminalId: term3.id, cursor: maxProductCursor });
|
||||||
|
const deltaCategories = await store.posterminal.getCategoryList({ posterminalId: term3.id, cursor: maxCategoryCursor });
|
||||||
|
const deltaCustomers = await store.posterminal.getCustomerList({ posterminalId: term3.id, cursor: maxCustomerCursor });
|
||||||
|
const deltaCustomerGroups = await store.posterminal.getCustomerGroupList({ posterminalId: term3.id, cursor: maxCustomerGroupCursor });
|
||||||
|
|
||||||
|
assert.equal(deltaProducts.length, 1);
|
||||||
|
assert.equal(deltaProducts[0]._id, String(art1.id));
|
||||||
|
assert.ok(Number(deltaProducts[0].lastChanged) > maxProductCursor);
|
||||||
|
|
||||||
|
assert.equal(deltaCategories.length, 1);
|
||||||
|
assert.equal(deltaCategories[0]._id, String(catA.id));
|
||||||
|
assert.ok(Number(deltaCategories[0].lastChanged) > maxCategoryCursor);
|
||||||
|
|
||||||
|
assert.equal(deltaCustomers.length, 1);
|
||||||
|
assert.equal(deltaCustomers[0].id, String(cust.id));
|
||||||
|
assert.ok(Number(deltaCustomers[0].lastChanged) > maxCustomerCursor);
|
||||||
|
|
||||||
|
assert.equal(deltaCustomerGroups.length, 1);
|
||||||
|
assert.equal(deltaCustomerGroups[0].customerGroupId, String(cg1.id));
|
||||||
|
assert.ok(Number(deltaCustomerGroups[0].lastChanged) > maxCustomerGroupCursor);
|
||||||
|
|
||||||
|
console.log('✅ ALL POSTERMINALSYNCQUEUE TESTS PASSED');
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
rmSync(tempDir, { recursive: true, force: true });
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((err) => {
|
||||||
|
console.error('Test failed:', err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -143,6 +143,7 @@ import posterminalGetCompositeProductCount from './store/posterminal/getComposit
|
|||||||
import posterminalGetDeletedEntityCount from './store/posterminal/getDeletedEntityCount.js';
|
import posterminalGetDeletedEntityCount from './store/posterminal/getDeletedEntityCount.js';
|
||||||
import posterminalGetDeletedEntityList from './store/posterminal/getDeletedEntityList.js';
|
import posterminalGetDeletedEntityList from './store/posterminal/getDeletedEntityList.js';
|
||||||
import posterminalRecordObituary from './store/posterminal/recordObituary.js';
|
import posterminalRecordObituary from './store/posterminal/recordObituary.js';
|
||||||
|
import posterminalRecordSyncQueue from './store/posterminal/recordSyncQueue.js';
|
||||||
import posterminalGetMaxOrderIdCount from './store/posterminal/getMaxOrderIdCount.js';
|
import posterminalGetMaxOrderIdCount from './store/posterminal/getMaxOrderIdCount.js';
|
||||||
import posterminalGetCategoryList from './store/posterminal/getCategoryList.js';
|
import posterminalGetCategoryList from './store/posterminal/getCategoryList.js';
|
||||||
import posterminalGetProductList from './store/posterminal/getProductList.js';
|
import posterminalGetProductList from './store/posterminal/getProductList.js';
|
||||||
@@ -528,6 +529,7 @@ export default class LibDashStore {
|
|||||||
getDeletedEntityCount: posterminalGetDeletedEntityCount(provider),
|
getDeletedEntityCount: posterminalGetDeletedEntityCount(provider),
|
||||||
getDeletedEntityList: posterminalGetDeletedEntityList(provider),
|
getDeletedEntityList: posterminalGetDeletedEntityList(provider),
|
||||||
recordObituary: posterminalRecordObituary(provider),
|
recordObituary: posterminalRecordObituary(provider),
|
||||||
|
recordSyncQueue: posterminalRecordSyncQueue(provider),
|
||||||
getMaxOrderIdCount: posterminalGetMaxOrderIdCount(provider),
|
getMaxOrderIdCount: posterminalGetMaxOrderIdCount(provider),
|
||||||
getCategoryList: posterminalGetCategoryList(provider),
|
getCategoryList: posterminalGetCategoryList(provider),
|
||||||
getProductList: posterminalGetProductList(provider),
|
getProductList: posterminalGetProductList(provider),
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export const TABLES = [
|
|||||||
'modelconversation',
|
'modelconversation',
|
||||||
'companyuser',
|
'companyuser',
|
||||||
'companysetting',
|
'companysetting',
|
||||||
|
'posterminalsyncqueue',
|
||||||
|
'posterminalobituary',
|
||||||
'posterminalcategory',
|
'posterminalcategory',
|
||||||
'posterminal',
|
'posterminal',
|
||||||
'printer',
|
'printer',
|
||||||
|
|||||||
@@ -249,6 +249,38 @@ WHERE articlelist_id IN (
|
|||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_SYNC_BY_ARTICLE = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.id = @articleId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_OPTION_PARENT_ARTICLES_SYNC = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.optionslist_id IN (
|
||||||
|
SELECT ola.optionslist_id
|
||||||
|
FROM optionslistarticle ola
|
||||||
|
WHERE ola.article_id = @articleId
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_STUECKLISTE_ARTICLES_SYNC = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.articlelist_id IN (
|
||||||
|
SELECT ala.articlelist_id
|
||||||
|
FROM articlelistarticle ala
|
||||||
|
WHERE ala.article_id = @articleId
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const CREATE = `
|
export const CREATE = `
|
||||||
INSERT INTO article (company_id, sku, unit_id, unitamount, weight, track_stock)
|
INSERT INTO article (company_id, sku, unit_id, unitamount, weight, track_stock)
|
||||||
|
|||||||
@@ -240,3 +240,40 @@ WHERE id IN (
|
|||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_SUBTREE_CATEGORIES_SYNC = `
|
||||||
|
;WITH cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'category', cats.id
|
||||||
|
FROM cats
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_SUBTREE_ARTICLES_SYNC = `
|
||||||
|
;WITH cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
),
|
||||||
|
arts AS (
|
||||||
|
SELECT ca.article_id AS id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
UNION
|
||||||
|
SELECT child.id FROM article child
|
||||||
|
WHERE child.parentarticle_id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
SELECT parent.parentarticle_id AS id FROM article parent
|
||||||
|
WHERE parent.id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
) AND parent.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', arts.id
|
||||||
|
FROM arts
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,12 @@ WHERE id = @id
|
|||||||
AND customergroup_id = @customergroupId
|
AND customergroup_id = @customergroupId
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const TOUCH_UPDATED_AT = `
|
||||||
|
UPDATE entity
|
||||||
|
SET updated_at = SYSUTCDATETIME()
|
||||||
|
WHERE id = @id
|
||||||
|
`;
|
||||||
|
|
||||||
export const DELETE_BY_COMPANY_AND_ID = `
|
export const DELETE_BY_COMPANY_AND_ID = `
|
||||||
DELETE e
|
DELETE e
|
||||||
FROM entity e
|
FROM entity e
|
||||||
|
|||||||
@@ -172,66 +172,100 @@ WHERE token = @token
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const COUNT_PRODUCTS = `
|
export const COUNT_PRODUCTS = `
|
||||||
SELECT COUNT(DISTINCT a.id) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM article a
|
FROM (
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
SELECT MAX(q.id) AS syncId, a.id
|
||||||
WHERE EXISTS (
|
FROM posterminalsyncqueue q
|
||||||
SELECT 1
|
INNER JOIN article a ON a.id = q.entity_id
|
||||||
FROM categoryarticle ca
|
INNER JOIN posterminal pt ON pt.id = q.posterminal_id AND pt.company_id = a.company_id
|
||||||
INNER JOIN posterminalcategory pc ON pc.category_id = ca.category_id
|
WHERE q.posterminal_id = @posterminalId
|
||||||
WHERE ca.article_id = a.id
|
AND q.entity_type = 'article'
|
||||||
AND pc.posterminal_id = @posterminalId
|
AND EXISTS (
|
||||||
)
|
SELECT 1
|
||||||
AND (DATEDIFF_BIG(second, '1970-01-01', a.updated_at) * 1000000 + (a.id % 1000000)) > @cursor
|
FROM categoryarticle ca
|
||||||
|
INNER JOIN posterminalcategory pc ON pc.category_id = ca.category_id
|
||||||
|
WHERE ca.article_id = a.id
|
||||||
|
AND pc.posterminal_id = @posterminalId
|
||||||
|
)
|
||||||
|
GROUP BY a.id
|
||||||
|
HAVING MAX(q.id) > @cursor
|
||||||
|
) t
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const COUNT_CATEGORIES = `
|
export const COUNT_CATEGORIES = `
|
||||||
SELECT COUNT(*) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM category c
|
FROM (
|
||||||
INNER JOIN posterminalcategory pc ON pc.category_id = c.id
|
SELECT MAX(q.id) AS syncId, c.id
|
||||||
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
FROM posterminalsyncqueue q
|
||||||
INNER JOIN company co ON co.id = pt.company_id
|
INNER JOIN category c ON c.id = q.entity_id
|
||||||
WHERE pc.posterminal_id = @posterminalId
|
INNER JOIN posterminalcategory pc ON pc.category_id = c.id AND pc.posterminal_id = q.posterminal_id
|
||||||
AND (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', c.updated_at) > @cursor
|
INNER JOIN company co ON co.id = pt.company_id
|
||||||
|
WHERE q.posterminal_id = @posterminalId
|
||||||
|
AND q.entity_type = 'category'
|
||||||
|
AND (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
||||||
|
GROUP BY c.id
|
||||||
|
HAVING MAX(q.id) > @cursor
|
||||||
|
) t
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const COUNT_CUSTOMERS = `
|
export const COUNT_CUSTOMERS = `
|
||||||
SELECT COUNT(*) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM entity e
|
FROM (
|
||||||
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
SELECT MAX(q.id) AS syncId, e.id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
FROM posterminalsyncqueue q
|
||||||
WHERE cg.name <> 'Lieferanten'
|
INNER JOIN entity e ON e.id = q.entity_id
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', e.updated_at) > @cursor
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
INNER JOIN posterminal pt ON pt.id = q.posterminal_id AND pt.company_id = cg.company_id
|
||||||
|
WHERE q.posterminal_id = @posterminalId
|
||||||
|
AND q.entity_type = 'customer'
|
||||||
|
AND cg.name <> 'Lieferanten'
|
||||||
|
GROUP BY e.id
|
||||||
|
HAVING MAX(q.id) > @cursor
|
||||||
|
) t
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const COUNT_CUSTOMER_GROUPS = `
|
export const COUNT_CUSTOMER_GROUPS = `
|
||||||
SELECT COUNT(*) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM customergroup cg
|
FROM (
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
SELECT MAX(q.id) AS syncId, cg.id
|
||||||
WHERE cg.name <> 'Lieferanten'
|
FROM posterminalsyncqueue q
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) > @cursor
|
INNER JOIN customergroup cg ON cg.id = q.entity_id
|
||||||
|
INNER JOIN posterminal pt ON pt.id = q.posterminal_id AND pt.company_id = cg.company_id
|
||||||
|
WHERE q.posterminal_id = @posterminalId
|
||||||
|
AND q.entity_type = 'customergroup'
|
||||||
|
AND cg.name <> 'Lieferanten'
|
||||||
|
GROUP BY cg.id
|
||||||
|
HAVING MAX(q.id) > @cursor
|
||||||
|
) t
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const COUNT_COMPOSITE_PRODUCTS = `
|
export const COUNT_COMPOSITE_PRODUCTS = `
|
||||||
SELECT COUNT(DISTINCT a.id) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM article a
|
FROM (
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
SELECT MAX(q.id) AS syncId, a.id
|
||||||
WHERE a.articlelist_id IS NOT NULL
|
FROM posterminalsyncqueue q
|
||||||
AND EXISTS (
|
INNER JOIN article a ON a.id = q.entity_id
|
||||||
SELECT 1
|
INNER JOIN posterminal pt ON pt.id = q.posterminal_id AND pt.company_id = a.company_id
|
||||||
FROM articlelistarticle ala
|
WHERE q.posterminal_id = @posterminalId
|
||||||
WHERE ala.articlelist_id = a.articlelist_id
|
AND q.entity_type = 'article'
|
||||||
)
|
AND a.articlelist_id IS NOT NULL
|
||||||
AND EXISTS (
|
AND EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM categoryarticle ca
|
FROM articlelistarticle ala
|
||||||
INNER JOIN posterminalcategory pc ON pc.category_id = ca.category_id
|
WHERE ala.articlelist_id = a.articlelist_id
|
||||||
WHERE ca.article_id = a.id
|
)
|
||||||
AND pc.posterminal_id = @posterminalId
|
AND EXISTS (
|
||||||
)
|
SELECT 1
|
||||||
AND (DATEDIFF_BIG(second, '1970-01-01', a.updated_at) * 1000000 + (a.id % 1000000)) > @cursor
|
FROM categoryarticle ca
|
||||||
|
INNER JOIN posterminalcategory pc ON pc.category_id = ca.category_id
|
||||||
|
WHERE ca.article_id = a.id
|
||||||
|
AND pc.posterminal_id = @posterminalId
|
||||||
|
)
|
||||||
|
GROUP BY a.id
|
||||||
|
HAVING MAX(q.id) > @cursor
|
||||||
|
) t
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const MAX_ORDER_ID = `
|
export const MAX_ORDER_ID = `
|
||||||
@@ -255,16 +289,21 @@ SELECT TOP (@limit)
|
|||||||
WHERE cp.category_id = c.id
|
WHERE cp.category_id = c.id
|
||||||
ORDER BY cp.sort ASC, cp.id ASC
|
ORDER BY cp.sort ASC, cp.id ASC
|
||||||
) AS imgHash,
|
) AS imgHash,
|
||||||
DATEDIFF_BIG(second, '1970-01-01', c.updated_at) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM category c
|
FROM (
|
||||||
INNER JOIN posterminalcategory pc ON pc.category_id = c.id
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'category'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN category c ON c.id = sq.entity_id
|
||||||
|
INNER JOIN posterminalcategory pc ON pc.category_id = c.id AND pc.posterminal_id = @posterminalId
|
||||||
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
||||||
INNER JOIN company co ON co.id = pt.company_id
|
INNER JOIN company co ON co.id = pt.company_id
|
||||||
LEFT JOIN categorytext ct ON ct.category_id = c.id AND ct.language_id = co.default_language_id
|
LEFT JOIN categorytext ct ON ct.category_id = c.id AND ct.language_id = co.default_language_id
|
||||||
WHERE pc.posterminal_id = @posterminalId
|
WHERE (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
||||||
AND (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
ORDER BY sq.syncId ASC
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', c.updated_at) > @cursor
|
|
||||||
ORDER BY DATEDIFF_BIG(second, '1970-01-01', c.updated_at) ASC, c.id ASC
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LIST_POS_PRODUCTS = `
|
export const LIST_POS_PRODUCTS = `
|
||||||
@@ -275,7 +314,7 @@ SELECT TOP (@limit)
|
|||||||
COALESCE(pr.net, 0) AS netPrice,
|
COALESCE(pr.net, 0) AS netPrice,
|
||||||
COALESCE(ptax.rate, ctax.rate, 0) AS taxRate,
|
COALESCE(ptax.rate, ctax.rate, 0) AS taxRate,
|
||||||
a.created_at AS createdAt,
|
a.created_at AS createdAt,
|
||||||
(DATEDIFF_BIG(second, '1970-01-01', a.updated_at) * 1000000 + (a.id % 1000000)) AS lastChanged,
|
sq.syncId AS lastChanged,
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
SELECT TOP 1 p.hash
|
SELECT TOP 1 p.hash
|
||||||
@@ -374,7 +413,14 @@ SELECT TOP (@limit)
|
|||||||
co.id AS companyId,
|
co.id AS companyId,
|
||||||
co.root_category_id AS rootCategoryId,
|
co.root_category_id AS rootCategoryId,
|
||||||
co.poscustomergroup_id AS posCustomerGroupId
|
co.poscustomergroup_id AS posCustomerGroupId
|
||||||
FROM article a
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'article'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN article a ON a.id = sq.entity_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
||||||
INNER JOIN company co ON co.id = a.company_id
|
INNER JOIN company co ON co.id = a.company_id
|
||||||
LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = co.default_language_id
|
LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = co.default_language_id
|
||||||
@@ -388,8 +434,7 @@ WHERE EXISTS (
|
|||||||
WHERE ca.article_id = a.id
|
WHERE ca.article_id = a.id
|
||||||
AND pc.posterminal_id = @posterminalId
|
AND pc.posterminal_id = @posterminalId
|
||||||
)
|
)
|
||||||
AND (DATEDIFF_BIG(second, '1970-01-01', a.updated_at) * 1000000 + (a.id % 1000000)) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY (DATEDIFF_BIG(second, '1970-01-01', a.updated_at) * 1000000 + (a.id % 1000000)) ASC
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LIST_POS_PRODUCT_CATEGORIES = `
|
export const LIST_POS_PRODUCT_CATEGORIES = `
|
||||||
@@ -411,13 +456,19 @@ SELECT TOP (@limit)
|
|||||||
cg.name,
|
cg.name,
|
||||||
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
|
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
|
||||||
'0.000000' AS discountPercent,
|
'0.000000' AS discountPercent,
|
||||||
DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM customergroup cg
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'customergroup'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN customergroup cg ON cg.id = sq.entity_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
||||||
INNER JOIN company co ON co.id = pt.company_id
|
INNER JOIN company co ON co.id = pt.company_id
|
||||||
WHERE cg.name <> 'Lieferanten'
|
WHERE cg.name <> 'Lieferanten'
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) ASC, cg.id ASC
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LIST_POS_CUSTOMERS = `
|
export const LIST_POS_CUSTOMERS = `
|
||||||
@@ -469,13 +520,19 @@ SELECT TOP (@limit)
|
|||||||
WHERE ec.entity_id = e.id AND ec.contacttype IN ('email', 'mail')
|
WHERE ec.entity_id = e.id AND ec.contacttype IN ('email', 'mail')
|
||||||
ORDER BY ec.sort ASC, ec.id ASC
|
ORDER BY ec.sort ASC, ec.id ASC
|
||||||
) AS email,
|
) AS email,
|
||||||
DATEDIFF_BIG(second, '1970-01-01', e.updated_at) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM entity e
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'customer'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN entity e ON e.id = sq.entity_id
|
||||||
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
||||||
WHERE cg.name <> 'Lieferanten'
|
WHERE cg.name <> 'Lieferanten'
|
||||||
AND DATEDIFF_BIG(second, '1970-01-01', e.updated_at) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY DATEDIFF_BIG(second, '1970-01-01', e.updated_at) ASC, e.id ASC
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
@@ -541,6 +598,34 @@ FROM posterminal pt
|
|||||||
WHERE pt.company_id = @companyId AND pt.token IS NOT NULL
|
WHERE pt.company_id = @companyId AND pt.token IS NOT NULL
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const RECORD_SYNC_QUEUE = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, @entityType, @entityId
|
||||||
|
FROM posterminal pt
|
||||||
|
WHERE pt.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SEED_SYNC_QUEUE_FOR_TERMINAL = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT @posterminalId, 'customergroup', cg.id
|
||||||
|
FROM customergroup cg
|
||||||
|
WHERE cg.company_id = @companyId
|
||||||
|
UNION ALL
|
||||||
|
SELECT @posterminalId, 'customer', e.id
|
||||||
|
FROM entity e
|
||||||
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
WHERE cg.company_id = @companyId
|
||||||
|
UNION ALL
|
||||||
|
SELECT @posterminalId, 'category', c.id
|
||||||
|
FROM category c
|
||||||
|
INNER JOIN posterminalcategory pc ON pc.category_id = c.id
|
||||||
|
WHERE pc.posterminal_id = @posterminalId
|
||||||
|
UNION ALL
|
||||||
|
SELECT @posterminalId, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
WHERE a.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
export const COUNT_DELETED_ENTITIES = `
|
export const COUNT_DELETED_ENTITIES = `
|
||||||
SELECT COUNT(*) AS count
|
SELECT COUNT(*) AS count
|
||||||
FROM posterminalobituary
|
FROM posterminalobituary
|
||||||
|
|||||||
@@ -417,6 +417,23 @@ BEGIN
|
|||||||
END
|
END
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const INIT_POSTERMINALSYNCQUEUE = `
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'posterminalsyncqueue')
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE posterminalsyncqueue (
|
||||||
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
posterminal_id INT NOT NULL,
|
||||||
|
entity_type NVARCHAR(50) NOT NULL,
|
||||||
|
entity_id INT NOT NULL,
|
||||||
|
CONSTRAINT CK_posterminalsyncqueue_entity_type CHECK (entity_type IN ('article', 'category', 'customer', 'customergroup')),
|
||||||
|
CONSTRAINT FK_posterminalsyncqueue_posterminal FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IX_posterminalsyncqueue_posterminal_id
|
||||||
|
ON posterminalsyncqueue (posterminal_id, id);
|
||||||
|
END
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const INIT_ARTICLEEAN = `
|
export const INIT_ARTICLEEAN = `
|
||||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'articleean')
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'articleean')
|
||||||
@@ -1642,6 +1659,7 @@ export const SCHEMA_SCRIPTS = [
|
|||||||
INIT_POSTERMINAL,
|
INIT_POSTERMINAL,
|
||||||
INIT_POSTERMINALCATEGORY,
|
INIT_POSTERMINALCATEGORY,
|
||||||
INIT_POSTERMINALOBITUARY,
|
INIT_POSTERMINALOBITUARY,
|
||||||
|
INIT_POSTERMINALSYNCQUEUE,
|
||||||
INIT_PRINTER,
|
INIT_PRINTER,
|
||||||
INIT_LABELTEMPLATE,
|
INIT_LABELTEMPLATE,
|
||||||
INIT_FILE,
|
INIT_FILE,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const {
|
|||||||
SET_PARENT_SORT,
|
SET_PARENT_SORT,
|
||||||
SET_IS_PARENT, TOGGLE_PARENT, TOUCH_UPDATED_AT, TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT,
|
SET_IS_PARENT, TOGGLE_PARENT, TOUCH_UPDATED_AT, TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT,
|
||||||
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT,
|
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE, ENQUEUE_OPTION_PARENT_ARTICLES_SYNC, ENQUEUE_STUECKLISTE_ARTICLES_SYNC,
|
||||||
UNLINK_CHILD, UPDATE_BRAND, UPDATE_PARENT_BY_SKU, UPDATE_TRACK_STOCK, UPDATE_UNIT,
|
UNLINK_CHILD, UPDATE_BRAND, UPDATE_PARENT_BY_SKU, UPDATE_TRACK_STOCK, UPDATE_UNIT,
|
||||||
UPDATE_UNITAMOUNT, UPDATE_UNIT_AND_AMOUNT, UPDATE_WEIGHT,
|
UPDATE_UNITAMOUNT, UPDATE_UNIT_AND_AMOUNT, UPDATE_WEIGHT,
|
||||||
} = queries;
|
} = queries;
|
||||||
|
|||||||
@@ -163,4 +163,41 @@ WHERE id IN (
|
|||||||
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
) AND parent.parentarticle_id IS NOT NULL
|
) AND parent.parentarticle_id IS NOT NULL
|
||||||
)
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_SUBTREE_CATEGORIES_SYNC = `
|
||||||
|
WITH RECURSIVE cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
)
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'category', cats.id
|
||||||
|
FROM cats
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ENQUEUE_SUBTREE_ARTICLES_SYNC = `
|
||||||
|
WITH RECURSIVE cats AS (
|
||||||
|
SELECT id FROM category WHERE id = @id
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id FROM category c INNER JOIN cats ON c.parent_id = cats.id
|
||||||
|
),
|
||||||
|
arts AS (
|
||||||
|
SELECT ca.article_id AS id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
UNION
|
||||||
|
SELECT child.id FROM article child
|
||||||
|
WHERE child.parentarticle_id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
SELECT parent.parentarticle_id AS id FROM article parent
|
||||||
|
WHERE parent.id IN (
|
||||||
|
SELECT ca.article_id FROM categoryarticle ca WHERE ca.category_id IN (SELECT id FROM cats)
|
||||||
|
) AND parent.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', arts.id
|
||||||
|
FROM arts
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = @companyId
|
||||||
`;
|
`;
|
||||||
@@ -7,8 +7,8 @@ export const {
|
|||||||
GET_BY_COMPANY_AND_ID, GET_CUSTOMER_BY_ID, GET_GROUP_ID_FOR_SUPPLIER,
|
GET_BY_COMPANY_AND_ID, GET_CUSTOMER_BY_ID, GET_GROUP_ID_FOR_SUPPLIER,
|
||||||
GET_SUPPLIER_BY_ID, LIST_BY_COMPANY, LIST_BY_COMPANY_AND_GROUP,
|
GET_SUPPLIER_BY_ID, LIST_BY_COMPANY, LIST_BY_COMPANY_AND_GROUP,
|
||||||
LIST_CUSTOMERS_BY_COMPANY, LIST_SUPPLIERS_BY_COMPANY,
|
LIST_CUSTOMERS_BY_COMPANY, LIST_SUPPLIERS_BY_COMPANY,
|
||||||
NUMBER_TAKEN_IN_COMPANY, POS_GROUP_NAME, SUPPLIER_GROUP_NAME, UPDATE,
|
NUMBER_TAKEN_IN_COMPANY, POS_GROUP_NAME, SUPPLIER_GROUP_NAME,
|
||||||
UPDATE_NAME,
|
TOUCH_UPDATED_AT, UPDATE, UPDATE_NAME,
|
||||||
} = queries;
|
} = queries;
|
||||||
|
|
||||||
export const DELETE_BY_COMPANY_AND_ID = `
|
export const DELETE_BY_COMPANY_AND_ID = `
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ export const {
|
|||||||
COUNT_CUSTOMER_GROUPS, COUNT_COMPOSITE_PRODUCTS, MAX_ORDER_ID,
|
COUNT_CUSTOMER_GROUPS, COUNT_COMPOSITE_PRODUCTS, MAX_ORDER_ID,
|
||||||
LIST_POS_PRODUCT_CATEGORIES, LIST_POS_CUSTOMER_GROUP_IDS, LIST_POS_PRODUCT_PRICES,
|
LIST_POS_PRODUCT_CATEGORIES, LIST_POS_CUSTOMER_GROUP_IDS, LIST_POS_PRODUCT_PRICES,
|
||||||
LIST_POS_MANDATED_OPTIONS, LIST_POS_PARENT_OPTIONS,
|
LIST_POS_MANDATED_OPTIONS, LIST_POS_PARENT_OPTIONS,
|
||||||
TOUCH_LASTSEEN, RECORD_OBITUARY, COUNT_DELETED_ENTITIES,
|
TOUCH_LASTSEEN, RECORD_OBITUARY, RECORD_SYNC_QUEUE, SEED_SYNC_QUEUE_FOR_TERMINAL,
|
||||||
|
COUNT_DELETED_ENTITIES,
|
||||||
} = queries;
|
} = queries;
|
||||||
|
|
||||||
export const SET_ON = `
|
export const SET_ON = `
|
||||||
@@ -50,13 +51,19 @@ SELECT
|
|||||||
cg.name,
|
cg.name,
|
||||||
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
|
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
|
||||||
'0.000000' AS discountPercent,
|
'0.000000' AS discountPercent,
|
||||||
CAST(strftime('%s', cg.updated_at) AS INTEGER) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM customergroup cg
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'customergroup'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN customergroup cg ON cg.id = sq.entity_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
||||||
INNER JOIN company co ON co.id = pt.company_id
|
INNER JOIN company co ON co.id = pt.company_id
|
||||||
WHERE cg.name <> 'Lieferanten'
|
WHERE cg.name <> 'Lieferanten'
|
||||||
AND CAST(strftime('%s', cg.updated_at) AS INTEGER) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY lastChanged ASC, cg.id ASC
|
|
||||||
LIMIT @limit
|
LIMIT @limit
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -116,13 +123,19 @@ SELECT
|
|||||||
ORDER BY ec.sort ASC, ec.id ASC
|
ORDER BY ec.sort ASC, ec.id ASC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
) AS email,
|
) AS email,
|
||||||
CAST(strftime('%s', e.updated_at) AS INTEGER) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM entity e
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'customer'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN entity e ON e.id = sq.entity_id
|
||||||
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
|
||||||
WHERE cg.name <> 'Lieferanten'
|
WHERE cg.name <> 'Lieferanten'
|
||||||
AND CAST(strftime('%s', e.updated_at) AS INTEGER) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY lastChanged ASC, e.id ASC
|
|
||||||
LIMIT @limit
|
LIMIT @limit
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -141,16 +154,21 @@ SELECT
|
|||||||
ORDER BY cp.sort ASC, cp.id ASC
|
ORDER BY cp.sort ASC, cp.id ASC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
) AS imgHash,
|
) AS imgHash,
|
||||||
CAST(strftime('%s', c.updated_at) AS INTEGER) AS lastChanged
|
sq.syncId AS lastChanged
|
||||||
FROM category c
|
FROM (
|
||||||
INNER JOIN posterminalcategory pc ON pc.category_id = c.id
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'category'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN category c ON c.id = sq.entity_id
|
||||||
|
INNER JOIN posterminalcategory pc ON pc.category_id = c.id AND pc.posterminal_id = @posterminalId
|
||||||
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
INNER JOIN posterminal pt ON pt.id = pc.posterminal_id
|
||||||
INNER JOIN company co ON co.id = pt.company_id
|
INNER JOIN company co ON co.id = pt.company_id
|
||||||
LEFT JOIN categorytext ct ON ct.category_id = c.id AND ct.language_id = co.default_language_id
|
LEFT JOIN categorytext ct ON ct.category_id = c.id AND ct.language_id = co.default_language_id
|
||||||
WHERE pc.posterminal_id = @posterminalId
|
WHERE (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
||||||
AND (co.root_category_id IS NULL OR c.id <> co.root_category_id)
|
ORDER BY sq.syncId ASC
|
||||||
AND CAST(strftime('%s', c.updated_at) AS INTEGER) > @cursor
|
|
||||||
ORDER BY lastChanged ASC, c.id ASC
|
|
||||||
LIMIT @limit
|
LIMIT @limit
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -162,7 +180,7 @@ SELECT
|
|||||||
COALESCE(pr.net, 0) AS netPrice,
|
COALESCE(pr.net, 0) AS netPrice,
|
||||||
COALESCE(ptax.rate, ctax.rate, 0) AS taxRate,
|
COALESCE(ptax.rate, ctax.rate, 0) AS taxRate,
|
||||||
a.created_at AS createdAt,
|
a.created_at AS createdAt,
|
||||||
(CAST(strftime('%s', a.updated_at) AS INTEGER) * 1000000 + (a.id % 1000000)) AS lastChanged,
|
sq.syncId AS lastChanged,
|
||||||
COALESCE(
|
COALESCE(
|
||||||
(
|
(
|
||||||
SELECT p.hash
|
SELECT p.hash
|
||||||
@@ -265,7 +283,14 @@ SELECT
|
|||||||
co.id AS companyId,
|
co.id AS companyId,
|
||||||
co.root_category_id AS rootCategoryId,
|
co.root_category_id AS rootCategoryId,
|
||||||
co.poscustomergroup_id AS posCustomerGroupId
|
co.poscustomergroup_id AS posCustomerGroupId
|
||||||
FROM article a
|
FROM (
|
||||||
|
SELECT entity_id, MAX(id) AS syncId
|
||||||
|
FROM posterminalsyncqueue
|
||||||
|
WHERE posterminal_id = @posterminalId AND entity_type = 'article'
|
||||||
|
GROUP BY entity_id
|
||||||
|
HAVING MAX(id) > @cursor
|
||||||
|
) sq
|
||||||
|
INNER JOIN article a ON a.id = sq.entity_id
|
||||||
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = a.company_id
|
||||||
INNER JOIN company co ON co.id = a.company_id
|
INNER JOIN company co ON co.id = a.company_id
|
||||||
LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = co.default_language_id
|
LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = co.default_language_id
|
||||||
@@ -279,8 +304,7 @@ WHERE EXISTS (
|
|||||||
WHERE ca.article_id = a.id
|
WHERE ca.article_id = a.id
|
||||||
AND pc.posterminal_id = @posterminalId
|
AND pc.posterminal_id = @posterminalId
|
||||||
)
|
)
|
||||||
AND (CAST(strftime('%s', a.updated_at) AS INTEGER) * 1000000 + (a.id % 1000000)) > @cursor
|
ORDER BY sq.syncId ASC
|
||||||
ORDER BY (CAST(strftime('%s', a.updated_at) AS INTEGER) * 1000000 + (a.id % 1000000)) ASC
|
|
||||||
LIMIT @limit
|
LIMIT @limit
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -660,6 +660,18 @@ CREATE INDEX IF NOT EXISTS IX_posterminalobituary_posterminal_id
|
|||||||
ON posterminalobituary (posterminal_id, id);
|
ON posterminalobituary (posterminal_id, id);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const INIT_POSTERMINALSYNCQUEUE = `
|
||||||
|
CREATE TABLE IF NOT EXISTS posterminalsyncqueue (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
posterminal_id INTEGER NOT NULL,
|
||||||
|
entity_type TEXT NOT NULL CHECK (entity_type IN ('article', 'category', 'customer', 'customergroup')),
|
||||||
|
entity_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS IX_posterminalsyncqueue_posterminal_id
|
||||||
|
ON posterminalsyncqueue (posterminal_id, id);
|
||||||
|
`;
|
||||||
|
|
||||||
export const INIT_PRINTER = `
|
export const INIT_PRINTER = `
|
||||||
CREATE TABLE IF NOT EXISTS printer (
|
CREATE TABLE IF NOT EXISTS printer (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
@@ -1206,6 +1218,7 @@ export const SCHEMA_SCRIPTS = [
|
|||||||
INIT_POSTERMINAL,
|
INIT_POSTERMINAL,
|
||||||
INIT_POSTERMINALCATEGORY,
|
INIT_POSTERMINALCATEGORY,
|
||||||
INIT_POSTERMINALOBITUARY,
|
INIT_POSTERMINALOBITUARY,
|
||||||
|
INIT_POSTERMINALSYNCQUEUE,
|
||||||
INIT_PRINTER,
|
INIT_PRINTER,
|
||||||
INIT_LABELTEMPLATE,
|
INIT_LABELTEMPLATE,
|
||||||
INIT_FILE,
|
INIT_FILE,
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ export default function addChild(provider) {
|
|||||||
|
|
||||||
// Touch parent article updated_at so POS and other consumers refresh parent options
|
// Touch parent article updated_at so POS and other consumers refresh parent options
|
||||||
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: childId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: parentId });
|
||||||
|
|
||||||
return load(googleAuthId, childSku, runner);
|
return load(googleAuthId, childSku, runner);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,8 +8,14 @@ import {
|
|||||||
} from '../../providers/sqlite3/queries/articlepic.js';
|
} from '../../providers/sqlite3/queries/articlepic.js';
|
||||||
import { CREATE as MSSQL_CREATE_PIC } from '../../providers/mssql/queries/pic.js';
|
import { CREATE as MSSQL_CREATE_PIC } from '../../providers/mssql/queries/pic.js';
|
||||||
import { CREATE as SQLITE_CREATE_PIC } from '../../providers/sqlite3/queries/pic.js';
|
import { CREATE as SQLITE_CREATE_PIC } from '../../providers/sqlite3/queries/pic.js';
|
||||||
import { TOUCH_UPDATED_AT as MSSQL_TOUCH } from '../../providers/mssql/queries/article.js';
|
import {
|
||||||
import { TOUCH_UPDATED_AT as SQLITE_TOUCH } from '../../providers/sqlite3/queries/article.js';
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import processAvifImage from '../../util/processAvifImage.js';
|
import processAvifImage from '../../util/processAvifImage.js';
|
||||||
import newFullHash from '../../util/newFullHash.js';
|
import newFullHash from '../../util/newFullHash.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
@@ -24,6 +30,7 @@ export default function addImage(provider) {
|
|||||||
const createPicSql = isSqlite ? SQLITE_CREATE_PIC : MSSQL_CREATE_PIC;
|
const createPicSql = isSqlite ? SQLITE_CREATE_PIC : MSSQL_CREATE_PIC;
|
||||||
const addArticlePicSql = isSqlite ? SQLITE_ADD_ARTICLEPIC : MSSQL_ADD_ARTICLEPIC;
|
const addArticlePicSql = isSqlite ? SQLITE_ADD_ARTICLEPIC : MSSQL_ADD_ARTICLEPIC;
|
||||||
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an image to an article by its SKU, processing full, thumb, and 32px-edge small-thumb AVIF variants.
|
* Adds an image to an article by its SKU, processing full, thumb, and 32px-edge small-thumb AVIF variants.
|
||||||
@@ -107,6 +114,7 @@ export default function addImage(provider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
picId,
|
picId,
|
||||||
|
|||||||
@@ -173,6 +173,8 @@ export default function attachChild(provider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: prevParentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: prevParentId });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign parentsort if not already child of this parent
|
// Assign parentsort if not already child of this parent
|
||||||
@@ -305,6 +307,11 @@ export default function attachChild(provider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: child.id });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: child.id });
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: parentId });
|
||||||
|
|
||||||
const updated = await load(googleAuthId, childSku, runner);
|
const updated = await load(googleAuthId, childSku, runner);
|
||||||
const children = await list(googleAuthId, parentSku, runner);
|
const children = await list(googleAuthId, parentSku, runner);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
CREATE as MSSQL_CREATE_ARTICLE,
|
CREATE as MSSQL_CREATE_ARTICLE,
|
||||||
CHECK_HAS_WAREHOUSE as MSSQL_CHECK_HAS_WAREHOUSE,
|
CHECK_HAS_WAREHOUSE as MSSQL_CHECK_HAS_WAREHOUSE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
CREATE as SQLITE_CREATE_ARTICLE,
|
CREATE as SQLITE_CREATE_ARTICLE,
|
||||||
CHECK_HAS_WAREHOUSE as SQLITE_CHECK_HAS_WAREHOUSE,
|
CHECK_HAS_WAREHOUSE as SQLITE_CHECK_HAS_WAREHOUSE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import { ADD as MSSQL_ADD_CATEGORYARTICLE } from '../../providers/mssql/queries/categoryarticle.js';
|
import { ADD as MSSQL_ADD_CATEGORYARTICLE } from '../../providers/mssql/queries/categoryarticle.js';
|
||||||
import { ADD as SQLITE_ADD_CATEGORYARTICLE } from '../../providers/sqlite3/queries/categoryarticle.js';
|
import { ADD as SQLITE_ADD_CATEGORYARTICLE } from '../../providers/sqlite3/queries/categoryarticle.js';
|
||||||
@@ -30,6 +32,7 @@ export default function createUnderParent(provider) {
|
|||||||
const checkHasWarehouseSql = isSqlite ? SQLITE_CHECK_HAS_WAREHOUSE : MSSQL_CHECK_HAS_WAREHOUSE;
|
const checkHasWarehouseSql = isSqlite ? SQLITE_CHECK_HAS_WAREHOUSE : MSSQL_CHECK_HAS_WAREHOUSE;
|
||||||
const addCategoryArticleSql = isSqlite ? SQLITE_ADD_CATEGORYARTICLE : MSSQL_ADD_CATEGORYARTICLE;
|
const addCategoryArticleSql = isSqlite ? SQLITE_ADD_CATEGORYARTICLE : MSSQL_ADD_CATEGORYARTICLE;
|
||||||
const createArticleTextSql = isSqlite ? SQLITE_CREATE_ARTICLETEXT : MSSQL_CREATE_ARTICLETEXT;
|
const createArticleTextSql = isSqlite ? SQLITE_CREATE_ARTICLETEXT : MSSQL_CREATE_ARTICLETEXT;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new article under a given parent category, allocating a SKU and
|
* Creates a new article under a given parent category, allocating a SKU and
|
||||||
@@ -118,6 +121,8 @@ export default function createUnderParent(provider) {
|
|||||||
await initArticleWarehouseSummary(runner, { companyId, articleId: id });
|
await initArticleWarehouseSummary(runner, { companyId, articleId: id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(enqueueSyncSql, { articleId: id });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
parentId,
|
parentId,
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default function del(provider) {
|
|||||||
|
|
||||||
// Touch any parent articles that used this article as an option before deleting it
|
// Touch any parent articles that used this article as an option before deleting it
|
||||||
await runner.query(articleQueries.TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT, { articleId: id });
|
await runner.query(articleQueries.TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT, { articleId: id });
|
||||||
|
await runner.query(articleQueries.ENQUEUE_OPTION_PARENT_ARTICLES_SYNC, { articleId: id });
|
||||||
|
|
||||||
const deleted = await runner.query(queries.DELETE_BY_ID, { articleId: id });
|
const deleted = await runner.query(queries.DELETE_BY_ID, { articleId: id });
|
||||||
if (!deleted.rowsAffected) {
|
if (!deleted.rowsAffected) {
|
||||||
|
|||||||
@@ -2,16 +2,24 @@ import sharp from 'sharp';
|
|||||||
import { encodeRGBA } from 'skelehash-wasm';
|
import { encodeRGBA } from 'skelehash-wasm';
|
||||||
import { DELETE_BY_ARTICLE_AND_HASH as MSSQL_QUERY } from '../../providers/mssql/queries/pic.js';
|
import { DELETE_BY_ARTICLE_AND_HASH as MSSQL_QUERY } from '../../providers/mssql/queries/pic.js';
|
||||||
import { DELETE_BY_ARTICLE_AND_HASH as SQLITE_QUERY } from '../../providers/sqlite3/queries/pic.js';
|
import { DELETE_BY_ARTICLE_AND_HASH as SQLITE_QUERY } from '../../providers/sqlite3/queries/pic.js';
|
||||||
import { TOUCH_UPDATED_AT as MSSQL_TOUCH } from '../../providers/mssql/queries/article.js';
|
import {
|
||||||
import { TOUCH_UPDATED_AT as SQLITE_TOUCH } from '../../providers/sqlite3/queries/article.js';
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
import { recordImageDeleteHistory } from '../articlehistory/record.js';
|
import { recordImageDeleteHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function deleteImage(provider) {
|
export default function deleteImage(provider) {
|
||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_QUERY : MSSQL_QUERY;
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const touchArticleSql = provider?.dialect === 'sqlite3' ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const sql = isSqlite ? SQLITE_QUERY : MSSQL_QUERY;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an image from an article by its SKU and full image hash.
|
* Deletes an image from an article by its SKU and full image hash.
|
||||||
@@ -86,6 +94,7 @@ export default function deleteImage(provider) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import * as mssqlPic from '../../providers/mssql/queries/articlepic.js';
|
import * as mssqlPic from '../../providers/mssql/queries/articlepic.js';
|
||||||
import * as sqlitePic from '../../providers/sqlite3/queries/articlepic.js';
|
import * as sqlitePic from '../../providers/sqlite3/queries/articlepic.js';
|
||||||
import { TOUCH_UPDATED_AT as MSSQL_TOUCH } from '../../providers/mssql/queries/article.js';
|
import {
|
||||||
import { TOUCH_UPDATED_AT as SQLITE_TOUCH } from '../../providers/sqlite3/queries/article.js';
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
import { recordImageOrderHistory } from '../articlehistory/record.js';
|
import { recordImageOrderHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -11,6 +17,7 @@ export default function orderImages(provider) {
|
|||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const queries = isSqlite ? sqlitePic : mssqlPic;
|
const queries = isSqlite ? sqlitePic : mssqlPic;
|
||||||
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reorders the images of an article by its SKU.
|
* Reorders the images of an article by its SKU.
|
||||||
@@ -73,6 +80,7 @@ export default function orderImages(provider) {
|
|||||||
fullHashes,
|
fullHashes,
|
||||||
});
|
});
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { fullHashes };
|
return { fullHashes };
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export default function removeChild(provider) {
|
|||||||
|
|
||||||
// Touch parent article updated_at so POS and other consumers refresh parent options
|
// Touch parent article updated_at so POS and other consumers refresh parent options
|
||||||
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: parentId });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -134,8 +135,11 @@ export default function removeChild(provider) {
|
|||||||
parentSku,
|
parentSku,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Touch parent article updated_at so POS and other consumers refresh parent options
|
// Touch child and parent article updated_at so POS and other consumers refresh parent options
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: childId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: childId });
|
||||||
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: parentId });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
GET_BRAND_BY_COMPANY_AND_ID as MSSQL_GET_BRAND,
|
GET_BRAND_BY_COMPANY_AND_ID as MSSQL_GET_BRAND,
|
||||||
UPDATE_BRAND as MSSQL_UPDATE_BRAND,
|
UPDATE_BRAND as MSSQL_UPDATE_BRAND,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
GET_BRAND_BY_COMPANY_AND_ID as SQLITE_GET_BRAND,
|
GET_BRAND_BY_COMPANY_AND_ID as SQLITE_GET_BRAND,
|
||||||
UPDATE_BRAND as SQLITE_UPDATE_BRAND,
|
UPDATE_BRAND as SQLITE_UPDATE_BRAND,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
@@ -18,6 +20,7 @@ export default function setBrandIdBySku(provider) {
|
|||||||
|
|
||||||
const getBrandSql = isSqlite ? SQLITE_GET_BRAND : MSSQL_GET_BRAND;
|
const getBrandSql = isSqlite ? SQLITE_GET_BRAND : MSSQL_GET_BRAND;
|
||||||
const updateBrandSql = isSqlite ? SQLITE_UPDATE_BRAND : MSSQL_UPDATE_BRAND;
|
const updateBrandSql = isSqlite ? SQLITE_UPDATE_BRAND : MSSQL_UPDATE_BRAND;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (or clears) the brand of an article by its SKU.
|
* Sets (or clears) the brand of an article by its SKU.
|
||||||
@@ -79,6 +82,8 @@ export default function setBrandIdBySku(provider) {
|
|||||||
throw new Error('Article not found');
|
throw new Error('Article not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
// null = no brand; treat as distinct sentinel so first assignment is logged
|
// null = no brand; treat as distinct sentinel so first assignment is logged
|
||||||
await recordBrandChangeHistory(runner, {
|
await recordBrandChangeHistory(runner, {
|
||||||
articleId,
|
articleId,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
INSERT_POSTERMINAL_OBITUARY as MSSQL_INSERT_OBITUARY,
|
INSERT_POSTERMINAL_OBITUARY as MSSQL_INSERT_OBITUARY,
|
||||||
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as MSSQL_LIST_TERMINALS,
|
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as MSSQL_LIST_TERMINALS,
|
||||||
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
ADD_CATEGORY as SQLITE_ADD_CATEGORY,
|
ADD_CATEGORY as SQLITE_ADD_CATEGORY,
|
||||||
@@ -13,6 +14,7 @@ import {
|
|||||||
INSERT_POSTERMINAL_OBITUARY as SQLITE_INSERT_OBITUARY,
|
INSERT_POSTERMINAL_OBITUARY as SQLITE_INSERT_OBITUARY,
|
||||||
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as SQLITE_LIST_TERMINALS,
|
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as SQLITE_LIST_TERMINALS,
|
||||||
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
@@ -32,6 +34,7 @@ export default function setCategoryIdsBySku(provider) {
|
|||||||
const listTerminalsSql = isSqlite ? SQLITE_LIST_TERMINALS : MSSQL_LIST_TERMINALS;
|
const listTerminalsSql = isSqlite ? SQLITE_LIST_TERMINALS : MSSQL_LIST_TERMINALS;
|
||||||
const insertObituarySql = isSqlite ? SQLITE_INSERT_OBITUARY : MSSQL_INSERT_OBITUARY;
|
const insertObituarySql = isSqlite ? SQLITE_INSERT_OBITUARY : MSSQL_INSERT_OBITUARY;
|
||||||
const clearObituarySql = isSqlite ? SQLITE_CLEAR_OBITUARY : MSSQL_CLEAR_OBITUARY;
|
const clearObituarySql = isSqlite ? SQLITE_CLEAR_OBITUARY : MSSQL_CLEAR_OBITUARY;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the category membership of an article by its SKU.
|
* Replaces the category membership of an article by its SKU.
|
||||||
@@ -150,6 +153,7 @@ export default function setCategoryIdsBySku(provider) {
|
|||||||
|
|
||||||
// Touch article updated_at so POS and other consumers pick up category assignment changes
|
// Touch article updated_at so POS and other consumers pick up category assignment changes
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
const article = await load(articleId, languageId, runner);
|
const article = await load(articleId, languageId, runner);
|
||||||
if (!article) {
|
if (!article) {
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import {
|
|||||||
DELETE_EANS_BY_ARTICLE as MSSQL_DELETE_EANS,
|
DELETE_EANS_BY_ARTICLE as MSSQL_DELETE_EANS,
|
||||||
EAN_EXISTS_FOR_OTHER_ARTICLE as MSSQL_CHECK_CONFLICT,
|
EAN_EXISTS_FOR_OTHER_ARTICLE as MSSQL_CHECK_CONFLICT,
|
||||||
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
ADD_EAN as SQLITE_ADD_EAN,
|
ADD_EAN as SQLITE_ADD_EAN,
|
||||||
DELETE_EANS_BY_ARTICLE as SQLITE_DELETE_EANS,
|
DELETE_EANS_BY_ARTICLE as SQLITE_DELETE_EANS,
|
||||||
EAN_EXISTS_FOR_OTHER_ARTICLE as SQLITE_CHECK_CONFLICT,
|
EAN_EXISTS_FOR_OTHER_ARTICLE as SQLITE_CHECK_CONFLICT,
|
||||||
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
@@ -25,6 +27,7 @@ export default function setEansBySku(provider) {
|
|||||||
const deleteEansSql = isSqlite ? SQLITE_DELETE_EANS : MSSQL_DELETE_EANS;
|
const deleteEansSql = isSqlite ? SQLITE_DELETE_EANS : MSSQL_DELETE_EANS;
|
||||||
const checkConflictSql = isSqlite ? SQLITE_CHECK_CONFLICT : MSSQL_CHECK_CONFLICT;
|
const checkConflictSql = isSqlite ? SQLITE_CHECK_CONFLICT : MSSQL_CHECK_CONFLICT;
|
||||||
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the EAN list of an article by its SKU.
|
* Replaces the EAN list of an article by its SKU.
|
||||||
@@ -103,6 +106,7 @@ export default function setEansBySku(provider) {
|
|||||||
|
|
||||||
// Touch article updated_at so POS and other consumers pick up the barcode change
|
// Touch article updated_at so POS and other consumers pick up the barcode change
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
const article = await load(articleId, languageId, runner);
|
const article = await load(articleId, languageId, runner);
|
||||||
if (!article) {
|
if (!article) {
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ export default function setParentBySku(provider) {
|
|||||||
parentArticleId: null,
|
parentArticleId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId });
|
||||||
|
|
||||||
if (prevParentId) {
|
if (prevParentId) {
|
||||||
const prevParentTextRes = await runner.query(
|
const prevParentTextRes = await runner.query(
|
||||||
'SELECT sku FROM article WHERE id = @prevParentId',
|
'SELECT sku FROM article WHERE id = @prevParentId',
|
||||||
@@ -74,6 +77,9 @@ export default function setParentBySku(provider) {
|
|||||||
companyuserId,
|
companyuserId,
|
||||||
text: `Variante "${childName}" (${sku}) getrennt`,
|
text: `Variante "${childName}" (${sku}) getrennt`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: prevParentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: prevParentId });
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlinked = await load(articleId, languageId, runner);
|
const unlinked = await load(articleId, languageId, runner);
|
||||||
@@ -141,6 +147,11 @@ export default function setParentBySku(provider) {
|
|||||||
parentSku,
|
parentSku,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId });
|
||||||
|
await runner.query(queries.TOUCH_UPDATED_AT, { articleId: parentId });
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId: parentId });
|
||||||
|
|
||||||
const article = await load(articleId, languageId, runner);
|
const article = await load(articleId, languageId, runner);
|
||||||
if (!article) {
|
if (!article) {
|
||||||
throw new Error('Article not found');
|
throw new Error('Article not found');
|
||||||
|
|||||||
@@ -9,10 +9,14 @@ import {
|
|||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT as MSSQL_TOUCH_OPTION_PARENTS,
|
TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT as MSSQL_TOUCH_OPTION_PARENTS,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_OPTION_PARENT_ARTICLES_SYNC as MSSQL_ENQUEUE_OPTION_PARENTS,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT as SQLITE_TOUCH_OPTION_PARENTS,
|
TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT as SQLITE_TOUCH_OPTION_PARENTS,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_OPTION_PARENT_ARTICLES_SYNC as SQLITE_ENQUEUE_OPTION_PARENTS,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import taxEnsure from '../tax/ensure.js';
|
import taxEnsure from '../tax/ensure.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
@@ -75,6 +79,8 @@ export default function setPricesBySku(provider) {
|
|||||||
const deletePriceSql = isSqlite ? SQLITE_DELETE_PRICE : MSSQL_DELETE_PRICE;
|
const deletePriceSql = isSqlite ? SQLITE_DELETE_PRICE : MSSQL_DELETE_PRICE;
|
||||||
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
const touchOptionParentsSql = isSqlite ? SQLITE_TOUCH_OPTION_PARENTS : MSSQL_TOUCH_OPTION_PARENTS;
|
const touchOptionParentsSql = isSqlite ? SQLITE_TOUCH_OPTION_PARENTS : MSSQL_TOUCH_OPTION_PARENTS;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
const enqueueOptionParentsSql = isSqlite ? SQLITE_ENQUEUE_OPTION_PARENTS : MSSQL_ENQUEUE_OPTION_PARENTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the price list of an article by its SKU.
|
* Replaces the price list of an article by its SKU.
|
||||||
@@ -153,9 +159,11 @@ export default function setPricesBySku(provider) {
|
|||||||
|
|
||||||
// Touch article updated_at so POS and other consumers pick up the price change
|
// Touch article updated_at so POS and other consumers pick up the price change
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
// Touch any parent articles using this article as an option so their deposit price updates
|
// Touch any parent articles using this article as an option so their deposit price updates
|
||||||
await runner.query(touchOptionParentsSql, { articleId });
|
await runner.query(touchOptionParentsSql, { articleId });
|
||||||
|
await runner.query(enqueueOptionParentsSql, { articleId });
|
||||||
|
|
||||||
const article = await load(articleId, languageId, runner);
|
const article = await load(articleId, languageId, runner);
|
||||||
if (!article) {
|
if (!article) {
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import {
|
|||||||
UPDATE_TRACK_STOCK as MSSQL_UPDATE_TRACK_STOCK,
|
UPDATE_TRACK_STOCK as MSSQL_UPDATE_TRACK_STOCK,
|
||||||
CHECK_HAS_WAREHOUSE as MSSQL_CHECK_HAS_WAREHOUSE,
|
CHECK_HAS_WAREHOUSE as MSSQL_CHECK_HAS_WAREHOUSE,
|
||||||
CHECK_ARTICLE_WAREHOUSE_STOCKS as MSSQL_CHECK_ARTICLE_WAREHOUSE_STOCKS,
|
CHECK_ARTICLE_WAREHOUSE_STOCKS as MSSQL_CHECK_ARTICLE_WAREHOUSE_STOCKS,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
UPDATE_TRACK_STOCK as SQLITE_UPDATE_TRACK_STOCK,
|
UPDATE_TRACK_STOCK as SQLITE_UPDATE_TRACK_STOCK,
|
||||||
CHECK_HAS_WAREHOUSE as SQLITE_CHECK_HAS_WAREHOUSE,
|
CHECK_HAS_WAREHOUSE as SQLITE_CHECK_HAS_WAREHOUSE,
|
||||||
CHECK_ARTICLE_WAREHOUSE_STOCKS as SQLITE_CHECK_ARTICLE_WAREHOUSE_STOCKS,
|
CHECK_ARTICLE_WAREHOUSE_STOCKS as SQLITE_CHECK_ARTICLE_WAREHOUSE_STOCKS,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
@@ -26,6 +28,7 @@ export default function setTrackStockBySku(provider) {
|
|||||||
const sql = isSqlite ? SQLITE_UPDATE_TRACK_STOCK : MSSQL_UPDATE_TRACK_STOCK;
|
const sql = isSqlite ? SQLITE_UPDATE_TRACK_STOCK : MSSQL_UPDATE_TRACK_STOCK;
|
||||||
const checkHasWarehouseSql = isSqlite ? SQLITE_CHECK_HAS_WAREHOUSE : MSSQL_CHECK_HAS_WAREHOUSE;
|
const checkHasWarehouseSql = isSqlite ? SQLITE_CHECK_HAS_WAREHOUSE : MSSQL_CHECK_HAS_WAREHOUSE;
|
||||||
const checkStocksSql = isSqlite ? SQLITE_CHECK_ARTICLE_WAREHOUSE_STOCKS : MSSQL_CHECK_ARTICLE_WAREHOUSE_STOCKS;
|
const checkStocksSql = isSqlite ? SQLITE_CHECK_ARTICLE_WAREHOUSE_STOCKS : MSSQL_CHECK_ARTICLE_WAREHOUSE_STOCKS;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the track_stock flag of an article by its SKU.
|
* Sets the track_stock flag of an article by its SKU.
|
||||||
@@ -96,6 +99,8 @@ export default function setTrackStockBySku(provider) {
|
|||||||
throw new Error('Article not found');
|
throw new Error('Article not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
// Write history if track_stock changed
|
// Write history if track_stock changed
|
||||||
if (oldTrack !== newTrack) {
|
if (oldTrack !== newTrack) {
|
||||||
if (!newTrack) {
|
if (!newTrack) {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { UPDATE_WEIGHT as MSSQL_UPDATE_WEIGHT } from '../../providers/mssql/queries/article.js';
|
import {
|
||||||
import { UPDATE_WEIGHT as SQLITE_UPDATE_WEIGHT } from '../../providers/sqlite3/queries/article.js';
|
UPDATE_WEIGHT as MSSQL_UPDATE_WEIGHT,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
UPDATE_WEIGHT as SQLITE_UPDATE_WEIGHT,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import queryBySku from './queryBySku.js';
|
import queryBySku from './queryBySku.js';
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
import { recordWeightChangeHistory } from '../articlehistory/record.js';
|
import { recordWeightChangeHistory } from '../articlehistory/record.js';
|
||||||
@@ -8,7 +14,9 @@ import makeRunner from '../runner.js';
|
|||||||
export default function setWeightBySku(provider) {
|
export default function setWeightBySku(provider) {
|
||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const load = queryBySku(provider);
|
const load = queryBySku(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_UPDATE_WEIGHT : MSSQL_UPDATE_WEIGHT;
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
const sql = isSqlite ? SQLITE_UPDATE_WEIGHT : MSSQL_UPDATE_WEIGHT;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the weight of an article by its SKU.
|
* Sets the weight of an article by its SKU.
|
||||||
@@ -48,6 +56,8 @@ export default function setWeightBySku(provider) {
|
|||||||
throw new Error('Article not found');
|
throw new Error('Article not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
// Write history if weight changed
|
// Write history if weight changed
|
||||||
await recordWeightChangeHistory(runner, {
|
await recordWeightChangeHistory(runner, {
|
||||||
articleId,
|
articleId,
|
||||||
|
|||||||
@@ -171,6 +171,8 @@ export default function toggleParent(provider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(queries.ENQUEUE_SYNC_BY_ARTICLE, { articleId });
|
||||||
|
|
||||||
return load(googleAuthId, sku, runner);
|
return load(googleAuthId, sku, runner);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -234,9 +234,11 @@ export default function updateBySku(provider) {
|
|||||||
|
|
||||||
// Touch article updated_at so all consumers pick up changes
|
// Touch article updated_at so all consumers pick up changes
|
||||||
await runner.query(articleQueries.TOUCH_UPDATED_AT, { articleId });
|
await runner.query(articleQueries.TOUCH_UPDATED_AT, { articleId });
|
||||||
|
await runner.query(articleQueries.ENQUEUE_SYNC_BY_ARTICLE, { articleId });
|
||||||
|
|
||||||
// Touch any parent articles that use this article as an option so their deposit name/details update on POS
|
// Touch any parent articles that use this article as an option so their deposit name/details update on POS
|
||||||
await runner.query(articleQueries.TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT, { articleId });
|
await runner.query(articleQueries.TOUCH_OPTION_PARENT_ARTICLES_UPDATED_AT, { articleId });
|
||||||
|
await runner.query(articleQueries.ENQUEUE_OPTION_PARENT_ARTICLES_SYNC, { articleId });
|
||||||
|
|
||||||
const article = await load(articleId, languageId, runner);
|
const article = await load(articleId, languageId, runner);
|
||||||
if (!article) {
|
if (!article) {
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ import {
|
|||||||
INSERT_ROW as SQLITE_INSERT,
|
INSERT_ROW as SQLITE_INSERT,
|
||||||
GET_VALUE_DETAIL as SQLITE_GET_DETAIL,
|
GET_VALUE_DETAIL as SQLITE_GET_DETAIL,
|
||||||
} from '../../providers/sqlite3/queries/articleattributevalue.js';
|
} from '../../providers/sqlite3/queries/articleattributevalue.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import { recordAttributeChangeHistory } from '../articlehistory/record.js';
|
import { recordAttributeChangeHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -18,6 +26,8 @@ export default function setByArticleSku(provider) {
|
|||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||||
const getDetailSql = isSqlite ? SQLITE_GET_DETAIL : MSSQL_GET_DETAIL;
|
const getDetailSql = isSqlite ? SQLITE_GET_DETAIL : MSSQL_GET_DETAIL;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces all attribute values for an article by its SKU.
|
* Replaces all attribute values for an article by its SKU.
|
||||||
@@ -187,6 +197,13 @@ export default function setByArticleSku(provider) {
|
|||||||
newAttrs: validated,
|
newAttrs: validated,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
if (article?.parentarticle_id != null) {
|
||||||
|
await runner.query(touchArticleSql, { articleId: article.parentarticle_id });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId: article.parentarticle_id });
|
||||||
|
}
|
||||||
|
|
||||||
return inserted;
|
return inserted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/articlelist.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/articlelist.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlelist.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/articlelist.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import getItemsByArticleSku from './getItemsByArticleSku.js';
|
import getItemsByArticleSku from './getItemsByArticleSku.js';
|
||||||
import {
|
import {
|
||||||
@@ -46,6 +54,8 @@ export default function setItemsByArticleSku(provider) {
|
|||||||
const getItems = getItemsByArticleSku(provider);
|
const getItems = getItemsByArticleSku(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets or clears the Stückliste (bundle items) for an article.
|
* Sets or clears the Stückliste (bundle items) for an article.
|
||||||
@@ -108,6 +118,8 @@ export default function setItemsByArticleSku(provider) {
|
|||||||
type: 'articlelist_cleared',
|
type: 'articlelist_cleared',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -229,6 +241,9 @@ export default function setItemsByArticleSku(provider) {
|
|||||||
items: result,
|
items: result,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ import {
|
|||||||
import {
|
import {
|
||||||
DELETE_BY_ARTICLE_AND_PROPERTY_ID as SQLITE_DELETE,
|
DELETE_BY_ARTICLE_AND_PROPERTY_ID as SQLITE_DELETE,
|
||||||
} from '../../providers/sqlite3/queries/articleproperty.js';
|
} from '../../providers/sqlite3/queries/articleproperty.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import { recordPropertyDeleteHistory } from '../articlehistory/record.js';
|
import { recordPropertyDeleteHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -12,6 +20,8 @@ export default function deleteArticleProperty(provider) {
|
|||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a property from an article by SKU and propertyId.
|
* Deletes a property from an article by SKU and propertyId.
|
||||||
@@ -45,6 +55,8 @@ export default function deleteArticleProperty(provider) {
|
|||||||
name: prop.name,
|
name: prop.name,
|
||||||
value: prop.value,
|
value: prop.value,
|
||||||
});
|
});
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ import {
|
|||||||
import {
|
import {
|
||||||
GET_BY_COMPANY_AND_ID as SQLITE_GET_PROP,
|
GET_BY_COMPANY_AND_ID as SQLITE_GET_PROP,
|
||||||
} from '../../providers/sqlite3/queries/propertyname.js';
|
} from '../../providers/sqlite3/queries/propertyname.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import { recordPropertyChangeHistory } from '../articlehistory/record.js';
|
import { recordPropertyChangeHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -22,6 +30,8 @@ export default function setByArticleSku(provider) {
|
|||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||||
const getPropSql = isSqlite ? SQLITE_GET_PROP : MSSQL_GET_PROP;
|
const getPropSql = isSqlite ? SQLITE_GET_PROP : MSSQL_GET_PROP;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces all properties for an article by its SKU.
|
* Replaces all properties for an article by its SKU.
|
||||||
@@ -124,6 +134,9 @@ export default function setByArticleSku(provider) {
|
|||||||
newProps: validated,
|
newProps: validated,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return inserted;
|
return inserted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import taxEnsure from '../tax/ensure.js';
|
import taxEnsure from '../tax/ensure.js';
|
||||||
import {
|
import {
|
||||||
@@ -17,6 +25,8 @@ export default function create(provider) {
|
|||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns a supplier to an article, optionally creating a purchase price.
|
* Assigns a supplier to an article, optionally creating a purchase price.
|
||||||
@@ -161,6 +171,9 @@ export default function create(provider) {
|
|||||||
pu: actualPu,
|
pu: actualPu,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return shapeArticleSupplier(supplierRow);
|
return shapeArticleSupplier(supplierRow);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import { recordSupplierDeleteHistory } from '../articlehistory/record.js';
|
import { recordSupplierDeleteHistory } from '../articlehistory/record.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -8,6 +16,8 @@ export default function del(provider) {
|
|||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a supplier assignment and cleans up its associated purchase price.
|
* Deletes a supplier assignment and cleans up its associated purchase price.
|
||||||
@@ -59,6 +69,9 @@ export default function del(provider) {
|
|||||||
supplierName,
|
supplierName,
|
||||||
supplierSku: existing.sku,
|
supplierSku: existing.sku,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
@@ -7,6 +15,8 @@ export default function order(provider) {
|
|||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reorders the supplier assignments of an article by its SKU.
|
* Reorders the supplier assignments of an article by its SKU.
|
||||||
@@ -65,6 +75,9 @@ export default function order(provider) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return { ids };
|
return { ids };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import taxEnsure from '../tax/ensure.js';
|
import taxEnsure from '../tax/ensure.js';
|
||||||
import {
|
import {
|
||||||
@@ -16,6 +24,8 @@ export default function update(provider) {
|
|||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing supplier assignment and its associated purchase price.
|
* Updates an existing supplier assignment and its associated purchase price.
|
||||||
@@ -218,6 +228,9 @@ export default function update(provider) {
|
|||||||
supplierName,
|
supplierName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
const loadRes = await runner.query(queries.GET_BY_ID_AND_ARTICLE_ID, {
|
const loadRes = await runner.query(queries.GET_BY_ID_AND_ARTICLE_ID, {
|
||||||
id,
|
id,
|
||||||
articleId,
|
articleId,
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as MSSQL_TOUCH_STUECKLISTE,
|
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as MSSQL_TOUCH_STUECKLISTE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_STUECKLISTE_ARTICLES_SYNC as MSSQL_ENQUEUE_STUECKLISTE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as SQLITE_TOUCH_STUECKLISTE,
|
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as SQLITE_TOUCH_STUECKLISTE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_STUECKLISTE_ARTICLES_SYNC as SQLITE_ENQUEUE_STUECKLISTE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,8 +158,12 @@ export async function syncArticleWarehouseSummaryForLedger(runner, { companyId,
|
|||||||
|
|
||||||
const touchSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
const enqueueStuecklisteSyncSql = isSqlite ? SQLITE_ENQUEUE_STUECKLISTE_SYNC : MSSQL_ENQUEUE_STUECKLISTE_SYNC;
|
||||||
await runner.query(touchSql, { articleId });
|
await runner.query(touchSql, { articleId });
|
||||||
await runner.query(touchStuecklisteSql, { articleId });
|
await runner.query(touchStuecklisteSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
await runner.query(enqueueStuecklisteSyncSql, { articleId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,51 @@ export default function update(provider) {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value !== existing.rows[0].value || sort !== existing.rows[0].sort) {
|
||||||
|
const touchSql = isSqlite
|
||||||
|
? `UPDATE article SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
||||||
|
WHERE company_id = @companyId
|
||||||
|
AND (
|
||||||
|
id IN (SELECT article_id FROM articleattributevalue WHERE attributevalue_id = @valId)
|
||||||
|
OR id IN (
|
||||||
|
SELECT a.parentarticle_id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN articleattributevalue aav ON aav.article_id = a.id
|
||||||
|
WHERE aav.attributevalue_id = @valId AND a.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
)`
|
||||||
|
: `UPDATE article SET updated_at = SYSUTCDATETIME()
|
||||||
|
WHERE company_id = @companyId
|
||||||
|
AND (
|
||||||
|
id IN (SELECT article_id FROM articleattributevalue WHERE attributevalue_id = @valId)
|
||||||
|
OR id IN (
|
||||||
|
SELECT a.parentarticle_id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN articleattributevalue aav ON aav.article_id = a.id
|
||||||
|
WHERE aav.attributevalue_id = @valId AND a.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
)`;
|
||||||
|
await runner.query(touchSql, { valId, companyId });
|
||||||
|
|
||||||
|
const enqueueSql = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.company_id = @companyId
|
||||||
|
AND (
|
||||||
|
a.id IN (SELECT article_id FROM articleattributevalue WHERE attributevalue_id = @valId)
|
||||||
|
OR a.id IN (
|
||||||
|
SELECT child.parentarticle_id
|
||||||
|
FROM article child
|
||||||
|
INNER JOIN articleattributevalue aav ON aav.article_id = child.id
|
||||||
|
WHERE aav.attributevalue_id = @valId AND child.parentarticle_id IS NOT NULL
|
||||||
|
)
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
await runner.query(enqueueSql, { valId, companyId });
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: valId,
|
id: valId,
|
||||||
attributeId: existing.rows[0].attributeId,
|
attributeId: existing.rows[0].attributeId,
|
||||||
|
|||||||
@@ -78,6 +78,15 @@ export default function update(provider) {
|
|||||||
: 'UPDATE article SET updated_at = SYSUTCDATETIME() WHERE brand_id = @brandId AND company_id = @companyId';
|
: 'UPDATE article SET updated_at = SYSUTCDATETIME() WHERE brand_id = @brandId AND company_id = @companyId';
|
||||||
const touched = await runner.query(touchSql, { brandId: numericId, companyId });
|
const touched = await runner.query(touchSql, { brandId: numericId, companyId });
|
||||||
touchedArticleCount = touched.rowsAffected ?? 0;
|
touchedArticleCount = touched.rowsAffected ?? 0;
|
||||||
|
|
||||||
|
const enqueueSql = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.brand_id = @brandId AND a.company_id = @companyId
|
||||||
|
`;
|
||||||
|
await runner.query(enqueueSql, { brandId: numericId, companyId });
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import { CREATE as SQLITE_CREATE_PIC } from '../../providers/sqlite3/queries/pic
|
|||||||
import processAvifImage from '../../util/processAvifImage.js';
|
import processAvifImage from '../../util/processAvifImage.js';
|
||||||
import newFullHash from '../../util/newFullHash.js';
|
import newFullHash from '../../util/newFullHash.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function addImage(provider) {
|
export default function addImage(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
|
||||||
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
||||||
@@ -42,7 +44,7 @@ export default function addImage(provider) {
|
|||||||
const fullHash = newFullHash(processed.full.buffer);
|
const fullHash = newFullHash(processed.full.buffer);
|
||||||
|
|
||||||
const runAdd = async (runner) => {
|
const runAdd = async (runner) => {
|
||||||
await access(googleAuthId, categoryId, runner);
|
const { companyId } = await access(googleAuthId, categoryId, runner);
|
||||||
|
|
||||||
const sortResult = await runner.query(getSortSql, { categoryId });
|
const sortResult = await runner.query(getSortSql, { categoryId });
|
||||||
const sort = sortResult.rows[0].sort;
|
const sort = sortResult.rows[0].sort;
|
||||||
@@ -95,6 +97,7 @@ export default function addImage(provider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryId }, runner);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: categoryId,
|
id: categoryId,
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ import {
|
|||||||
import { CREATE as MSSQL_CREATE_CATEGORYTEXT } from '../../providers/mssql/queries/categorytext.js';
|
import { CREATE as MSSQL_CREATE_CATEGORYTEXT } from '../../providers/mssql/queries/categorytext.js';
|
||||||
import { CREATE as SQLITE_CREATE_CATEGORYTEXT } from '../../providers/sqlite3/queries/categorytext.js';
|
import { CREATE as SQLITE_CREATE_CATEGORYTEXT } from '../../providers/sqlite3/queries/categorytext.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import slugify from '../slugify.js';
|
import slugify from '../slugify.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function createUnderParent(provider) {
|
export default function createUnderParent(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
|
||||||
const getSortSql = isSqlite
|
const getSortSql = isSqlite
|
||||||
@@ -40,7 +42,7 @@ export default function createUnderParent(provider) {
|
|||||||
*/
|
*/
|
||||||
return async ({ googleAuthId, parentId, name }, tx) => {
|
return async ({ googleAuthId, parentId, name }, tx) => {
|
||||||
const runCreate = async (runner) => {
|
const runCreate = async (runner) => {
|
||||||
const { languageId } = await access(googleAuthId, parentId, runner);
|
const { languageId, companyId } = await access(googleAuthId, parentId, runner);
|
||||||
|
|
||||||
const sortResult = await runner.query(getSortSql, { parentId });
|
const sortResult = await runner.query(getSortSql, { parentId });
|
||||||
const sort = sortResult.rows[0].sort;
|
const sort = sortResult.rows[0].sort;
|
||||||
@@ -60,6 +62,8 @@ export default function createUnderParent(provider) {
|
|||||||
slug,
|
slug,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: id }, runner);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
parentId,
|
parentId,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { DELETE_BY_CATEGORY as MSSQL_DELETE } from '../../providers/mssql/queries/categorypic.js';
|
import { DELETE_BY_CATEGORY as MSSQL_DELETE } from '../../providers/mssql/queries/categorypic.js';
|
||||||
import { DELETE_BY_CATEGORY as SQLITE_DELETE } from '../../providers/sqlite3/queries/categorypic.js';
|
import { DELETE_BY_CATEGORY as SQLITE_DELETE } from '../../providers/sqlite3/queries/categorypic.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function deleteImage(provider) {
|
export default function deleteImage(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const touchSql = isSqlite
|
const touchSql = isSqlite
|
||||||
@@ -26,7 +28,7 @@ export default function deleteImage(provider) {
|
|||||||
*/
|
*/
|
||||||
return async (googleAuthId, categoryId, tx) => {
|
return async (googleAuthId, categoryId, tx) => {
|
||||||
const runner = makeRunner(provider, tx);
|
const runner = makeRunner(provider, tx);
|
||||||
await access(googleAuthId, categoryId, runner);
|
const { companyId } = await access(googleAuthId, categoryId, runner);
|
||||||
|
|
||||||
const result = await runner.query(sql, { categoryId });
|
const result = await runner.query(sql, { categoryId });
|
||||||
|
|
||||||
@@ -35,6 +37,7 @@ export default function deleteImage(provider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryId }, runner);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: categoryId,
|
id: categoryId,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
import { CREATE as MSSQL_CREATE_CATEGORYTEXT } from '../../providers/mssql/queries/categorytext.js';
|
import { CREATE as MSSQL_CREATE_CATEGORYTEXT } from '../../providers/mssql/queries/categorytext.js';
|
||||||
import { CREATE as SQLITE_CREATE_CATEGORYTEXT } from '../../providers/sqlite3/queries/categorytext.js';
|
import { CREATE as SQLITE_CREATE_CATEGORYTEXT } from '../../providers/sqlite3/queries/categorytext.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import slugify from '../slugify.js';
|
import slugify from '../slugify.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ export function splitPath(path) {
|
|||||||
|
|
||||||
export default function ensureByPath(provider) {
|
export default function ensureByPath(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
|
||||||
const getSortSql = isSqlite
|
const getSortSql = isSqlite
|
||||||
@@ -61,7 +63,7 @@ export default function ensureByPath(provider) {
|
|||||||
|
|
||||||
let currentId = parentId;
|
let currentId = parentId;
|
||||||
|
|
||||||
const createCategory = async (runner, parentId, name, languageId) => {
|
const createCategory = async (runner, parentId, name, languageId, companyId) => {
|
||||||
const sortResult = await runner.query(getSortSql, { parentId });
|
const sortResult = await runner.query(getSortSql, { parentId });
|
||||||
const sort = sortResult.rows[0].sort;
|
const sort = sortResult.rows[0].sort;
|
||||||
const slug = slugify(name);
|
const slug = slugify(name);
|
||||||
@@ -79,11 +81,13 @@ export default function ensureByPath(provider) {
|
|||||||
slug,
|
slug,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: id }, runner);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const name of names) {
|
for (const name of names) {
|
||||||
const { languageId } = await access(googleAuthId, currentId, tx);
|
const { languageId, companyId } = await access(googleAuthId, currentId, tx);
|
||||||
|
|
||||||
const existing = await makeRunner(provider, tx).query(getByNameSql, {
|
const existing = await makeRunner(provider, tx).query(getByNameSql, {
|
||||||
parentId: currentId,
|
parentId: currentId,
|
||||||
@@ -98,17 +102,17 @@ export default function ensureByPath(provider) {
|
|||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
// Run within the caller's transaction (e.g. article import row).
|
// Run within the caller's transaction (e.g. article import row).
|
||||||
currentId = await createCategory(makeRunner(provider, tx), currentId, name, languageId);
|
currentId = await createCategory(makeRunner(provider, tx), currentId, name, languageId, companyId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standalone use: own transaction per created category.
|
// Standalone use: own transaction per created category.
|
||||||
if (typeof provider?.transaction === 'function') {
|
if (typeof provider?.transaction === 'function') {
|
||||||
currentId = await provider.transaction((runner) =>
|
currentId = await provider.transaction((runner) =>
|
||||||
createCategory(runner, currentId, name, languageId),
|
createCategory(runner, currentId, name, languageId, companyId),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
currentId = await createCategory(makeRunner(provider), currentId, name, languageId);
|
currentId = await createCategory(makeRunner(provider), currentId, name, languageId, companyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import {
|
|||||||
MOVE as MSSQL_MOVE,
|
MOVE as MSSQL_MOVE,
|
||||||
TOUCH_SUBTREE_CATEGORIES as MSSQL_TOUCH_SUBTREE_CATEGORIES,
|
TOUCH_SUBTREE_CATEGORIES as MSSQL_TOUCH_SUBTREE_CATEGORIES,
|
||||||
TOUCH_SUBTREE_ARTICLES as MSSQL_TOUCH_SUBTREE_ARTICLES,
|
TOUCH_SUBTREE_ARTICLES as MSSQL_TOUCH_SUBTREE_ARTICLES,
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as MSSQL_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as MSSQL_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
} from '../../providers/mssql/queries/category.js';
|
} from '../../providers/mssql/queries/category.js';
|
||||||
import {
|
import {
|
||||||
GET_NEXT_SIBLING_SORT as SQLITE_GET_NEXT_SIBLING_SORT,
|
GET_NEXT_SIBLING_SORT as SQLITE_GET_NEXT_SIBLING_SORT,
|
||||||
@@ -11,6 +13,8 @@ import {
|
|||||||
MOVE as SQLITE_MOVE,
|
MOVE as SQLITE_MOVE,
|
||||||
TOUCH_SUBTREE_CATEGORIES as SQLITE_TOUCH_SUBTREE_CATEGORIES,
|
TOUCH_SUBTREE_CATEGORIES as SQLITE_TOUCH_SUBTREE_CATEGORIES,
|
||||||
TOUCH_SUBTREE_ARTICLES as SQLITE_TOUCH_SUBTREE_ARTICLES,
|
TOUCH_SUBTREE_ARTICLES as SQLITE_TOUCH_SUBTREE_ARTICLES,
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as SQLITE_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as SQLITE_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
} from '../../providers/sqlite3/queries/category.js';
|
} from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -30,6 +34,12 @@ export default function move(provider) {
|
|||||||
const touchArticlesSql = isSqlite
|
const touchArticlesSql = isSqlite
|
||||||
? SQLITE_TOUCH_SUBTREE_ARTICLES
|
? SQLITE_TOUCH_SUBTREE_ARTICLES
|
||||||
: MSSQL_TOUCH_SUBTREE_ARTICLES;
|
: MSSQL_TOUCH_SUBTREE_ARTICLES;
|
||||||
|
const enqueueCategoriesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_CATEGORIES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_CATEGORIES;
|
||||||
|
const enqueueArticlesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_ARTICLES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_ARTICLES;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a category to a new parent, preventing cycles and cross-company moves.
|
* Moves a category to a new parent, preventing cycles and cross-company moves.
|
||||||
@@ -82,6 +92,8 @@ export default function move(provider) {
|
|||||||
|
|
||||||
await runner.query(touchCategoriesSql, { id });
|
await runner.query(touchCategoriesSql, { id });
|
||||||
await runner.query(touchArticlesSql, { id });
|
await runner.query(touchArticlesSql, { id });
|
||||||
|
await runner.query(enqueueCategoriesSql, { id, companyId: source.companyId });
|
||||||
|
await runner.query(enqueueArticlesSql, { id, companyId: source.companyId });
|
||||||
|
|
||||||
return { id, parentId, sort };
|
return { id, parentId, sort };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import {
|
|||||||
UPDATE_SORT as SQLITE_UPDATE_SORT,
|
UPDATE_SORT as SQLITE_UPDATE_SORT,
|
||||||
} from '../../providers/sqlite3/queries/category.js';
|
} from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function order(provider) {
|
export default function order(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const listChildIdsSql = isSqlite
|
const listChildIdsSql = isSqlite
|
||||||
? SQLITE_LIST_CHILD_IDS
|
? SQLITE_LIST_CHILD_IDS
|
||||||
@@ -39,7 +41,7 @@ export default function order(provider) {
|
|||||||
|
|
||||||
const runOrder = async (runner) => {
|
const runOrder = async (runner) => {
|
||||||
// Auth + ensures parentId is a real category of the user's company.
|
// Auth + ensures parentId is a real category of the user's company.
|
||||||
await access(googleAuthId, parentId, runner);
|
const { companyId } = await access(googleAuthId, parentId, runner);
|
||||||
|
|
||||||
const children = await runner.query(listChildIdsSql, { parentId });
|
const children = await runner.query(listChildIdsSql, { parentId });
|
||||||
|
|
||||||
@@ -63,6 +65,7 @@ export default function order(provider) {
|
|||||||
parentId,
|
parentId,
|
||||||
sort,
|
sort,
|
||||||
});
|
});
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryIds[sort] }, runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { categoryIds };
|
return { categoryIds };
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { UPDATE_BY_CATEGORY_AND_LANGUAGE as MSSQL_UPDATE } from '../../providers/mssql/queries/categorytext.js';
|
import { UPDATE_BY_CATEGORY_AND_LANGUAGE as MSSQL_UPDATE } from '../../providers/mssql/queries/categorytext.js';
|
||||||
import { UPDATE_BY_CATEGORY_AND_LANGUAGE as SQLITE_UPDATE } from '../../providers/sqlite3/queries/categorytext.js';
|
import { UPDATE_BY_CATEGORY_AND_LANGUAGE as SQLITE_UPDATE } from '../../providers/sqlite3/queries/categorytext.js';
|
||||||
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
import resolveCategoryAccess from './resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import slugify from '../slugify.js';
|
import slugify from '../slugify.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function rename(provider) {
|
export default function rename(provider) {
|
||||||
const access = resolveCategoryAccess(provider);
|
const access = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_UPDATE : MSSQL_UPDATE;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const touchSql = isSqlite
|
const touchSql = isSqlite
|
||||||
@@ -33,7 +35,7 @@ export default function rename(provider) {
|
|||||||
}
|
}
|
||||||
const cleaned = name.trim();
|
const cleaned = name.trim();
|
||||||
|
|
||||||
const { languageId } = await access(googleAuthId, id, tx);
|
const { languageId, companyId } = await access(googleAuthId, id, tx);
|
||||||
|
|
||||||
const slug = slugify(cleaned);
|
const slug = slugify(cleaned);
|
||||||
|
|
||||||
@@ -50,6 +52,7 @@ export default function rename(provider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await runner.query(touchSql, { categoryId: id });
|
await runner.query(touchSql, { categoryId: id });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: id }, runner);
|
||||||
|
|
||||||
return { id, name: cleaned, slug };
|
return { id, name: cleaned, slug };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ import {
|
|||||||
GET_VALUE_DETAIL as SQLITE_GET_DETAIL,
|
GET_VALUE_DETAIL as SQLITE_GET_DETAIL,
|
||||||
} from '../../providers/sqlite3/queries/categoryattributevalue.js';
|
} from '../../providers/sqlite3/queries/categoryattributevalue.js';
|
||||||
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function setByCategoryId(provider) {
|
export default function setByCategoryId(provider) {
|
||||||
const resolve = resolveCategoryAccess(provider);
|
const resolve = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||||
@@ -140,6 +142,7 @@ export default function setByCategoryId(provider) {
|
|||||||
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
||||||
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryId }, runner);
|
||||||
|
|
||||||
return inserted;
|
return inserted;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ import {
|
|||||||
DELETE_BY_CATEGORY_AND_PROPERTY_ID as SQLITE_DELETE,
|
DELETE_BY_CATEGORY_AND_PROPERTY_ID as SQLITE_DELETE,
|
||||||
} from '../../providers/sqlite3/queries/categoryproperty.js';
|
} from '../../providers/sqlite3/queries/categoryproperty.js';
|
||||||
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function deleteCategoryProperty(provider) {
|
export default function deleteCategoryProperty(provider) {
|
||||||
const resolve = resolveCategoryAccess(provider);
|
const resolve = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ export default function deleteCategoryProperty(provider) {
|
|||||||
*/
|
*/
|
||||||
return async (googleAuthId, categoryId, propertyId, tx) => {
|
return async (googleAuthId, categoryId, propertyId, tx) => {
|
||||||
const runner = makeRunner(provider, tx);
|
const runner = makeRunner(provider, tx);
|
||||||
await resolve(googleAuthId, categoryId, runner);
|
const { companyId } = await resolve(googleAuthId, categoryId, runner);
|
||||||
|
|
||||||
await runner.query(deleteSql, { categoryId, propertyId });
|
await runner.query(deleteSql, { categoryId, propertyId });
|
||||||
|
|
||||||
@@ -32,5 +34,6 @@ export default function deleteCategoryProperty(provider) {
|
|||||||
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
||||||
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryId }, runner);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ import {
|
|||||||
GET_BY_COMPANY_AND_ID as SQLITE_GET_PROP,
|
GET_BY_COMPANY_AND_ID as SQLITE_GET_PROP,
|
||||||
} from '../../providers/sqlite3/queries/propertyname.js';
|
} from '../../providers/sqlite3/queries/propertyname.js';
|
||||||
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function setByCategoryId(provider) {
|
export default function setByCategoryId(provider) {
|
||||||
const resolve = resolveCategoryAccess(provider);
|
const resolve = resolveCategoryAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||||
@@ -102,6 +104,7 @@ export default function setByCategoryId(provider) {
|
|||||||
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
? "UPDATE category SET updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = @categoryId"
|
||||||
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
: 'UPDATE category SET updated_at = SYSUTCDATETIME() WHERE id = @categoryId';
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
|
await recordSync({ companyId, entityType: 'category', entityId: categoryId }, runner);
|
||||||
|
|
||||||
return inserted;
|
return inserted;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '../../providers/sqlite3/queries/customergroup.js';
|
} from '../../providers/sqlite3/queries/customergroup.js';
|
||||||
import { POS_GROUP_NAME, SUPPLIER_GROUP_NAME } from '../../providers/mssql/queries/entity.js';
|
import { POS_GROUP_NAME, SUPPLIER_GROUP_NAME } from '../../providers/mssql/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
const RESERVED_NAMES = new Set([POS_GROUP_NAME, SUPPLIER_GROUP_NAME]);
|
const RESERVED_NAMES = new Set([POS_GROUP_NAME, SUPPLIER_GROUP_NAME]);
|
||||||
@@ -18,6 +19,7 @@ function shape(row) {
|
|||||||
|
|
||||||
export default function create(provider) {
|
export default function create(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
||||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||||
@@ -58,6 +60,7 @@ export default function create(provider) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const row = result.rows[0] ?? { id: result.insertId, name: cleaned, sort };
|
const row = result.rows[0] ?? { id: result.insertId, name: cleaned, sort };
|
||||||
|
await recordSync({ companyId, entityType: 'customergroup', entityId: row.id }, runner);
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import {
|
|||||||
UPDATE_SORT as SQLITE_UPDATE_SORT,
|
UPDATE_SORT as SQLITE_UPDATE_SORT,
|
||||||
} from '../../providers/sqlite3/queries/customergroup.js';
|
} from '../../providers/sqlite3/queries/customergroup.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function order(provider) {
|
export default function order(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const listIdsSql = isSqlite
|
const listIdsSql = isSqlite
|
||||||
? SQLITE_LIST_IDS_BY_COMPANY
|
? SQLITE_LIST_IDS_BY_COMPANY
|
||||||
@@ -65,6 +67,7 @@ export default function order(provider) {
|
|||||||
companyId,
|
companyId,
|
||||||
sort,
|
sort,
|
||||||
});
|
});
|
||||||
|
await recordSync({ companyId, entityType: 'customergroup', entityId: customergroupIds[sort] }, runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { customergroupIds };
|
return { customergroupIds };
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '../../providers/sqlite3/queries/customergroup.js';
|
} from '../../providers/sqlite3/queries/customergroup.js';
|
||||||
import { POS_GROUP_NAME, SUPPLIER_GROUP_NAME } from '../../providers/mssql/queries/entity.js';
|
import { POS_GROUP_NAME, SUPPLIER_GROUP_NAME } from '../../providers/mssql/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
const LOCKED_NAMES = new Set([POS_GROUP_NAME, SUPPLIER_GROUP_NAME]);
|
const LOCKED_NAMES = new Set([POS_GROUP_NAME, SUPPLIER_GROUP_NAME]);
|
||||||
@@ -18,6 +19,7 @@ function shape(row) {
|
|||||||
|
|
||||||
export default function update(provider) {
|
export default function update(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSql = isSqlite
|
const getSql = isSqlite
|
||||||
? SQLITE_GET_BY_COMPANY_AND_ID
|
? SQLITE_GET_BY_COMPANY_AND_ID
|
||||||
@@ -70,6 +72,7 @@ export default function update(provider) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const row = result.rows[0] ?? { id, name: cleaned, sort: current.sort };
|
const row = result.rows[0] ?? { id, name: cleaned, sort: current.sort };
|
||||||
|
await recordSync({ companyId, entityType: 'customergroup', entityId: id }, runner);
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries
|
|||||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveCustomerGroupAccess from '../customergroup/resolveCustomerGroupAccess.js';
|
import resolveCustomerGroupAccess from '../customergroup/resolveCustomerGroupAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import nextNumber from '../numbers/nextNumber.js';
|
import nextNumber from '../numbers/nextNumber.js';
|
||||||
import shape from './shape.js';
|
import shape from './shape.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -12,6 +13,7 @@ import makeRunner from '../runner.js';
|
|||||||
export default function create(provider) {
|
export default function create(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const groupAccess = resolveCustomerGroupAccess(provider);
|
const groupAccess = resolveCustomerGroupAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const allocateNumber = nextNumber(provider);
|
const allocateNumber = nextNumber(provider);
|
||||||
|
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
@@ -82,6 +84,8 @@ export default function create(provider) {
|
|||||||
text: 'Erstellt',
|
text: 'Erstellt',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId: row.id }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isUniqueConstraintError(err)) {
|
if (isUniqueConstraintError(err)) {
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/en
|
|||||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/entityhistory.js';
|
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/entityhistory.js';
|
||||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import shape from './shape.js';
|
import shape from './shape.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function update(provider) {
|
export default function update(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSql = isSqlite
|
const getSql = isSqlite
|
||||||
? SQLITE_GET_BY_COMPANY_AND_ID
|
? SQLITE_GET_BY_COMPANY_AND_ID
|
||||||
@@ -134,6 +136,8 @@ export default function update(provider) {
|
|||||||
text: historyLines.join('\n'),
|
text: historyLines.join('\n'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId: id }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isUniqueConstraintError(err)) {
|
if (isUniqueConstraintError(err)) {
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ import {
|
|||||||
CREATE as SQLITE_CREATE,
|
CREATE as SQLITE_CREATE,
|
||||||
GET_NEXT_SORT as SQLITE_GET_NEXT_SORT,
|
GET_NEXT_SORT as SQLITE_GET_NEXT_SORT,
|
||||||
} from '../../providers/sqlite3/queries/entityaddress.js';
|
} from '../../providers/sqlite3/queries/entityaddress.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
function shape(row) {
|
function shape(row) {
|
||||||
@@ -35,9 +38,11 @@ function optionalString(value) {
|
|||||||
export default function create(provider) {
|
export default function create(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
||||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new address for an entity.
|
* Creates a new address for an entity.
|
||||||
@@ -109,6 +114,9 @@ export default function create(provider) {
|
|||||||
sort,
|
sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { DELETE_BY_ENTITY_AND_ID as MSSQL_DELETE } from '../../providers/mssql/queries/entityaddress.js';
|
import { DELETE_BY_ENTITY_AND_ID as MSSQL_DELETE } from '../../providers/mssql/queries/entityaddress.js';
|
||||||
import { DELETE_BY_ENTITY_AND_ID as SQLITE_DELETE } from '../../providers/sqlite3/queries/entityaddress.js';
|
import { DELETE_BY_ENTITY_AND_ID as SQLITE_DELETE } from '../../providers/sqlite3/queries/entityaddress.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function del(provider) {
|
export default function del(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
const recordSync = recordSyncQueue(provider);
|
||||||
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
const sql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an address of an entity.
|
* Deletes an address of an entity.
|
||||||
@@ -39,5 +45,8 @@ export default function del(provider) {
|
|||||||
if (!result.rowsAffected) {
|
if (!result.rowsAffected) {
|
||||||
throw new Error('Address not found');
|
throw new Error('Address not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ import {
|
|||||||
GET_BY_ENTITY_AND_ID as SQLITE_GET_BY_ENTITY_AND_ID,
|
GET_BY_ENTITY_AND_ID as SQLITE_GET_BY_ENTITY_AND_ID,
|
||||||
UPDATE as SQLITE_UPDATE,
|
UPDATE as SQLITE_UPDATE,
|
||||||
} from '../../providers/sqlite3/queries/entityaddress.js';
|
} from '../../providers/sqlite3/queries/entityaddress.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
function shape(row) {
|
function shape(row) {
|
||||||
@@ -35,11 +38,13 @@ function optionalString(value) {
|
|||||||
export default function update(provider) {
|
export default function update(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSql = isSqlite
|
const getSql = isSqlite
|
||||||
? SQLITE_GET_BY_ENTITY_AND_ID
|
? SQLITE_GET_BY_ENTITY_AND_ID
|
||||||
: MSSQL_GET_BY_ENTITY_AND_ID;
|
: MSSQL_GET_BY_ENTITY_AND_ID;
|
||||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an address of an entity.
|
* Updates an address of an entity.
|
||||||
@@ -152,6 +157,9 @@ export default function update(provider) {
|
|||||||
sort,
|
sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ import {
|
|||||||
CREATE as SQLITE_CREATE,
|
CREATE as SQLITE_CREATE,
|
||||||
GET_NEXT_SORT as SQLITE_GET_NEXT_SORT,
|
GET_NEXT_SORT as SQLITE_GET_NEXT_SORT,
|
||||||
} from '../../providers/sqlite3/queries/entitycontact.js';
|
} from '../../providers/sqlite3/queries/entitycontact.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
function shape(row) {
|
function shape(row) {
|
||||||
@@ -23,9 +26,11 @@ function shape(row) {
|
|||||||
export default function create(provider) {
|
export default function create(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
|
||||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new contact for an entity.
|
* Creates a new contact for an entity.
|
||||||
@@ -80,6 +85,9 @@ export default function create(provider) {
|
|||||||
sort,
|
sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { DELETE_BY_ENTITY_AND_ID as MSSQL_DELETE } from '../../providers/mssql/queries/entitycontact.js';
|
import { DELETE_BY_ENTITY_AND_ID as MSSQL_DELETE } from '../../providers/mssql/queries/entitycontact.js';
|
||||||
import { DELETE_BY_ENTITY_AND_ID as SQLITE_DELETE } from '../../providers/sqlite3/queries/entitycontact.js';
|
import { DELETE_BY_ENTITY_AND_ID as SQLITE_DELETE } from '../../providers/sqlite3/queries/entitycontact.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function del(provider) {
|
export default function del(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
const recordSync = recordSyncQueue(provider);
|
||||||
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
|
const sql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a contact of an entity.
|
* Deletes a contact of an entity.
|
||||||
@@ -39,5 +45,8 @@ export default function del(provider) {
|
|||||||
if (!result.rowsAffected) {
|
if (!result.rowsAffected) {
|
||||||
throw new Error('Contact not found');
|
throw new Error('Contact not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ import {
|
|||||||
GET_BY_ENTITY_AND_ID as SQLITE_GET_BY_ENTITY_AND_ID,
|
GET_BY_ENTITY_AND_ID as SQLITE_GET_BY_ENTITY_AND_ID,
|
||||||
UPDATE as SQLITE_UPDATE,
|
UPDATE as SQLITE_UPDATE,
|
||||||
} from '../../providers/sqlite3/queries/entitycontact.js';
|
} from '../../providers/sqlite3/queries/entitycontact.js';
|
||||||
|
import { TOUCH_UPDATED_AT as MSSQL_TOUCH_ENTITY } from '../../providers/mssql/queries/entity.js';
|
||||||
|
import { TOUCH_UPDATED_AT as SQLITE_TOUCH_ENTITY } from '../../providers/sqlite3/queries/entity.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
import recordSyncQueue from '../posterminal/recordSyncQueue.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
function shape(row) {
|
function shape(row) {
|
||||||
@@ -23,11 +26,13 @@ function shape(row) {
|
|||||||
export default function update(provider) {
|
export default function update(provider) {
|
||||||
const access = resolveSelectedCompanyAccess(provider);
|
const access = resolveSelectedCompanyAccess(provider);
|
||||||
const entityAccess = resolveEntityAccess(provider);
|
const entityAccess = resolveEntityAccess(provider);
|
||||||
|
const recordSync = recordSyncQueue(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const getSql = isSqlite
|
const getSql = isSqlite
|
||||||
? SQLITE_GET_BY_ENTITY_AND_ID
|
? SQLITE_GET_BY_ENTITY_AND_ID
|
||||||
: MSSQL_GET_BY_ENTITY_AND_ID;
|
: MSSQL_GET_BY_ENTITY_AND_ID;
|
||||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||||
|
const touchEntitySql = isSqlite ? SQLITE_TOUCH_ENTITY : MSSQL_TOUCH_ENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a contact of an entity.
|
* Updates a contact of an entity.
|
||||||
@@ -100,6 +105,9 @@ export default function update(provider) {
|
|||||||
sort,
|
sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await runner.query(touchEntitySql, { id: entityId });
|
||||||
|
await recordSync({ companyId, entityType: 'customer', entityId }, runner);
|
||||||
|
|
||||||
return shape(row);
|
return shape(row);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ import makeRunner from '../runner.js';
|
|||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as MSSQL_TOUCH_STUECKLISTE,
|
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as MSSQL_TOUCH_STUECKLISTE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_STUECKLISTE_ARTICLES_SYNC as MSSQL_ENQUEUE_STUECKLISTE_SYNC,
|
||||||
} from '../../providers/mssql/queries/article.js';
|
} from '../../providers/mssql/queries/article.js';
|
||||||
import {
|
import {
|
||||||
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as SQLITE_TOUCH_STUECKLISTE,
|
TOUCH_STUECKLISTE_ARTICLES_UPDATED_AT as SQLITE_TOUCH_STUECKLISTE,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
ENQUEUE_STUECKLISTE_ARTICLES_SYNC as SQLITE_ENQUEUE_STUECKLISTE_SYNC,
|
||||||
} from '../../providers/sqlite3/queries/article.js';
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
|
|
||||||
export const INIT_HASH = 'TODO_TSE_BASED_INITHASH';
|
export const INIT_HASH = 'TODO_TSE_BASED_INITHASH';
|
||||||
@@ -218,6 +222,12 @@ export default function add(provider) {
|
|||||||
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
||||||
await runner.query(touchSql, { articleId: match.id });
|
await runner.query(touchSql, { articleId: match.id });
|
||||||
await runner.query(touchStuecklisteSql, { articleId: match.id });
|
await runner.query(touchStuecklisteSql, { articleId: match.id });
|
||||||
|
if (!isTracked) {
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
const enqueueStuecklisteSyncSql = isSqlite ? SQLITE_ENQUEUE_STUECKLISTE_SYNC : MSSQL_ENQUEUE_STUECKLISTE_SYNC;
|
||||||
|
await runner.query(enqueueSyncSql, { articleId: match.id });
|
||||||
|
await runner.query(enqueueStuecklisteSyncSql, { articleId: match.id });
|
||||||
|
}
|
||||||
await recordAcceptanceHistory(runner, {
|
await recordAcceptanceHistory(runner, {
|
||||||
articleId: match.id,
|
articleId: match.id,
|
||||||
companyuserId,
|
companyuserId,
|
||||||
@@ -312,6 +322,12 @@ export default function add(provider) {
|
|||||||
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
const touchStuecklisteSql = isSqlite ? SQLITE_TOUCH_STUECKLISTE : MSSQL_TOUCH_STUECKLISTE;
|
||||||
await runner.query(touchSql, { articleId: match.id });
|
await runner.query(touchSql, { articleId: match.id });
|
||||||
await runner.query(touchStuecklisteSql, { articleId: match.id });
|
await runner.query(touchStuecklisteSql, { articleId: match.id });
|
||||||
|
if (!isTracked) {
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
const enqueueStuecklisteSyncSql = isSqlite ? SQLITE_ENQUEUE_STUECKLISTE_SYNC : MSSQL_ENQUEUE_STUECKLISTE_SYNC;
|
||||||
|
await runner.query(enqueueSyncSql, { articleId: match.id });
|
||||||
|
await runner.query(enqueueStuecklisteSyncSql, { articleId: match.id });
|
||||||
|
}
|
||||||
await recordShipmentHistory(runner, {
|
await recordShipmentHistory(runner, {
|
||||||
articleId: match.id,
|
articleId: match.id,
|
||||||
companyuserId,
|
companyuserId,
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import * as mssqlQueries from '../../providers/mssql/queries/optionslist.js';
|
import * as mssqlQueries from '../../providers/mssql/queries/optionslist.js';
|
||||||
import * as sqliteQueries from '../../providers/sqlite3/queries/optionslist.js';
|
import * as sqliteQueries from '../../providers/sqlite3/queries/optionslist.js';
|
||||||
import { TOUCH_UPDATED_AT as MSSQL_TOUCH } from '../../providers/mssql/queries/article.js';
|
import {
|
||||||
import { TOUCH_UPDATED_AT as SQLITE_TOUCH } from '../../providers/sqlite3/queries/article.js';
|
TOUCH_UPDATED_AT as MSSQL_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as MSSQL_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/mssql/queries/article.js';
|
||||||
|
import {
|
||||||
|
TOUCH_UPDATED_AT as SQLITE_TOUCH,
|
||||||
|
ENQUEUE_SYNC_BY_ARTICLE as SQLITE_ENQUEUE_SYNC,
|
||||||
|
} from '../../providers/sqlite3/queries/article.js';
|
||||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||||
import getOptionsByArticleSku from './getOptionsByArticleSku.js';
|
import getOptionsByArticleSku from './getOptionsByArticleSku.js';
|
||||||
import {
|
import {
|
||||||
@@ -49,6 +55,7 @@ export default function setOptionsByArticleSku(provider) {
|
|||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||||
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||||
|
const enqueueSyncSql = isSqlite ? SQLITE_ENQUEUE_SYNC : MSSQL_ENQUEUE_SYNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets or clears the options list for an article.
|
* Sets or clears the options list for an article.
|
||||||
@@ -112,6 +119,7 @@ export default function setOptionsByArticleSku(provider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -242,6 +250,7 @@ export default function setOptionsByArticleSku(provider) {
|
|||||||
|
|
||||||
// Touch article updated_at so POS and other consumers pick up options/deposit changes
|
// Touch article updated_at so POS and other consumers pick up options/deposit changes
|
||||||
await runner.query(touchArticleSql, { articleId });
|
await runner.query(touchArticleSql, { articleId });
|
||||||
|
await runner.query(enqueueSyncSql, { articleId });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCategoryCount(provider) {
|
export default function getCategoryCount(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts categories assigned to the POS terminal updated after the given unix timestamp cursor.
|
* Counts categories assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor of last update.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<number>} The count of changed records.
|
* @returns {Promise<number>} The count of changed records.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCategoryList(provider) {
|
export default function getCategoryList(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists categories for a POS terminal modified after the cursor.
|
* Lists categories for a POS terminal queued after the sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {number} [input.limit=20] - Max items to return.
|
* @param {number} [input.limit=20] - Max items to return.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<Array<object>>}
|
* @returns {Promise<Array<object>>}
|
||||||
|
|||||||
@@ -4,21 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
if (n < 1e11) return Math.floor(n * 1000000);
|
|
||||||
if (n < 1e14) return Math.floor((n / 1000) * 1000000);
|
|
||||||
return Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCompositeProductCount(provider) {
|
export default function getCompositeProductCount(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts composite products (Stücklisten) assigned to the POS terminal updated after the given unix timestamp cursor.
|
* Counts composite products (Stücklisten) assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor of last update.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<number>} The count of changed records.
|
* @returns {Promise<number>} The count of changed records.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCustomerCount(provider) {
|
export default function getCustomerCount(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts customers of the POS terminal company updated after the given unix timestamp cursor.
|
* Counts customers of the POS terminal company queued after the given sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor of last update.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<number>} The count of changed records.
|
* @returns {Promise<number>} The count of changed records.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCustomerGroupCount(provider) {
|
export default function getCustomerGroupCount(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts customer groups of the POS terminal company updated after the given unix timestamp cursor.
|
* Counts customer groups of the POS terminal company queued after the given sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor of last update.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<number>} The count of changed records.
|
* @returns {Promise<number>} The count of changed records.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCustomerGroupList(provider) {
|
export default function getCustomerGroupList(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists customer groups for a POS terminal modified after the cursor, excluding 'Lieferanten'.
|
* Lists customer groups for a POS terminal queued after the sync queue cursor ID, excluding 'Lieferanten'.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {number} [input.limit=50] - Max items to return.
|
* @param {number} [input.limit=50] - Max items to return.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<Array<{customerGroupId: string, name: string, standard: string, discountPercent: string, lastChanged: string}>>}
|
* @returns {Promise<Array<{customerGroupId: string, name: string, standard: string, discountPercent: string, lastChanged: string}>>}
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCustomerList(provider) {
|
export default function getCustomerList(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists customers for a POS terminal modified after the cursor, excluding 'Lieferanten'.
|
* Lists customers for a POS terminal queued after the sync queue cursor ID, excluding 'Lieferanten'.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {number} [input.limit=20] - Max items to return.
|
* @param {number} [input.limit=20] - Max items to return.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<Array<object>>}
|
* @returns {Promise<Array<object>>}
|
||||||
|
|||||||
@@ -4,21 +4,18 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
if (n < 1e11) return Math.floor(n * 1000000);
|
|
||||||
if (n < 1e14) return Math.floor((n / 1000) * 1000000);
|
|
||||||
return Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getProductCount(provider) {
|
export default function getProductCount(provider) {
|
||||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts products assigned to the POS terminal updated after the given unix timestamp cursor.
|
* Counts products assigned to the POS terminal queued after the given sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor of last update.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {object} [tx] - Optional transaction to run within.
|
* @param {object} [tx] - Optional transaction to run within.
|
||||||
* @returns {Promise<number>} The count of changed records.
|
* @returns {Promise<number>} The count of changed records.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ import makeRunner from '../runner.js';
|
|||||||
|
|
||||||
function normalizeCursor(cursor) {
|
function normalizeCursor(cursor) {
|
||||||
const n = Number(cursor) || 0;
|
const n = Number(cursor) || 0;
|
||||||
if (n <= 0) return 0;
|
return n > 0 ? Math.floor(n) : 0;
|
||||||
if (n < 1e11) return Math.floor(n * 1000000);
|
|
||||||
if (n < 1e14) return Math.floor((n / 1000) * 1000000);
|
|
||||||
return Math.floor(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDateTime(value) {
|
function formatDateTime(value) {
|
||||||
@@ -46,11 +43,11 @@ export default function getProductList(provider) {
|
|||||||
const parentOptionsSql = isSqlite ? SQLITE_PARENT_OPTIONS : MSSQL_PARENT_OPTIONS;
|
const parentOptionsSql = isSqlite ? SQLITE_PARENT_OPTIONS : MSSQL_PARENT_OPTIONS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists products for a POS terminal modified after the cursor.
|
* Lists products for a POS terminal queued after the sync queue cursor ID.
|
||||||
*
|
*
|
||||||
* @param {object} input
|
* @param {object} input
|
||||||
* @param {number} input.posterminalId - The POS terminal id.
|
* @param {number} input.posterminalId - The POS terminal id.
|
||||||
* @param {number} [input.cursor=0] - Unix timestamp cursor.
|
* @param {number} [input.cursor=0] - Sequential ID cursor of last synced posterminalsyncqueue entry.
|
||||||
* @param {number} [input.limit=20] - Max items to return.
|
* @param {number} [input.limit=20] - Max items to return.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<Array<object>>}
|
* @returns {Promise<Array<object>>}
|
||||||
|
|||||||
28
src/store/posterminal/recordSyncQueue.js
Normal file
28
src/store/posterminal/recordSyncQueue.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { RECORD_SYNC_QUEUE as MSSQL_SQL } from '../../providers/mssql/queries/posterminal.js';
|
||||||
|
import { RECORD_SYNC_QUEUE as SQLITE_SQL } from '../../providers/sqlite3/queries/posterminal.js';
|
||||||
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
|
export default function recordSyncQueue(provider) {
|
||||||
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues a sync notification for all POS terminals of a company.
|
||||||
|
*
|
||||||
|
* @param {object} input
|
||||||
|
* @param {number} input.companyId - The company id.
|
||||||
|
* @param {string} input.entityType - 'category' | 'article' | 'customer' | 'customergroup'
|
||||||
|
* @param {number} input.entityId - The entity's id.
|
||||||
|
* @param {object} [tx] - Optional transaction/runner.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
return async ({ companyId, entityType, entityId }, tx) => {
|
||||||
|
if (!companyId || !entityType || !entityId) return;
|
||||||
|
const runner = makeRunner(provider, tx);
|
||||||
|
await runner.query(sql, {
|
||||||
|
companyId: Number(companyId),
|
||||||
|
entityType: String(entityType).toLowerCase().trim(),
|
||||||
|
entityId: Number(entityId),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -8,6 +8,14 @@ import {
|
|||||||
SET_OFF as SQLITE_SET_OFF,
|
SET_OFF as SQLITE_SET_OFF,
|
||||||
LIST_CATEGORY_IDS as SQLITE_LIST_CATEGORY_IDS,
|
LIST_CATEGORY_IDS as SQLITE_LIST_CATEGORY_IDS,
|
||||||
} from '../../providers/sqlite3/queries/posterminal.js';
|
} from '../../providers/sqlite3/queries/posterminal.js';
|
||||||
|
import {
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as MSSQL_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as MSSQL_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
|
} from '../../providers/mssql/queries/category.js';
|
||||||
|
import {
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as SQLITE_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as SQLITE_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
|
} from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
@@ -20,6 +28,12 @@ export default function setOff(provider) {
|
|||||||
const listCatIdsSql = isSqlite
|
const listCatIdsSql = isSqlite
|
||||||
? SQLITE_LIST_CATEGORY_IDS
|
? SQLITE_LIST_CATEGORY_IDS
|
||||||
: MSSQL_LIST_CATEGORY_IDS;
|
: MSSQL_LIST_CATEGORY_IDS;
|
||||||
|
const enqueueCategoriesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_CATEGORIES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_CATEGORIES;
|
||||||
|
const enqueueArticlesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_ARTICLES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_ARTICLES;
|
||||||
|
|
||||||
const touchSql = isSqlite
|
const touchSql = isSqlite
|
||||||
? `WITH RECURSIVE cats AS (
|
? `WITH RECURSIVE cats AS (
|
||||||
@@ -182,6 +196,8 @@ export default function setOff(provider) {
|
|||||||
|
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
await runner.query(touchArticlesSql, { categoryId });
|
await runner.query(touchArticlesSql, { categoryId });
|
||||||
|
await runner.query(enqueueCategoriesSql, { id: categoryId, companyId });
|
||||||
|
await runner.query(enqueueArticlesSql, { id: categoryId, companyId });
|
||||||
|
|
||||||
const result = await runner.query(listCatIdsSql, { posterminalId });
|
const result = await runner.query(listCatIdsSql, { posterminalId });
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ import {
|
|||||||
SET_ON as SQLITE_SET_ON,
|
SET_ON as SQLITE_SET_ON,
|
||||||
LIST_CATEGORY_IDS as SQLITE_LIST_CATEGORY_IDS,
|
LIST_CATEGORY_IDS as SQLITE_LIST_CATEGORY_IDS,
|
||||||
} from '../../providers/sqlite3/queries/posterminal.js';
|
} from '../../providers/sqlite3/queries/posterminal.js';
|
||||||
|
import {
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as MSSQL_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as MSSQL_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
|
} from '../../providers/mssql/queries/category.js';
|
||||||
|
import {
|
||||||
|
ENQUEUE_SUBTREE_CATEGORIES_SYNC as SQLITE_ENQUEUE_SUBTREE_CATEGORIES,
|
||||||
|
ENQUEUE_SUBTREE_ARTICLES_SYNC as SQLITE_ENQUEUE_SUBTREE_ARTICLES,
|
||||||
|
} from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
@@ -20,6 +28,12 @@ export default function setOn(provider) {
|
|||||||
const listCatIdsSql = isSqlite
|
const listCatIdsSql = isSqlite
|
||||||
? SQLITE_LIST_CATEGORY_IDS
|
? SQLITE_LIST_CATEGORY_IDS
|
||||||
: MSSQL_LIST_CATEGORY_IDS;
|
: MSSQL_LIST_CATEGORY_IDS;
|
||||||
|
const enqueueCategoriesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_CATEGORIES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_CATEGORIES;
|
||||||
|
const enqueueArticlesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_ARTICLES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_ARTICLES;
|
||||||
const touchSql = isSqlite
|
const touchSql = isSqlite
|
||||||
? `WITH RECURSIVE cats AS (
|
? `WITH RECURSIVE cats AS (
|
||||||
SELECT id FROM category WHERE id = @categoryId
|
SELECT id FROM category WHERE id = @categoryId
|
||||||
@@ -166,6 +180,8 @@ export default function setOn(provider) {
|
|||||||
|
|
||||||
await runner.query(touchSql, { categoryId });
|
await runner.query(touchSql, { categoryId });
|
||||||
await runner.query(touchArticlesSql, { categoryId });
|
await runner.query(touchArticlesSql, { categoryId });
|
||||||
|
await runner.query(enqueueCategoriesSql, { id: categoryId, companyId });
|
||||||
|
await runner.query(enqueueArticlesSql, { id: categoryId, companyId });
|
||||||
|
|
||||||
const result = await runner.query(listCatIdsSql, { posterminalId });
|
const result = await runner.query(listCatIdsSql, { posterminalId });
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import {
|
|||||||
} from '../../providers/sqlite3/queries/posterminal.js';
|
} from '../../providers/sqlite3/queries/posterminal.js';
|
||||||
import { GET_COMPANY_ROOT_CATEGORY as MSSQL_ROOT } from '../../providers/mssql/queries/company.js';
|
import { GET_COMPANY_ROOT_CATEGORY as MSSQL_ROOT } from '../../providers/mssql/queries/company.js';
|
||||||
import { GET_COMPANY_ROOT_CATEGORY as SQLITE_ROOT } from '../../providers/sqlite3/queries/company.js';
|
import { GET_COMPANY_ROOT_CATEGORY as SQLITE_ROOT } from '../../providers/sqlite3/queries/company.js';
|
||||||
|
import { ENQUEUE_SUBTREE_CATEGORIES_SYNC as MSSQL_ENQUEUE_SUBTREE_CATEGORIES } from '../../providers/mssql/queries/category.js';
|
||||||
|
import { ENQUEUE_SUBTREE_CATEGORIES_SYNC as SQLITE_ENQUEUE_SUBTREE_CATEGORIES } from '../../providers/sqlite3/queries/category.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
@@ -23,6 +25,16 @@ export default function setOnAll(provider) {
|
|||||||
? SQLITE_LIST_CATEGORY_IDS
|
? SQLITE_LIST_CATEGORY_IDS
|
||||||
: MSSQL_LIST_CATEGORY_IDS;
|
: MSSQL_LIST_CATEGORY_IDS;
|
||||||
const rootSql = isSqlite ? SQLITE_ROOT : MSSQL_ROOT;
|
const rootSql = isSqlite ? SQLITE_ROOT : MSSQL_ROOT;
|
||||||
|
const enqueueCategoriesSql = isSqlite
|
||||||
|
? SQLITE_ENQUEUE_SUBTREE_CATEGORIES
|
||||||
|
: MSSQL_ENQUEUE_SUBTREE_CATEGORIES;
|
||||||
|
const enqueueAllArticlesSql = `
|
||||||
|
INSERT INTO posterminalsyncqueue (posterminal_id, entity_type, entity_id)
|
||||||
|
SELECT pt.id, 'article', a.id
|
||||||
|
FROM article a
|
||||||
|
INNER JOIN posterminal pt ON pt.company_id = a.company_id
|
||||||
|
WHERE a.company_id = @companyId
|
||||||
|
`;
|
||||||
const touchAllSql = isSqlite
|
const touchAllSql = isSqlite
|
||||||
? `WITH RECURSIVE cats AS (
|
? `WITH RECURSIVE cats AS (
|
||||||
SELECT id FROM category WHERE id = @rootCategoryId
|
SELECT id FROM category WHERE id = @rootCategoryId
|
||||||
@@ -100,6 +112,8 @@ export default function setOnAll(provider) {
|
|||||||
|
|
||||||
await runner.query(touchAllSql, { rootCategoryId });
|
await runner.query(touchAllSql, { rootCategoryId });
|
||||||
await runner.query(touchAllArticlesSql, { companyId });
|
await runner.query(touchAllArticlesSql, { companyId });
|
||||||
|
await runner.query(enqueueCategoriesSql, { id: rootCategoryId, companyId });
|
||||||
|
await runner.query(enqueueAllArticlesSql, { companyId });
|
||||||
|
|
||||||
const result = await runner.query(listCatIdsSql, { posterminalId });
|
const result = await runner.query(listCatIdsSql, { posterminalId });
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import {
|
|||||||
GET_BY_ID as MSSQL_GET_BY_ID,
|
GET_BY_ID as MSSQL_GET_BY_ID,
|
||||||
CREATE as MSSQL_CREATE,
|
CREATE as MSSQL_CREATE,
|
||||||
UPDATE as MSSQL_UPDATE,
|
UPDATE as MSSQL_UPDATE,
|
||||||
|
SEED_SYNC_QUEUE_FOR_TERMINAL as MSSQL_SEED_SYNC_QUEUE,
|
||||||
} from '../../providers/mssql/queries/posterminal.js';
|
} from '../../providers/mssql/queries/posterminal.js';
|
||||||
import {
|
import {
|
||||||
GET_BY_ID as SQLITE_GET_BY_ID,
|
GET_BY_ID as SQLITE_GET_BY_ID,
|
||||||
CREATE as SQLITE_CREATE,
|
CREATE as SQLITE_CREATE,
|
||||||
UPDATE as SQLITE_UPDATE,
|
UPDATE as SQLITE_UPDATE,
|
||||||
|
SEED_SYNC_QUEUE_FOR_TERMINAL as SQLITE_SEED_SYNC_QUEUE,
|
||||||
} from '../../providers/sqlite3/queries/posterminal.js';
|
} from '../../providers/sqlite3/queries/posterminal.js';
|
||||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
@@ -18,6 +20,7 @@ export default function upsert(provider) {
|
|||||||
const getByIdSql = isSqlite ? SQLITE_GET_BY_ID : MSSQL_GET_BY_ID;
|
const getByIdSql = isSqlite ? SQLITE_GET_BY_ID : MSSQL_GET_BY_ID;
|
||||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||||
|
const seedSyncQueueSql = isSqlite ? SQLITE_SEED_SYNC_QUEUE : MSSQL_SEED_SYNC_QUEUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates or updates a posterminal for the user's selected company.
|
* Creates or updates a posterminal for the user's selected company.
|
||||||
@@ -143,6 +146,11 @@ export default function upsert(provider) {
|
|||||||
lastseenAt,
|
lastseenAt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
await runner.query(seedSyncQueueSql, {
|
||||||
|
posterminalId: row.id,
|
||||||
|
companyId,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
name: row.name,
|
name: row.name,
|
||||||
|
|||||||
Reference in New Issue
Block a user