Compare commits
3 Commits
c7d1b1a5d2
...
55f04de8a8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55f04de8a8 | ||
|
|
76ea6642f4 | ||
|
|
f612c87b6e |
119
API.agentprinter.md
Normal file
119
API.agentprinter.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# agentprinter
|
||||
|
||||
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
|
||||
|
||||
## `agentprinter.delete`
|
||||
|
||||
*Source: `src/store/agentprinter/delete.js`*
|
||||
|
||||
Deletes an agent printer by id for the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `id` | `number` | The agent printer id. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<{id: number}>`
|
||||
|
||||
## `agentprinter.findOrCreate`
|
||||
|
||||
*Source: `src/store/agentprinter/findOrCreate.js`*
|
||||
|
||||
Finds or creates an agentprinter by (printeragentId, type, model, serial) combo.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `printeragentId` | `number` | The parent printer agent id. |
|
||||
| `input` | `object` | |
|
||||
| `input.type` | `string` | Printer type ("zpl", "esc/pos", etc.). |
|
||||
| `[input.model]` | `string|null` | Discovered model name. |
|
||||
| `[input.serial]` | `string|null` | Discovered serial number. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<{created: boolean, agentprinter: {id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}}>`
|
||||
|
||||
## `agentprinter.getById`
|
||||
|
||||
*Source: `src/store/agentprinter/getById.js`*
|
||||
|
||||
Retrieves an agent printer by id, scoped to the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `id` | `number` | The agent printer id. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}|null>`
|
||||
|
||||
## `agentprinter.list`
|
||||
|
||||
*Source: `src/store/agentprinter/list.js`*
|
||||
|
||||
Lists agent printers of the user's selected company, optionally filtered by printer agent.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `[printeragentId]` | `number` | Optional printer agent id filter. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<Array<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>>`
|
||||
|
||||
## `agentprinter.order`
|
||||
|
||||
*Source: `src/store/agentprinter/order.js`*
|
||||
|
||||
Reorders agent printers for a given printer agent within the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `input` | `object` | |
|
||||
| `input.printeragentId` | `number` | The printer agent id. |
|
||||
| `input.agentprinterIds` | `number[]` | Complete ordered list of agent printer IDs. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<{agentprinterIds: number[]}>`
|
||||
|
||||
## `agentprinter.update`
|
||||
|
||||
*Source: `src/store/agentprinter/update.js`*
|
||||
|
||||
Updates enabled and/or sort of an agent printer for the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `input` | `object` | |
|
||||
| `input.id` | `number` | Agent printer id. |
|
||||
| `[input.enabled]` | `boolean` | Whether the printer is enabled. |
|
||||
| `[input.sort]` | `number` | Display order integer. |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>`
|
||||
13
API.md
13
API.md
@@ -344,6 +344,13 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
||||
- `create(googleAuthId: number, input: {type: string, name: string}, tx?: object): Promise<{id: number, companyId: number, type: string, name: string}>`
|
||||
- `delete(googleAuthId: number, id: number, tx?: object): Promise<void>`
|
||||
- `list(googleAuthId: number, tx?: object): Promise<Array<{id: number, companyId: number, type: string, name: string}>>`
|
||||
- [agentprinter](API.agentprinter.md)
|
||||
- `delete(googleAuthId: number, id: number, tx?: object): Promise<{id: number}>`
|
||||
- `findOrCreate(printeragentId: number, input: {type: string, model?: string|null, serial?: string|null}, tx?: object): Promise<{created: boolean, agentprinter: {id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}}>`
|
||||
- `getById(googleAuthId: number, id: number, tx?: object): Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}|null>`
|
||||
- `list(googleAuthId: number, printeragentId?: number, tx?: object): Promise<Array<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>>`
|
||||
- `order(googleAuthId: number, input: {printeragentId: number, agentprinterIds: number[]}, tx?: object): Promise<{agentprinterIds: number[]}>`
|
||||
- `update(googleAuthId: number, input: {id: number, enabled?: boolean, sort?: number}, tx?: object): Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>`
|
||||
- [articlehistory](API.articlehistory.md)
|
||||
- `record(): void`
|
||||
- [articlelist](API.articlelist.md)
|
||||
@@ -414,6 +421,12 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
||||
- `touchLastseen(id: number, agentversion?: string|null, tx?: object): Promise<{id: number}>`
|
||||
- `update(googleAuthId: number, input: {id: number, name?: string, sort?: number}, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, clientmodel: string|null, clientstate: string|null, agentversion: string|null, lastseenAt: string|null, updatedAt: string, sort: number}>`
|
||||
- `updateState(id: number, clientstate: string|null, tx?: object): Promise<{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, clientmodel: string|null, clientstate: string|null, agentversion: string|null, lastseenAt: string|null, updatedAt: string, sort: number}>`
|
||||
- [printerjob](API.printerjob.md)
|
||||
- `create(googleAuthId: number, input: {agentprinterId: number, data: string, type?: string, state?: string}, tx?: object): Promise<object>`
|
||||
- `delete(googleAuthId: number, id: number, tx?: object): Promise<object>`
|
||||
- `getById(auth: number|{agentId: number}, id: number, tx?: object): Promise<object|null>`
|
||||
- `list(auth: number|{agentId: number}, filters?: {agentprinterId?: number, state?: string}, tx?: object): Promise<Array<object>>`
|
||||
- `updateState(auth: number|{agentId: number}, id: number, state: string, tx?: object): Promise<object>`
|
||||
- [retoure](API.retoure.md)
|
||||
- `create(googleAuthId: number, body: {number?: string, date: string, entityId?: number, externalNumber?: string, lines?: Array<object>}, tx?: object): Promise<object>`
|
||||
- `createShipment(googleAuthId: number, retoureId: number, input: object, tx?: object): Promise<object>`
|
||||
|
||||
100
API.printerjob.md
Normal file
100
API.printerjob.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# printerjob
|
||||
|
||||
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
|
||||
|
||||
## `printerjob.create`
|
||||
|
||||
*Source: `src/store/printerjob/create.js`*
|
||||
|
||||
Creates a new printer job for an agent printer belonging to the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `input` | `object` | |
|
||||
| `input.agentprinterId` | `number` | Target agent printer ID. |
|
||||
| `input.data` | `string` | Job payload (ZPL code, etc.). |
|
||||
| `[input.type]` | `string` | Job type ("zpl", "pdf", etc., defaults to agentprinter type or "zpl"). |
|
||||
| `[input.state]` | `string` | Initial state (defaults to "pending"). |
|
||||
| `[tx]` | `object` | Optional transaction to run within. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<object>` — Created printer job with printeragentId attached.
|
||||
|
||||
## `printerjob.delete`
|
||||
|
||||
*Source: `src/store/printerjob/delete.js`*
|
||||
|
||||
Deletes a printer job belonging to the user's selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||
| `id` | `number` | Printer job ID. |
|
||||
| `[tx]` | `object` | Optional transaction. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<object>` — The deleted job's snapshot.
|
||||
|
||||
## `printerjob.getById`
|
||||
|
||||
*Source: `src/store/printerjob/getById.js`*
|
||||
|
||||
Retrieves a printer job by ID. If caller is an agent ({ agentId: number }), checks that the job belongs to that printer agent. If caller is a user (googleAuthId: number), checks that the job belongs to the selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `auth` | `number|{agentId: number}` | User's googleAuthId or { agentId }. |
|
||||
| `id` | `number` | Printer job ID. |
|
||||
| `[tx]` | `object` | Optional transaction. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<object|null>`
|
||||
|
||||
## `printerjob.list`
|
||||
|
||||
*Source: `src/store/printerjob/list.js`*
|
||||
|
||||
Lists printer jobs. If caller is an agent ({ agentId: number }), lists jobs for that agent. If caller is a user (googleAuthId: number), lists jobs for the selected company.
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `auth` | `number|{agentId: number}` | User's googleAuthId or { agentId }. |
|
||||
| `[filters]` | `object` | |
|
||||
| `[filters.agentprinterId]` | `number` | Filter by agentprinterId (company callers only). |
|
||||
| `[filters.state]` | `string` | Filter by job state (e.g. "pending"). |
|
||||
| `[tx]` | `object` | Optional transaction. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<Array<object>>`
|
||||
|
||||
## `printerjob.updateState`
|
||||
|
||||
*Source: `src/store/printerjob/updateState.js`*
|
||||
|
||||
Updates a printer job's state ("processing", "completed", "cancelled", etc.).
|
||||
|
||||
**Parameters**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `auth` | `number|{agentId: number}` | User's googleAuthId or { agentId }. |
|
||||
| `id` | `number` | Printer job ID. |
|
||||
| `state` | `string` | New state. |
|
||||
| `[tx]` | `object` | Optional transaction. |
|
||||
|
||||
**Returns**
|
||||
|
||||
`Promise<object>` — Updated printer job.
|
||||
@@ -34,42 +34,78 @@ try {
|
||||
// pair
|
||||
const paired = await store.printeragent.pair(a.id, {
|
||||
token: 'test-token-123',
|
||||
clientserial: 'SN12345',
|
||||
clientmodel: 'Epson TM-T88VI',
|
||||
agentversion: '1.0.0',
|
||||
});
|
||||
assert.equal(paired.token, 'test-token-123');
|
||||
assert.equal(paired.clientserial, 'SN12345');
|
||||
assert.equal(paired.clientmodel, 'Epson TM-T88VI');
|
||||
assert.equal(paired.agentversion, '1.0.0');
|
||||
assert.equal(paired.pairingpin, null);
|
||||
assert.equal(paired.enabled, true);
|
||||
assert.ok(paired.pairedAt);
|
||||
|
||||
// findByToken
|
||||
const foundByToken = await store.printeragent.findByToken('test-token-123');
|
||||
assert.equal(foundByToken.id, a.id);
|
||||
assert.equal(foundByToken.clientmodel, 'Epson TM-T88VI');
|
||||
assert.equal(foundByToken.enabled, true);
|
||||
assert.equal(await store.printeragent.findByToken('invalid-token'), null);
|
||||
|
||||
// updateState
|
||||
const withState = await store.printeragent.updateState(a.id, { online: true, paper: 'ok' });
|
||||
assert.equal(withState.clientstate, JSON.stringify({ online: true, paper: 'ok' }));
|
||||
|
||||
// touchLastseen
|
||||
await store.printeragent.touchLastseen(a.id, '1.0.1');
|
||||
const afterTouch = await store.printeragent.findByToken('test-token-123');
|
||||
assert.equal(afterTouch.agentversion, '1.0.1');
|
||||
|
||||
// update name and sort
|
||||
const b = await store.printeragent.update(googleAuthId, { id: a.id, name: 'Kitchen', sort: 1 });
|
||||
// update name, sort, and enabled
|
||||
const b = await store.printeragent.update(googleAuthId, { id: a.id, name: 'Kitchen', sort: 1, enabled: false });
|
||||
assert.equal(b.name, 'Kitchen');
|
||||
assert.equal(b.sort, 1);
|
||||
assert.equal(b.enabled, false);
|
||||
|
||||
// list
|
||||
const list = await store.printeragent.list(googleAuthId);
|
||||
assert.equal(list.length, 1);
|
||||
assert.equal(list[0].name, 'Kitchen');
|
||||
assert.equal(list[0].sort, 1);
|
||||
assert.equal(list[0].enabled, false);
|
||||
|
||||
// test agentprinter findOrCreate
|
||||
const ap1 = await store.agentprinter.findOrCreate(a.id, { type: 'zpl', model: 'ZD410-200dpi', serial: '50J203002218' });
|
||||
assert.equal(ap1.created, true);
|
||||
assert.equal(ap1.agentprinter.type, 'zpl');
|
||||
assert.equal(ap1.agentprinter.model, 'ZD410-200dpi');
|
||||
assert.equal(ap1.agentprinter.serial, '50J203002218');
|
||||
assert.equal(ap1.agentprinter.enabled, true);
|
||||
|
||||
// second call with same combo returns existing
|
||||
const ap1Again = await store.agentprinter.findOrCreate(a.id, { type: 'zpl', model: 'ZD410-200dpi', serial: '50J203002218' });
|
||||
assert.equal(ap1Again.created, false);
|
||||
assert.equal(ap1Again.agentprinter.id, ap1.agentprinter.id);
|
||||
|
||||
// create second printer
|
||||
const ap2 = await store.agentprinter.findOrCreate(a.id, { type: 'esc/pos', model: 'TM-T88VI', serial: 'SN999' });
|
||||
assert.equal(ap2.created, true);
|
||||
|
||||
// list agentprinters
|
||||
const apList = await store.agentprinter.list(googleAuthId, a.id);
|
||||
assert.equal(apList.length, 2);
|
||||
|
||||
// getById
|
||||
const apGet = await store.agentprinter.getById(googleAuthId, ap1.agentprinter.id);
|
||||
assert.equal(apGet.serial, '50J203002218');
|
||||
|
||||
// update agentprinter
|
||||
const apUpdated = await store.agentprinter.update(googleAuthId, { id: ap1.agentprinter.id, enabled: false, sort: 10 });
|
||||
assert.equal(apUpdated.enabled, false);
|
||||
assert.equal(apUpdated.sort, 10);
|
||||
|
||||
// order agentprinters
|
||||
const ordered = await store.agentprinter.order(googleAuthId, {
|
||||
printeragentId: a.id,
|
||||
agentprinterIds: [ap2.agentprinter.id, ap1.agentprinter.id],
|
||||
});
|
||||
assert.deepEqual(ordered.agentprinterIds, [ap2.agentprinter.id, ap1.agentprinter.id]);
|
||||
|
||||
// delete agentprinter
|
||||
await store.agentprinter.delete(googleAuthId, ap2.agentprinter.id);
|
||||
assert.equal((await store.agentprinter.list(googleAuthId, a.id)).length, 1);
|
||||
|
||||
// delete
|
||||
await store.printeragent.delete(googleAuthId, a.id);
|
||||
|
||||
28
src/index.js
28
src/index.js
@@ -209,6 +209,17 @@ import printeragentFindByToken from './store/printeragent/findByToken.js';
|
||||
import printeragentPair from './store/printeragent/pair.js';
|
||||
import printeragentUpdateState from './store/printeragent/updateState.js';
|
||||
import printeragentTouchLastseen from './store/printeragent/touchLastseen.js';
|
||||
import agentprinterList from './store/agentprinter/list.js';
|
||||
import agentprinterGetById from './store/agentprinter/getById.js';
|
||||
import agentprinterFindOrCreate from './store/agentprinter/findOrCreate.js';
|
||||
import agentprinterUpdate from './store/agentprinter/update.js';
|
||||
import agentprinterOrder from './store/agentprinter/order.js';
|
||||
import agentprinterDelete from './store/agentprinter/delete.js';
|
||||
import printerjobCreate from './store/printerjob/create.js';
|
||||
import printerjobGetById from './store/printerjob/getById.js';
|
||||
import printerjobList from './store/printerjob/list.js';
|
||||
import printerjobUpdateState from './store/printerjob/updateState.js';
|
||||
import printerjobDelete from './store/printerjob/delete.js';
|
||||
import modelconversationCreate from './store/modelconversation/create.js';
|
||||
import modelconversationGet from './store/modelconversation/get.js';
|
||||
import modelconversationList from './store/modelconversation/list.js';
|
||||
@@ -658,6 +669,23 @@ export default class LibDashStore {
|
||||
touchLastseen: printeragentTouchLastseen(provider),
|
||||
};
|
||||
|
||||
this.agentprinter = {
|
||||
list: agentprinterList(provider),
|
||||
getById: agentprinterGetById(provider),
|
||||
findOrCreate: agentprinterFindOrCreate(provider),
|
||||
update: agentprinterUpdate(provider),
|
||||
order: agentprinterOrder(provider),
|
||||
delete: agentprinterDelete(provider),
|
||||
};
|
||||
|
||||
this.printerjob = {
|
||||
create: printerjobCreate(provider),
|
||||
getById: printerjobGetById(provider),
|
||||
list: printerjobList(provider),
|
||||
updateState: printerjobUpdateState(provider),
|
||||
delete: printerjobDelete(provider),
|
||||
};
|
||||
|
||||
this.modelconversation = {
|
||||
create: modelconversationCreate(provider),
|
||||
get: modelconversationGet(provider),
|
||||
|
||||
38
src/providers/mssql/downgrade/4_to_3.js
Normal file
38
src/providers/mssql/downgrade/4_to_3.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Schema 4 → 3 (MSSQL):
|
||||
* - Drops agentprinter table
|
||||
* - Removes enabled from printeragent
|
||||
* - Restores clientserial, clientmodel, clientstate in printeragent
|
||||
* @param {{ query: (sql: string, params?: object) => Promise<unknown>, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function downgrade({ query, assertVersion, setVersion }) {
|
||||
await assertVersion(4);
|
||||
|
||||
await query(`DROP TABLE IF EXISTS agentprinter;`);
|
||||
|
||||
await query(`
|
||||
IF OBJECT_ID(N'dbo.printeragent', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
IF COL_LENGTH('printeragent', 'enabled') IS NOT NULL
|
||||
BEGIN
|
||||
DECLARE @defName NVARCHAR(255);
|
||||
SELECT @defName = dc.name
|
||||
FROM sys.default_constraints dc
|
||||
JOIN sys.columns c ON c.default_object_id = dc.object_id
|
||||
WHERE dc.parent_object_id = OBJECT_ID(N'dbo.printeragent') AND c.name = 'enabled';
|
||||
IF @defName IS NOT NULL
|
||||
EXEC('ALTER TABLE printeragent DROP CONSTRAINT ' + @defName);
|
||||
ALTER TABLE printeragent DROP COLUMN enabled;
|
||||
END
|
||||
IF COL_LENGTH('printeragent', 'clientserial') IS NULL
|
||||
ALTER TABLE printeragent ADD clientserial NVARCHAR(255) NULL;
|
||||
IF COL_LENGTH('printeragent', 'clientmodel') IS NULL
|
||||
ALTER TABLE printeragent ADD clientmodel NVARCHAR(255) NULL;
|
||||
IF COL_LENGTH('printeragent', 'clientstate') IS NULL
|
||||
ALTER TABLE printeragent ADD clientstate NVARCHAR(255) NULL;
|
||||
END
|
||||
`);
|
||||
|
||||
await setVersion(3);
|
||||
}
|
||||
|
||||
13
src/providers/mssql/downgrade/5_to_4.js
Normal file
13
src/providers/mssql/downgrade/5_to_4.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Schema 5 → 4 (MSSQL):
|
||||
* - Drops printerjob table
|
||||
* @param {{ query: (sql: string, params?: object) => Promise<unknown>, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function downgrade({ query, assertVersion, setVersion }) {
|
||||
await assertVersion(5);
|
||||
|
||||
await query(`DROP TABLE IF EXISTS printerjob;`);
|
||||
|
||||
await setVersion(4);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ export const TABLES = [
|
||||
'posterminalobituary',
|
||||
'posterminalcategory',
|
||||
'posterminal',
|
||||
'printerjob',
|
||||
'agentprinter',
|
||||
'printeragent',
|
||||
'printer',
|
||||
'numbers',
|
||||
|
||||
69
src/providers/mssql/queries/agentprinter.js
Normal file
69
src/providers/mssql/queries/agentprinter.js
Normal file
@@ -0,0 +1,69 @@
|
||||
export const AGENTPRINTER_COLUMNS = `
|
||||
ap.id,
|
||||
ap.printeragent_id AS printeragentId,
|
||||
ap.type,
|
||||
ap.model,
|
||||
ap.serial,
|
||||
ap.enabled,
|
||||
ap.sort
|
||||
`;
|
||||
|
||||
export const LIST_BY_COMPANY = `
|
||||
SELECT
|
||||
${AGENTPRINTER_COLUMNS}
|
||||
FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pa.company_id = @companyId
|
||||
ORDER BY ap.sort, ap.id
|
||||
`;
|
||||
|
||||
export const LIST_BY_PRINTERAGENT = `
|
||||
SELECT
|
||||
${AGENTPRINTER_COLUMNS}
|
||||
FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE ap.printeragent_id = @printeragentId AND pa.company_id = @companyId
|
||||
ORDER BY ap.sort, ap.id
|
||||
`;
|
||||
|
||||
export const GET_BY_ID = `
|
||||
SELECT
|
||||
${AGENTPRINTER_COLUMNS}
|
||||
FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE ap.id = @id AND pa.company_id = @companyId
|
||||
`;
|
||||
|
||||
export const FIND_BY_COMBO = `
|
||||
SELECT
|
||||
${AGENTPRINTER_COLUMNS}
|
||||
FROM agentprinter ap
|
||||
WHERE ap.printeragent_id = @printeragentId
|
||||
AND ap.type = @type
|
||||
AND (ap.serial = @serial OR (ap.serial IS NULL AND @serial IS NULL))
|
||||
AND (ap.model = @model OR (ap.model IS NULL AND @model IS NULL))
|
||||
`;
|
||||
|
||||
export const CREATE = `
|
||||
INSERT INTO agentprinter (printeragent_id, type, model, serial, enabled, sort)
|
||||
OUTPUT
|
||||
INSERTED.id,
|
||||
INSERTED.printeragent_id AS printeragentId,
|
||||
INSERTED.type,
|
||||
INSERTED.model,
|
||||
INSERTED.serial,
|
||||
INSERTED.enabled,
|
||||
INSERTED.sort
|
||||
VALUES (@printeragentId, @type, @model, @serial, @enabled, @sort)
|
||||
`;
|
||||
|
||||
export const UPDATE = `
|
||||
UPDATE agentprinter
|
||||
SET enabled = @enabled, sort = @sort
|
||||
WHERE id = @id AND printeragent_id IN (SELECT id FROM printeragent WHERE company_id = @companyId)
|
||||
`;
|
||||
|
||||
export const DELETE_BY_COMPANY_AND_ID = `
|
||||
DELETE FROM agentprinter
|
||||
WHERE id = @id AND printeragent_id IN (SELECT id FROM printeragent WHERE company_id = @companyId)
|
||||
`;
|
||||
@@ -5,13 +5,11 @@ export const PRINTERAGENT_COLUMNS = `
|
||||
token,
|
||||
pairingpin,
|
||||
paired_at AS pairedAt,
|
||||
clientserial,
|
||||
clientmodel,
|
||||
clientstate,
|
||||
agentversion,
|
||||
lastseen_at AS lastseenAt,
|
||||
updated_at AS updatedAt,
|
||||
sort
|
||||
sort,
|
||||
enabled
|
||||
`;
|
||||
|
||||
export const LIST_BY_COMPANY = `
|
||||
@@ -55,8 +53,6 @@ UPDATE printeragent
|
||||
SET token = @token,
|
||||
pairingpin = NULL,
|
||||
paired_at = @pairedAt,
|
||||
clientserial = @clientserial,
|
||||
clientmodel = @clientmodel,
|
||||
agentversion = @agentversion,
|
||||
lastseen_at = SYSUTCDATETIME(),
|
||||
updated_at = SYSUTCDATETIME()
|
||||
@@ -85,7 +81,7 @@ WHERE id = @id
|
||||
`;
|
||||
|
||||
export const CREATE = `
|
||||
INSERT INTO printeragent (company_id, name, pairingpin, sort)
|
||||
INSERT INTO printeragent (company_id, name, pairingpin, sort, enabled)
|
||||
OUTPUT
|
||||
INSERTED.id,
|
||||
INSERTED.company_id AS companyId,
|
||||
@@ -93,19 +89,17 @@ OUTPUT
|
||||
INSERTED.token,
|
||||
INSERTED.pairingpin,
|
||||
INSERTED.paired_at AS pairedAt,
|
||||
INSERTED.clientserial,
|
||||
INSERTED.clientmodel,
|
||||
INSERTED.clientstate,
|
||||
INSERTED.agentversion,
|
||||
INSERTED.lastseen_at AS lastseenAt,
|
||||
INSERTED.updated_at AS updatedAt,
|
||||
INSERTED.sort
|
||||
VALUES (@companyId, @name, @pairingpin, @sort)
|
||||
INSERTED.sort,
|
||||
INSERTED.enabled
|
||||
VALUES (@companyId, @name, @pairingpin, @sort, @enabled)
|
||||
`;
|
||||
|
||||
export const UPDATE = `
|
||||
UPDATE printeragent
|
||||
SET name = @name, sort = @sort, updated_at = SYSUTCDATETIME()
|
||||
SET name = @name, sort = @sort, enabled = @enabled, updated_at = SYSUTCDATETIME()
|
||||
WHERE id = @id AND company_id = @companyId
|
||||
`;
|
||||
|
||||
|
||||
115
src/providers/mssql/queries/printerjob.js
Normal file
115
src/providers/mssql/queries/printerjob.js
Normal file
@@ -0,0 +1,115 @@
|
||||
export const PRINTERJOB_COLUMNS = `
|
||||
pj.id,
|
||||
pj.agentprinter_id AS agentprinterId,
|
||||
pj.type,
|
||||
pj.state,
|
||||
pj.data,
|
||||
pj.created_at AS createdAt,
|
||||
pj.completed_at AS completedAt
|
||||
`;
|
||||
|
||||
export const CREATE = `
|
||||
INSERT INTO printerjob (agentprinter_id, type, state, data, created_at)
|
||||
OUTPUT
|
||||
INSERTED.id,
|
||||
INSERTED.agentprinter_id AS agentprinterId,
|
||||
INSERTED.type,
|
||||
INSERTED.state,
|
||||
INSERTED.data,
|
||||
INSERTED.created_at AS createdAt,
|
||||
INSERTED.completed_at AS completedAt
|
||||
VALUES (@agentprinterId, @type, @state, @data, SYSUTCDATETIME())
|
||||
`;
|
||||
|
||||
export const GET_BY_ID_FOR_COMPANY = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pj.id = @id AND pa.company_id = @companyId
|
||||
`;
|
||||
|
||||
export const GET_BY_ID_FOR_AGENT = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
WHERE pj.id = @id AND ap.printeragent_id = @agentId
|
||||
`;
|
||||
|
||||
export const LIST_BY_COMPANY = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pa.company_id = @companyId
|
||||
ORDER BY pj.id DESC
|
||||
`;
|
||||
|
||||
export const LIST_BY_COMPANY_AND_AGENTPRINTER = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pa.company_id = @companyId AND pj.agentprinter_id = @agentprinterId
|
||||
ORDER BY pj.id DESC
|
||||
`;
|
||||
|
||||
export const LIST_BY_AGENT = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
WHERE ap.printeragent_id = @agentId
|
||||
ORDER BY pj.id ASC
|
||||
`;
|
||||
|
||||
export const LIST_BY_AGENT_AND_STATE = `
|
||||
SELECT
|
||||
${PRINTERJOB_COLUMNS},
|
||||
ap.printeragent_id AS printeragentId
|
||||
FROM printerjob pj
|
||||
JOIN agentprinter ap ON ap.id = pj.agentprinter_id
|
||||
WHERE ap.printeragent_id = @agentId AND pj.state = @state
|
||||
ORDER BY pj.id ASC
|
||||
`;
|
||||
|
||||
export const UPDATE_STATE_FOR_AGENT = `
|
||||
UPDATE printerjob
|
||||
SET
|
||||
state = @state,
|
||||
completed_at = CASE WHEN @state IN ('completed', 'cancelled') THEN SYSUTCDATETIME() ELSE completed_at END
|
||||
WHERE id = @id AND agentprinter_id IN (
|
||||
SELECT ap.id FROM agentprinter ap WHERE ap.printeragent_id = @agentId
|
||||
)
|
||||
`;
|
||||
|
||||
export const UPDATE_STATE_FOR_COMPANY = `
|
||||
UPDATE printerjob
|
||||
SET
|
||||
state = @state,
|
||||
completed_at = CASE WHEN @state IN ('completed', 'cancelled') THEN SYSUTCDATETIME() ELSE completed_at END
|
||||
WHERE id = @id AND agentprinter_id IN (
|
||||
SELECT ap.id FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pa.company_id = @companyId
|
||||
)
|
||||
`;
|
||||
|
||||
export const DELETE_BY_COMPANY_AND_ID = `
|
||||
DELETE FROM printerjob
|
||||
WHERE id = @id AND agentprinter_id IN (
|
||||
SELECT ap.id FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE pa.company_id = @companyId
|
||||
)
|
||||
`;
|
||||
|
||||
@@ -1021,13 +1021,11 @@ BEGIN
|
||||
token NVARCHAR(255) NULL,
|
||||
pairingpin NVARCHAR(50) NULL,
|
||||
paired_at DATETIME2 NULL,
|
||||
clientserial NVARCHAR(255) NULL,
|
||||
clientmodel NVARCHAR(255) NULL,
|
||||
clientstate NVARCHAR(255) NULL,
|
||||
agentversion NVARCHAR(255) NULL,
|
||||
lastseen_at DATETIME2 NULL,
|
||||
updated_at DATETIME2 NOT NULL CONSTRAINT DF_printeragent_updated_at DEFAULT SYSUTCDATETIME(),
|
||||
sort INT NOT NULL CONSTRAINT DF_printeragent_sort DEFAULT 0,
|
||||
enabled BIT NOT NULL CONSTRAINT DF_printeragent_enabled DEFAULT 1,
|
||||
CONSTRAINT FK_printeragent_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX UQ_printeragent_token ON printeragent(token) WHERE token IS NOT NULL;
|
||||
@@ -1035,6 +1033,41 @@ BEGIN
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_AGENTPRINTER = `
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'agentprinter')
|
||||
BEGIN
|
||||
CREATE TABLE agentprinter (
|
||||
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||
printeragent_id INT NOT NULL,
|
||||
type NVARCHAR(50) NOT NULL,
|
||||
model NVARCHAR(255) NULL,
|
||||
serial NVARCHAR(255) NULL,
|
||||
enabled BIT NOT NULL CONSTRAINT DF_agentprinter_enabled DEFAULT 1,
|
||||
sort INT NOT NULL CONSTRAINT DF_agentprinter_sort DEFAULT 0,
|
||||
CONSTRAINT FK_agentprinter_printeragent FOREIGN KEY (printeragent_id) REFERENCES printeragent(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IX_agentprinter_printeragent_id ON agentprinter(printeragent_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_PRINTERJOB = `
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'printerjob')
|
||||
BEGIN
|
||||
CREATE TABLE printerjob (
|
||||
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||
agentprinter_id INT NOT NULL,
|
||||
type NVARCHAR(50) NOT NULL,
|
||||
state NVARCHAR(50) NOT NULL CONSTRAINT DF_printerjob_state DEFAULT 'pending',
|
||||
data NVARCHAR(MAX) NOT NULL,
|
||||
created_at DATETIME2 NOT NULL CONSTRAINT DF_printerjob_created_at DEFAULT SYSUTCDATETIME(),
|
||||
completed_at DATETIME2 NULL,
|
||||
CONSTRAINT FK_printerjob_agentprinter FOREIGN KEY (agentprinter_id) REFERENCES agentprinter(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IX_printerjob_agentprinter_id ON printerjob(agentprinter_id);
|
||||
CREATE INDEX IX_printerjob_state ON printerjob(state);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_LABELTEMPLATE = `
|
||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'labeltemplate')
|
||||
BEGIN
|
||||
@@ -1691,6 +1724,8 @@ export const SCHEMA_SCRIPTS = [
|
||||
INIT_POSTERMINALSYNCQUEUE,
|
||||
INIT_PRINTER,
|
||||
INIT_PRINTERAGENT,
|
||||
INIT_AGENTPRINTER,
|
||||
INIT_PRINTERJOB,
|
||||
INIT_LABELTEMPLATE,
|
||||
INIT_FILE,
|
||||
INIT_MANIFESTATTACHMENT,
|
||||
|
||||
31
src/providers/mssql/upgrade/3_to_4.js
Normal file
31
src/providers/mssql/upgrade/3_to_4.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { INIT_AGENTPRINTER } from '../schema.js';
|
||||
|
||||
/**
|
||||
* Schema 3 → 4 (MSSQL):
|
||||
* - Drops clientstate, clientmodel, clientserial from printeragent
|
||||
* - Adds enabled to printeragent
|
||||
* - Creates agentprinter table
|
||||
* @param {{ query: (sql: string, params?: object) => Promise<unknown>, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function upgrade({ query, assertVersion, setVersion }) {
|
||||
await assertVersion(3);
|
||||
|
||||
await query(`
|
||||
IF OBJECT_ID(N'dbo.printeragent', N'U') IS NOT NULL
|
||||
BEGIN
|
||||
IF COL_LENGTH('printeragent', 'clientstate') IS NOT NULL
|
||||
ALTER TABLE printeragent DROP COLUMN clientstate;
|
||||
IF COL_LENGTH('printeragent', 'clientmodel') IS NOT NULL
|
||||
ALTER TABLE printeragent DROP COLUMN clientmodel;
|
||||
IF COL_LENGTH('printeragent', 'clientserial') IS NOT NULL
|
||||
ALTER TABLE printeragent DROP COLUMN clientserial;
|
||||
IF COL_LENGTH('printeragent', 'enabled') IS NULL
|
||||
ALTER TABLE printeragent ADD enabled BIT NOT NULL CONSTRAINT DF_printeragent_enabled DEFAULT 1;
|
||||
END
|
||||
`);
|
||||
|
||||
await query(INIT_AGENTPRINTER);
|
||||
|
||||
await setVersion(4);
|
||||
}
|
||||
|
||||
15
src/providers/mssql/upgrade/4_to_5.js
Normal file
15
src/providers/mssql/upgrade/4_to_5.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { INIT_PRINTERJOB } from '../schema.js';
|
||||
|
||||
/**
|
||||
* Schema 4 → 5 (MSSQL):
|
||||
* - Creates printerjob table
|
||||
* @param {{ query: (sql: string, params?: object) => Promise<unknown>, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function upgrade({ query, assertVersion, setVersion }) {
|
||||
await assertVersion(4);
|
||||
|
||||
await query(INIT_PRINTERJOB);
|
||||
|
||||
await setVersion(5);
|
||||
}
|
||||
|
||||
28
src/providers/sqlite3/downgrade/4_to_3.js
Normal file
28
src/providers/sqlite3/downgrade/4_to_3.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Schema 4 → 3 (SQLite):
|
||||
* - Drops agentprinter table
|
||||
* - Removes enabled from printeragent
|
||||
* - Restores clientserial, clientmodel, clientstate in printeragent
|
||||
* @param {{ exec: (sql: string) => void, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function downgrade({ exec, assertVersion, setVersion }) {
|
||||
await assertVersion(4);
|
||||
|
||||
exec(`DROP TABLE IF EXISTS agentprinter;`);
|
||||
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent DROP COLUMN enabled;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent ADD COLUMN clientserial TEXT;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent ADD COLUMN clientmodel TEXT;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent ADD COLUMN clientstate TEXT;`);
|
||||
} catch {}
|
||||
|
||||
await setVersion(3);
|
||||
}
|
||||
|
||||
13
src/providers/sqlite3/downgrade/5_to_4.js
Normal file
13
src/providers/sqlite3/downgrade/5_to_4.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Schema 5 → 4 (SQLite):
|
||||
* - Drops printerjob table
|
||||
* @param {{ exec: (sql: string) => void, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function downgrade({ exec, assertVersion, setVersion }) {
|
||||
await assertVersion(5);
|
||||
|
||||
exec(`DROP TABLE IF EXISTS printerjob;`);
|
||||
|
||||
await setVersion(4);
|
||||
}
|
||||
|
||||
15
src/providers/sqlite3/queries/agentprinter.js
Normal file
15
src/providers/sqlite3/queries/agentprinter.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as source from '../../mssql/queries/agentprinter.js';
|
||||
import { translateQueries } from './translate.js';
|
||||
|
||||
const queries = translateQueries(source, 'agentprinter');
|
||||
export const {
|
||||
AGENTPRINTER_COLUMNS,
|
||||
CREATE,
|
||||
DELETE_BY_COMPANY_AND_ID,
|
||||
FIND_BY_COMBO,
|
||||
GET_BY_ID,
|
||||
LIST_BY_COMPANY,
|
||||
LIST_BY_PRINTERAGENT,
|
||||
UPDATE,
|
||||
} = queries;
|
||||
|
||||
18
src/providers/sqlite3/queries/printerjob.js
Normal file
18
src/providers/sqlite3/queries/printerjob.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import * as source from '../../mssql/queries/printerjob.js';
|
||||
import { translateQueries } from './translate.js';
|
||||
|
||||
const queries = translateQueries(source, 'printerjob');
|
||||
export const {
|
||||
PRINTERJOB_COLUMNS,
|
||||
CREATE,
|
||||
GET_BY_ID_FOR_COMPANY,
|
||||
GET_BY_ID_FOR_AGENT,
|
||||
LIST_BY_COMPANY,
|
||||
LIST_BY_COMPANY_AND_AGENTPRINTER,
|
||||
LIST_BY_AGENT,
|
||||
LIST_BY_AGENT_AND_STATE,
|
||||
UPDATE_STATE_FOR_AGENT,
|
||||
UPDATE_STATE_FOR_COMPANY,
|
||||
DELETE_BY_COMPANY_AND_ID,
|
||||
} = queries;
|
||||
|
||||
@@ -700,13 +700,11 @@ CREATE TABLE IF NOT EXISTS printeragent (
|
||||
token TEXT,
|
||||
pairingpin TEXT,
|
||||
paired_at TEXT,
|
||||
clientserial TEXT,
|
||||
clientmodel TEXT,
|
||||
clientstate TEXT,
|
||||
agentversion TEXT,
|
||||
lastseen_at TEXT,
|
||||
updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}),
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS UQ_printeragent_token
|
||||
@@ -715,6 +713,38 @@ CREATE UNIQUE INDEX IF NOT EXISTS UQ_printeragent_pairingpin
|
||||
ON printeragent(pairingpin) WHERE pairingpin IS NOT NULL;
|
||||
`;
|
||||
|
||||
export const INIT_AGENTPRINTER = `
|
||||
CREATE TABLE IF NOT EXISTS agentprinter (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
printeragent_id INTEGER NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
model TEXT,
|
||||
serial TEXT,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY (printeragent_id) REFERENCES printeragent(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_agentprinter_printeragent_id
|
||||
ON agentprinter(printeragent_id);
|
||||
`;
|
||||
|
||||
export const INIT_PRINTERJOB = `
|
||||
CREATE TABLE IF NOT EXISTS printerjob (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
agentprinter_id INTEGER NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
state TEXT NOT NULL DEFAULT 'pending',
|
||||
data TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
||||
completed_at TEXT,
|
||||
FOREIGN KEY (agentprinter_id) REFERENCES agentprinter(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_printerjob_agentprinter_id
|
||||
ON printerjob(agentprinter_id);
|
||||
CREATE INDEX IF NOT EXISTS IX_printerjob_state
|
||||
ON printerjob(state);
|
||||
`;
|
||||
|
||||
export const INIT_LABELTEMPLATE = `
|
||||
CREATE TABLE IF NOT EXISTS labeltemplate (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -1249,6 +1279,8 @@ export const SCHEMA_SCRIPTS = [
|
||||
INIT_POSTERMINALSYNCQUEUE,
|
||||
INIT_PRINTER,
|
||||
INIT_PRINTERAGENT,
|
||||
INIT_AGENTPRINTER,
|
||||
INIT_PRINTERJOB,
|
||||
INIT_LABELTEMPLATE,
|
||||
INIT_FILE,
|
||||
INIT_MANIFESTATTACHMENT,
|
||||
|
||||
30
src/providers/sqlite3/upgrade/3_to_4.js
Normal file
30
src/providers/sqlite3/upgrade/3_to_4.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { INIT_AGENTPRINTER } from '../schema.js';
|
||||
|
||||
/**
|
||||
* Schema 3 → 4 (SQLite):
|
||||
* - Drops clientstate, clientmodel, clientserial from printeragent
|
||||
* - Adds enabled to printeragent
|
||||
* - Creates agentprinter table
|
||||
* @param {{ exec: (sql: string) => void, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function upgrade({ exec, assertVersion, setVersion }) {
|
||||
await assertVersion(3);
|
||||
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent DROP COLUMN clientstate;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent DROP COLUMN clientmodel;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent DROP COLUMN clientserial;`);
|
||||
} catch {}
|
||||
try {
|
||||
exec(`ALTER TABLE printeragent ADD COLUMN enabled INTEGER NOT NULL DEFAULT 1;`);
|
||||
} catch {}
|
||||
|
||||
exec(INIT_AGENTPRINTER);
|
||||
|
||||
await setVersion(4);
|
||||
}
|
||||
|
||||
15
src/providers/sqlite3/upgrade/4_to_5.js
Normal file
15
src/providers/sqlite3/upgrade/4_to_5.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { INIT_PRINTERJOB } from '../schema.js';
|
||||
|
||||
/**
|
||||
* Schema 4 → 5 (SQLite):
|
||||
* - Creates printerjob table
|
||||
* @param {{ exec: (sql: string) => void, assertVersion: (v: number) => Promise<void>, setVersion: (v: number) => Promise<void> }} ctx
|
||||
*/
|
||||
export default async function upgrade({ exec, assertVersion, setVersion }) {
|
||||
await assertVersion(4);
|
||||
|
||||
exec(INIT_PRINTERJOB);
|
||||
|
||||
await setVersion(5);
|
||||
}
|
||||
|
||||
16
src/store/agentprinter/_shared.js
Normal file
16
src/store/agentprinter/_shared.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function shape(row) {
|
||||
if (!row) return null;
|
||||
return {
|
||||
id: row.id,
|
||||
printeragentId: row.printeragentId,
|
||||
type: row.type,
|
||||
model: row.model ?? null,
|
||||
serial: row.serial ?? null,
|
||||
enabled: Boolean(row.enabled),
|
||||
sort: row.sort,
|
||||
};
|
||||
}
|
||||
|
||||
export const AGENTPRINTER_TYPEDEF =
|
||||
'{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}';
|
||||
|
||||
35
src/store/agentprinter/delete.js
Normal file
35
src/store/agentprinter/delete.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as MSSQL_DELETE,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as SQLITE_DELETE,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function del(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
|
||||
/**
|
||||
* Deletes an agent printer by id for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - The agent printer id.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number}>}
|
||||
*/
|
||||
return async (googleAuthId, id, tx) => {
|
||||
const numericId = Number(id);
|
||||
if (!Number.isInteger(numericId) || numericId <= 0) {
|
||||
throw new Error('Agentprinter not found');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
await runner.query(sql, { id: numericId, companyId });
|
||||
return { id: numericId };
|
||||
};
|
||||
}
|
||||
|
||||
55
src/store/agentprinter/findOrCreate.js
Normal file
55
src/store/agentprinter/findOrCreate.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import {
|
||||
FIND_BY_COMBO as MSSQL_FIND,
|
||||
CREATE as MSSQL_CREATE,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
FIND_BY_COMBO as SQLITE_FIND,
|
||||
CREATE as SQLITE_CREATE,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function findOrCreate(provider) {
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const findSql = isSqlite ? SQLITE_FIND : MSSQL_FIND;
|
||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||
|
||||
/**
|
||||
* Finds or creates an agentprinter by (printeragentId, type, model, serial) combo.
|
||||
*
|
||||
* @param {number} printeragentId - The parent printer agent id.
|
||||
* @param {object} input
|
||||
* @param {string} input.type - Printer type ("zpl", "esc/pos", etc.).
|
||||
* @param {string|null} [input.model] - Discovered model name.
|
||||
* @param {string|null} [input.serial] - Discovered serial number.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{created: boolean, agentprinter: {id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}}>}
|
||||
*/
|
||||
return async (printeragentId, input = {}, tx) => {
|
||||
const pId = Number(printeragentId);
|
||||
if (!Number.isInteger(pId) || pId <= 0) {
|
||||
throw new Error('Printeragent not found');
|
||||
}
|
||||
|
||||
const type = typeof input.type === 'string' && input.type.trim() ? input.type.trim().toLowerCase() : 'zpl';
|
||||
const model = input.model != null && String(input.model).trim() ? String(input.model).trim() : null;
|
||||
const serial = input.serial != null && String(input.serial).trim() ? String(input.serial).trim() : null;
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const existing = await runner.query(findSql, { printeragentId: pId, type, model, serial });
|
||||
if (existing.rows.length > 0) {
|
||||
return { created: false, agentprinter: shape(existing.rows[0]) };
|
||||
}
|
||||
|
||||
const created = await runner.query(createSql, {
|
||||
printeragentId: pId,
|
||||
type,
|
||||
model,
|
||||
serial,
|
||||
enabled: 1,
|
||||
sort: 0,
|
||||
});
|
||||
return { created: true, agentprinter: shape(created.rows[0]) };
|
||||
};
|
||||
}
|
||||
|
||||
36
src/store/agentprinter/getById.js
Normal file
36
src/store/agentprinter/getById.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
GET_BY_ID as MSSQL_GET,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
GET_BY_ID as SQLITE_GET,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function getById(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_GET : MSSQL_GET;
|
||||
|
||||
/**
|
||||
* Retrieves an agent printer by id, scoped to the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - The agent printer id.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}|null>}
|
||||
*/
|
||||
return async (googleAuthId, id, tx) => {
|
||||
const numericId = Number(id);
|
||||
if (!Number.isInteger(numericId) || numericId <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const result = await runner.query(sql, { id: numericId, companyId });
|
||||
return result.rows[0] ? shape(result.rows[0]) : null;
|
||||
};
|
||||
}
|
||||
|
||||
41
src/store/agentprinter/list.js
Normal file
41
src/store/agentprinter/list.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
LIST_BY_COMPANY as MSSQL_LIST_BY_COMPANY,
|
||||
LIST_BY_PRINTERAGENT as MSSQL_LIST_BY_PRINTERAGENT,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
LIST_BY_COMPANY as SQLITE_LIST_BY_COMPANY,
|
||||
LIST_BY_PRINTERAGENT as SQLITE_LIST_BY_PRINTERAGENT,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function list(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const listCompanySql = isSqlite ? SQLITE_LIST_BY_COMPANY : MSSQL_LIST_BY_COMPANY;
|
||||
const listAgentSql = isSqlite ? SQLITE_LIST_BY_PRINTERAGENT : MSSQL_LIST_BY_PRINTERAGENT;
|
||||
|
||||
/**
|
||||
* Lists agent printers of the user's selected company, optionally filtered by printer agent.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} [printeragentId] - Optional printer agent id filter.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<Array<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>>}
|
||||
*/
|
||||
return async (googleAuthId, printeragentId, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const aId = printeragentId != null ? Number(printeragentId) : null;
|
||||
let result;
|
||||
if (aId && Number.isInteger(aId) && aId > 0) {
|
||||
result = await runner.query(listAgentSql, { companyId, printeragentId: aId });
|
||||
} else {
|
||||
result = await runner.query(listCompanySql, { companyId });
|
||||
}
|
||||
return result.rows.map(shape);
|
||||
};
|
||||
}
|
||||
|
||||
68
src/store/agentprinter/order.js
Normal file
68
src/store/agentprinter/order.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
LIST_BY_COMPANY as MSSQL_LIST_BY_COMPANY,
|
||||
LIST_BY_PRINTERAGENT as MSSQL_LIST_BY_AGENT,
|
||||
UPDATE as MSSQL_UPDATE,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
LIST_BY_COMPANY as SQLITE_LIST_BY_COMPANY,
|
||||
LIST_BY_PRINTERAGENT as SQLITE_LIST_BY_AGENT,
|
||||
UPDATE as SQLITE_UPDATE,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function order(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const listCompanySql = isSqlite ? SQLITE_LIST_BY_COMPANY : MSSQL_LIST_BY_COMPANY;
|
||||
const listAgentSql = isSqlite ? SQLITE_LIST_BY_AGENT : MSSQL_LIST_BY_AGENT;
|
||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||
|
||||
/**
|
||||
* Reorders agent printers for a given printer agent or globally across the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {object} input
|
||||
* @param {number} [input.printeragentId] - Optional printer agent id. If omitted, reorders all printers in company.
|
||||
* @param {number[]} input.agentprinterIds - Complete ordered list of agent printer IDs.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{agentprinterIds: number[]}>}
|
||||
*/
|
||||
return async (googleAuthId, input = {}, tx) => {
|
||||
const hasAgent = input.printeragentId != null;
|
||||
let pId;
|
||||
if (hasAgent) {
|
||||
pId = Number(input.printeragentId);
|
||||
if (!Number.isInteger(pId) || pId <= 0) {
|
||||
throw new Error('Printeragent not found');
|
||||
}
|
||||
}
|
||||
|
||||
const ids = input.agentprinterIds;
|
||||
if (!Array.isArray(ids) || ids.length === 0 || ids.some((id) => !Number.isInteger(Number(id)) || Number(id) <= 0)) {
|
||||
throw new Error('Invalid agentprinter order');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const existing = hasAgent
|
||||
? await runner.query(listAgentSql, { companyId, printeragentId: pId })
|
||||
: await runner.query(listCompanySql, { companyId });
|
||||
const existingIds = new Set(existing.rows.map((r) => r.id));
|
||||
|
||||
if (ids.length !== existingIds.size || ids.some((id) => !existingIds.has(Number(id)))) {
|
||||
throw new Error('Invalid agentprinter order');
|
||||
}
|
||||
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = Number(ids[i]);
|
||||
const current = existing.rows.find((r) => r.id === id);
|
||||
const enabled = current ? (current.enabled ? 1 : 0) : 1;
|
||||
await runner.query(updateSql, { id, companyId, sort: i + 1, enabled });
|
||||
}
|
||||
|
||||
return { agentprinterIds: ids.map(Number) };
|
||||
};
|
||||
}
|
||||
|
||||
63
src/store/agentprinter/update.js
Normal file
63
src/store/agentprinter/update.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
GET_BY_ID as MSSQL_GET,
|
||||
UPDATE as MSSQL_UPDATE,
|
||||
} from '../../providers/mssql/queries/agentprinter.js';
|
||||
import {
|
||||
GET_BY_ID as SQLITE_GET,
|
||||
UPDATE as SQLITE_UPDATE,
|
||||
} from '../../providers/sqlite3/queries/agentprinter.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function update(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const getSql = isSqlite ? SQLITE_GET : MSSQL_GET;
|
||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||
|
||||
/**
|
||||
* Updates enabled and/or sort of an agent printer for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {object} input
|
||||
* @param {number} input.id - Agent printer id.
|
||||
* @param {boolean} [input.enabled] - Whether the printer is enabled.
|
||||
* @param {number} [input.sort] - Display order integer.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, printeragentId: number, type: string, model: string|null, serial: string|null, enabled: boolean, sort: number}>}
|
||||
*/
|
||||
return async (googleAuthId, input = {}, tx) => {
|
||||
const id = Number(input.id);
|
||||
if (!Number.isInteger(id) || id <= 0) {
|
||||
throw new Error('Agentprinter not found');
|
||||
}
|
||||
|
||||
if (input.enabled === undefined && input.sort === undefined) {
|
||||
throw new Error('Invalid agentprinter');
|
||||
}
|
||||
if (input.enabled !== undefined && typeof input.enabled !== 'boolean') {
|
||||
throw new Error('Invalid agentprinter');
|
||||
}
|
||||
if (input.sort !== undefined && !Number.isInteger(input.sort)) {
|
||||
throw new Error('Invalid agentprinter');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const existing = await runner.query(getSql, { id, companyId });
|
||||
if (!existing.rows[0]) {
|
||||
throw new Error('Agentprinter not found');
|
||||
}
|
||||
|
||||
const sort = input.sort !== undefined ? input.sort : existing.rows[0].sort;
|
||||
const enabled = input.enabled !== undefined ? (input.enabled ? 1 : 0) : (existing.rows[0].enabled ? 1 : 0);
|
||||
|
||||
await runner.query(updateSql, { id, companyId, sort, enabled });
|
||||
|
||||
const updated = await runner.query(getSql, { id, companyId });
|
||||
return shape(updated.rows[0]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,15 +6,13 @@ export function shape(row) {
|
||||
token: row.token ?? null,
|
||||
pairingpin: row.pairingpin ?? null,
|
||||
pairedAt: row.pairedAt ?? null,
|
||||
clientserial: row.clientserial ?? null,
|
||||
clientmodel: row.clientmodel ?? null,
|
||||
clientstate: row.clientstate ?? null,
|
||||
agentversion: row.agentversion ?? null,
|
||||
lastseenAt: row.lastseenAt ?? null,
|
||||
updatedAt: row.updatedAt,
|
||||
sort: row.sort,
|
||||
enabled: Boolean(row.enabled),
|
||||
};
|
||||
}
|
||||
|
||||
export const PRINTERAGENT_TYPEDEF =
|
||||
'{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, clientserial: string|null, clientmodel: string|null, clientstate: string|null, agentversion: string|null, lastseenAt: string|null, updatedAt: string, sort: number}';
|
||||
'{id: number, companyId: number, name: string, token: string|null, pairingpin: string|null, pairedAt: string|null, agentversion: string|null, lastseenAt: string|null, updatedAt: string, sort: number, enabled: boolean}';
|
||||
|
||||
@@ -39,11 +39,12 @@ export default function create(provider) {
|
||||
throw new Error('Invalid printeragent');
|
||||
}
|
||||
const sort = input.sort ?? 0;
|
||||
const enabled = input.enabled !== undefined ? (input.enabled ? 1 : 0) : 1;
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const result = await runner.query(sql, { companyId, name, pairingpin, sort });
|
||||
const result = await runner.query(sql, { companyId, name, pairingpin, sort, enabled });
|
||||
return shape(result.rows[0]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ export default function pair(provider) {
|
||||
throw new Error('Invalid printeragent');
|
||||
}
|
||||
|
||||
const clientserial = input.clientserial ? String(input.clientserial).trim() : null;
|
||||
const clientmodel = input.clientmodel ? String(input.clientmodel).trim() : null;
|
||||
const agentversion = input.agentversion ? String(input.agentversion).trim() : null;
|
||||
const pairedAt = input.pairedAt ?? new Date().toISOString();
|
||||
|
||||
@@ -47,8 +45,6 @@ export default function pair(provider) {
|
||||
id: numericId,
|
||||
token,
|
||||
pairedAt,
|
||||
clientserial,
|
||||
clientmodel,
|
||||
agentversion,
|
||||
});
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function update(provider) {
|
||||
if (!Number.isInteger(id) || id <= 0) {
|
||||
throw new Error('Printeragent not found');
|
||||
}
|
||||
if (input.name === undefined && input.sort === undefined) {
|
||||
if (input.name === undefined && input.sort === undefined && input.enabled === undefined) {
|
||||
throw new Error('Invalid printeragent');
|
||||
}
|
||||
if (input.name !== undefined && (typeof input.name !== 'string' || !input.name.trim())) {
|
||||
@@ -45,6 +45,9 @@ export default function update(provider) {
|
||||
if (input.sort !== undefined && !Number.isInteger(input.sort)) {
|
||||
throw new Error('Invalid printeragent');
|
||||
}
|
||||
if (input.enabled !== undefined && typeof input.enabled !== 'boolean') {
|
||||
throw new Error('Invalid printeragent');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
@@ -59,6 +62,7 @@ export default function update(provider) {
|
||||
companyId,
|
||||
name: input.name !== undefined ? input.name.trim() : existing.rows[0].name,
|
||||
sort: input.sort !== undefined ? input.sort : existing.rows[0].sort,
|
||||
enabled: input.enabled !== undefined ? (input.enabled ? 1 : 0) : existing.rows[0].enabled,
|
||||
});
|
||||
|
||||
const row = await runner.query(getSql, { id, companyId });
|
||||
|
||||
14
src/store/printerjob/_shared.js
Normal file
14
src/store/printerjob/_shared.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export function shape(row) {
|
||||
if (!row) return null;
|
||||
return {
|
||||
id: row.id,
|
||||
agentprinterId: row.agentprinterId,
|
||||
printeragentId: row.printeragentId != null ? Number(row.printeragentId) : null,
|
||||
type: row.type,
|
||||
state: row.state,
|
||||
data: row.data,
|
||||
createdAt: row.createdAt instanceof Date ? row.createdAt.toISOString() : (row.createdAt ?? null),
|
||||
completedAt: row.completedAt instanceof Date ? row.completedAt.toISOString() : (row.completedAt ?? null),
|
||||
};
|
||||
}
|
||||
|
||||
71
src/store/printerjob/create.js
Normal file
71
src/store/printerjob/create.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { CREATE as MSSQL_CREATE } from '../../providers/mssql/queries/printerjob.js';
|
||||
import { CREATE as SQLITE_CREATE } from '../../providers/sqlite3/queries/printerjob.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
const VERIFY_AGENTPRINTER = `
|
||||
SELECT ap.id, ap.printeragent_id AS printeragentId, ap.type, ap.enabled
|
||||
FROM agentprinter ap
|
||||
JOIN printeragent pa ON pa.id = ap.printeragent_id
|
||||
WHERE ap.id = @agentprinterId AND pa.company_id = @companyId
|
||||
`;
|
||||
|
||||
export default function create(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
|
||||
|
||||
/**
|
||||
* Creates a new printer job for an agent printer belonging to the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {object} input
|
||||
* @param {number} input.agentprinterId - Target agent printer ID.
|
||||
* @param {string} input.data - Job payload (ZPL code, etc.).
|
||||
* @param {string} [input.type] - Job type ("zpl", "pdf", etc., defaults to agentprinter type or "zpl").
|
||||
* @param {string} [input.state] - Initial state (defaults to "pending").
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<object>} Created printer job with printeragentId attached.
|
||||
*/
|
||||
return async (googleAuthId, input = {}, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const apId = Number(input.agentprinterId ?? input.agentprinter_id);
|
||||
if (!Number.isInteger(apId) || apId <= 0) {
|
||||
throw new Error('agentprinterId is required');
|
||||
}
|
||||
|
||||
const data = input.data != null ? String(input.data) : '';
|
||||
if (!data.trim()) {
|
||||
throw new Error('data is required');
|
||||
}
|
||||
|
||||
const verified = await runner.query(VERIFY_AGENTPRINTER, { agentprinterId: apId, companyId });
|
||||
if (verified.rows.length === 0) {
|
||||
throw new Error('Agentprinter not found');
|
||||
}
|
||||
|
||||
const apRow = verified.rows[0];
|
||||
const printeragentId = Number(apRow.printeragentId);
|
||||
const type = typeof input.type === 'string' && input.type.trim()
|
||||
? input.type.trim().toLowerCase()
|
||||
: (apRow.type ? String(apRow.type).toLowerCase() : 'zpl');
|
||||
const state = typeof input.state === 'string' && input.state.trim()
|
||||
? input.state.trim().toLowerCase()
|
||||
: 'pending';
|
||||
|
||||
const result = await runner.query(createSql, {
|
||||
agentprinterId: apId,
|
||||
type,
|
||||
state,
|
||||
data,
|
||||
});
|
||||
|
||||
const job = shape(result.rows[0]);
|
||||
job.printeragentId = printeragentId;
|
||||
return job;
|
||||
};
|
||||
}
|
||||
|
||||
46
src/store/printerjob/delete.js
Normal file
46
src/store/printerjob/delete.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as MSSQL_DELETE,
|
||||
GET_BY_ID_FOR_COMPANY as MSSQL_GET,
|
||||
} from '../../providers/mssql/queries/printerjob.js';
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as SQLITE_DELETE,
|
||||
GET_BY_ID_FOR_COMPANY as SQLITE_GET,
|
||||
} from '../../providers/sqlite3/queries/printerjob.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function deleteJob(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
const getSql = isSqlite ? SQLITE_GET : MSSQL_GET;
|
||||
|
||||
/**
|
||||
* Deletes a printer job belonging to the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - Printer job ID.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<object>} The deleted job's snapshot.
|
||||
*/
|
||||
return async (googleAuthId, id, tx) => {
|
||||
const jId = Number(id);
|
||||
if (!Number.isInteger(jId) || jId <= 0) {
|
||||
throw new Error('Printerjob not found');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const existing = await runner.query(getSql, { id: jId, companyId });
|
||||
if (existing.rows.length === 0) {
|
||||
throw new Error('Printerjob not found');
|
||||
}
|
||||
|
||||
const job = shape(existing.rows[0]);
|
||||
await runner.query(deleteSql, { id: jId, companyId });
|
||||
return job;
|
||||
};
|
||||
}
|
||||
|
||||
49
src/store/printerjob/getById.js
Normal file
49
src/store/printerjob/getById.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
GET_BY_ID_FOR_COMPANY as MSSQL_GET_BY_ID_FOR_COMPANY,
|
||||
GET_BY_ID_FOR_AGENT as MSSQL_GET_BY_ID_FOR_AGENT,
|
||||
} from '../../providers/mssql/queries/printerjob.js';
|
||||
import {
|
||||
GET_BY_ID_FOR_COMPANY as SQLITE_GET_BY_ID_FOR_COMPANY,
|
||||
GET_BY_ID_FOR_AGENT as SQLITE_GET_BY_ID_FOR_AGENT,
|
||||
} from '../../providers/sqlite3/queries/printerjob.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function getById(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const getForCompanySql = isSqlite ? SQLITE_GET_BY_ID_FOR_COMPANY : MSSQL_GET_BY_ID_FOR_COMPANY;
|
||||
const getForAgentSql = isSqlite ? SQLITE_GET_BY_ID_FOR_AGENT : MSSQL_GET_BY_ID_FOR_AGENT;
|
||||
|
||||
/**
|
||||
* Retrieves a printer job by ID.
|
||||
* If caller is an agent ({ agentId: number }), checks that the job belongs to that printer agent.
|
||||
* If caller is a user (googleAuthId: number), checks that the job belongs to the selected company.
|
||||
*
|
||||
* @param {number|{agentId: number}} auth - User's googleAuthId or { agentId }.
|
||||
* @param {number} id - Printer job ID.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<object|null>}
|
||||
*/
|
||||
return async (auth, id, tx) => {
|
||||
const jId = Number(id);
|
||||
if (!Number.isInteger(jId) || jId <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
|
||||
if (typeof auth === 'object' && auth !== null && auth.agentId != null) {
|
||||
const aId = Number(auth.agentId);
|
||||
if (!Number.isInteger(aId) || aId <= 0) return null;
|
||||
const result = await runner.query(getForAgentSql, { id: jId, agentId: aId });
|
||||
return result.rows.length > 0 ? shape(result.rows[0]) : null;
|
||||
}
|
||||
|
||||
const { companyId } = await access(auth, runner);
|
||||
const result = await runner.query(getForCompanySql, { id: jId, companyId });
|
||||
return result.rows.length > 0 ? shape(result.rows[0]) : null;
|
||||
};
|
||||
}
|
||||
|
||||
74
src/store/printerjob/list.js
Normal file
74
src/store/printerjob/list.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import {
|
||||
LIST_BY_COMPANY as MSSQL_LIST_BY_COMPANY,
|
||||
LIST_BY_COMPANY_AND_AGENTPRINTER as MSSQL_LIST_BY_COMPANY_AND_AGENTPRINTER,
|
||||
LIST_BY_AGENT as MSSQL_LIST_BY_AGENT,
|
||||
LIST_BY_AGENT_AND_STATE as MSSQL_LIST_BY_AGENT_AND_STATE,
|
||||
} from '../../providers/mssql/queries/printerjob.js';
|
||||
import {
|
||||
LIST_BY_COMPANY as SQLITE_LIST_BY_COMPANY,
|
||||
LIST_BY_COMPANY_AND_AGENTPRINTER as SQLITE_LIST_BY_COMPANY_AND_AGENTPRINTER,
|
||||
LIST_BY_AGENT as SQLITE_LIST_BY_AGENT,
|
||||
LIST_BY_AGENT_AND_STATE as SQLITE_LIST_BY_AGENT_AND_STATE,
|
||||
} from '../../providers/sqlite3/queries/printerjob.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
export default function list(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const listCompanySql = isSqlite ? SQLITE_LIST_BY_COMPANY : MSSQL_LIST_BY_COMPANY;
|
||||
const listCompanyApSql = isSqlite ? SQLITE_LIST_BY_COMPANY_AND_AGENTPRINTER : MSSQL_LIST_BY_COMPANY_AND_AGENTPRINTER;
|
||||
const listAgentSql = isSqlite ? SQLITE_LIST_BY_AGENT : MSSQL_LIST_BY_AGENT;
|
||||
const listAgentStateSql = isSqlite ? SQLITE_LIST_BY_AGENT_AND_STATE : MSSQL_LIST_BY_AGENT_AND_STATE;
|
||||
|
||||
/**
|
||||
* Lists printer jobs.
|
||||
* If caller is an agent ({ agentId: number }), lists jobs for that agent.
|
||||
* If caller is a user (googleAuthId: number), lists jobs for the selected company.
|
||||
*
|
||||
* @param {number|{agentId: number}} auth - User's googleAuthId or { agentId }.
|
||||
* @param {object} [filters]
|
||||
* @param {number} [filters.agentprinterId] - Filter by agentprinterId (company callers only).
|
||||
* @param {string} [filters.state] - Filter by job state (e.g. "pending").
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<Array<object>>}
|
||||
*/
|
||||
return async (auth, filters = {}, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
|
||||
if (typeof auth === 'object' && auth !== null && auth.agentId != null) {
|
||||
const aId = Number(auth.agentId);
|
||||
if (!Number.isInteger(aId) || aId <= 0) return [];
|
||||
const state = typeof filters.state === 'string' && filters.state.trim()
|
||||
? filters.state.trim().toLowerCase()
|
||||
: null;
|
||||
|
||||
let result;
|
||||
if (state) {
|
||||
result = await runner.query(listAgentStateSql, { agentId: aId, state });
|
||||
} else {
|
||||
result = await runner.query(listAgentSql, { agentId: aId });
|
||||
}
|
||||
return result.rows.map(shape);
|
||||
}
|
||||
|
||||
const { companyId } = await access(auth, runner);
|
||||
const apId = filters.agentprinterId != null ? Number(filters.agentprinterId) : null;
|
||||
|
||||
let result;
|
||||
if (apId && Number.isInteger(apId) && apId > 0) {
|
||||
result = await runner.query(listCompanyApSql, { companyId, agentprinterId: apId });
|
||||
} else {
|
||||
result = await runner.query(listCompanySql, { companyId });
|
||||
}
|
||||
|
||||
let rows = result.rows.map(shape);
|
||||
if (filters.state) {
|
||||
const targetState = String(filters.state).trim().toLowerCase();
|
||||
rows = rows.filter((r) => r.state === targetState);
|
||||
}
|
||||
return rows;
|
||||
};
|
||||
}
|
||||
|
||||
66
src/store/printerjob/updateState.js
Normal file
66
src/store/printerjob/updateState.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
UPDATE_STATE_FOR_COMPANY as MSSQL_UPDATE_COMPANY,
|
||||
UPDATE_STATE_FOR_AGENT as MSSQL_UPDATE_AGENT,
|
||||
GET_BY_ID_FOR_COMPANY as MSSQL_GET_COMPANY,
|
||||
GET_BY_ID_FOR_AGENT as MSSQL_GET_AGENT,
|
||||
} from '../../providers/mssql/queries/printerjob.js';
|
||||
import {
|
||||
UPDATE_STATE_FOR_COMPANY as SQLITE_UPDATE_COMPANY,
|
||||
UPDATE_STATE_FOR_AGENT as SQLITE_UPDATE_AGENT,
|
||||
GET_BY_ID_FOR_COMPANY as SQLITE_GET_COMPANY,
|
||||
GET_BY_ID_FOR_AGENT as SQLITE_GET_AGENT,
|
||||
} from '../../providers/sqlite3/queries/printerjob.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
import { shape } from './_shared.js';
|
||||
|
||||
const VALID_STATES = new Set(['pending', 'processing', 'completed', 'cancelled', 'failed']);
|
||||
|
||||
export default function updateState(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const updateCompanySql = isSqlite ? SQLITE_UPDATE_COMPANY : MSSQL_UPDATE_COMPANY;
|
||||
const updateAgentSql = isSqlite ? SQLITE_UPDATE_AGENT : MSSQL_UPDATE_AGENT;
|
||||
const getCompanySql = isSqlite ? SQLITE_GET_COMPANY : MSSQL_GET_COMPANY;
|
||||
const getAgentSql = isSqlite ? SQLITE_GET_AGENT : MSSQL_GET_AGENT;
|
||||
|
||||
/**
|
||||
* Updates a printer job's state ("processing", "completed", "cancelled", etc.).
|
||||
*
|
||||
* @param {number|{agentId: number}} auth - User's googleAuthId or { agentId }.
|
||||
* @param {number} id - Printer job ID.
|
||||
* @param {string} state - New state.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<object>} Updated printer job.
|
||||
*/
|
||||
return async (auth, id, state, tx) => {
|
||||
const jId = Number(id);
|
||||
if (!Number.isInteger(jId) || jId <= 0) {
|
||||
throw new Error('Printerjob not found');
|
||||
}
|
||||
|
||||
const normalizedState = typeof state === 'string' ? state.trim().toLowerCase() : '';
|
||||
if (!VALID_STATES.has(normalizedState)) {
|
||||
throw new Error(`Invalid printerjob state: ${state}`);
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
|
||||
if (typeof auth === 'object' && auth !== null && auth.agentId != null) {
|
||||
const aId = Number(auth.agentId);
|
||||
if (!Number.isInteger(aId) || aId <= 0) throw new Error('Not authorized');
|
||||
|
||||
await runner.query(updateAgentSql, { id: jId, agentId: aId, state: normalizedState });
|
||||
const fetched = await runner.query(getAgentSql, { id: jId, agentId: aId });
|
||||
if (fetched.rows.length === 0) throw new Error('Printerjob not found');
|
||||
return shape(fetched.rows[0]);
|
||||
}
|
||||
|
||||
const { companyId } = await access(auth, runner);
|
||||
await runner.query(updateCompanySql, { id: jId, companyId, state: normalizedState });
|
||||
const fetched = await runner.query(getCompanySql, { id: jId, companyId });
|
||||
if (fetched.rows.length === 0) throw new Error('Printerjob not found');
|
||||
return shape(fetched.rows[0]);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user