This commit is contained in:
seb
2026-10-01 17:40:04 +02:00
parent 62c3e69ed4
commit 84e547660e
53 changed files with 4604 additions and 2059 deletions

View File

@@ -17,6 +17,29 @@ WHERE id = @articleId
`;
export const CREATE_TOMBSTONE = `
INSERT INTO articletombstone (company_id, article_id, sku, name, taxrate, net)
SELECT
a.company_id,
a.id AS article_id,
a.sku,
COALESCE(
(SELECT TOP 1 at.name FROM articletext at WHERE at.article_id = a.id AND at.language_id = co.default_language_id),
(SELECT TOP 1 at.name FROM articletext at WHERE at.article_id = a.id ORDER BY at.id ASC)
) AS name,
COALESCE(
(SELECT TOP 1 t.rate FROM price pr INNER JOIN tax t ON t.id = pr.tax_id WHERE pr.article_id = a.id AND pr.customergroup_id = co.poscustomergroup_id AND pr.minmultiplier = 1),
(SELECT TOP 1 t.rate FROM price pr INNER JOIN tax t ON t.id = pr.tax_id WHERE pr.article_id = a.id ORDER BY pr.id ASC)
) AS taxrate,
COALESCE(
(SELECT TOP 1 pr.net FROM price pr WHERE pr.article_id = a.id AND pr.customergroup_id = co.poscustomergroup_id AND pr.minmultiplier = 1),
(SELECT TOP 1 pr.net FROM price pr WHERE pr.article_id = a.id ORDER BY pr.id ASC)
) AS net
FROM article a
INNER JOIN company co ON co.id = a.company_id
WHERE a.id = @articleId
`;
export const DELETE_PICS_BY_ARTICLE = `
DELETE p
FROM pic p

View File

@@ -9,3 +9,10 @@ FROM articlehistory
WHERE article_id = @articleId
ORDER BY [date] DESC, id DESC
`;
export const LIST_BY_ARTICLE_ID_LIMITED = `
SELECT TOP (@limit) id, companyuser_id AS companyuserId, [date], [text]
FROM articlehistory
WHERE article_id = @articleId
ORDER BY [date] DESC, id DESC
`;

View File

@@ -8,3 +8,13 @@ UPDATE articletext
SET name = @name, slug = @slug
WHERE article_id = @articleId AND language_id = @languageId
`;
export const LIST_SLUGS_BY_COMPANY_AND_LANGUAGE = `
SELECT at.slug, at.article_id AS articleId
FROM articletext at
INNER JOIN article a ON a.id = at.article_id
WHERE a.company_id = @companyId
AND at.language_id = @languageId
AND (at.slug = @baseSlug OR at.slug LIKE @likePattern)
`;

View File

@@ -0,0 +1,41 @@
export const LIST_BY_CATEGORY_ID = `
SELECT
cav.id,
cav.category_id AS categoryId,
an.id AS attributeId,
an.name AS attributeName,
an.exclusive,
av.id AS attributeValueId,
av.value,
cav.sort
FROM categoryattributevalue cav
INNER JOIN attributevalue av ON av.id = cav.attributevalue_id
INNER JOIN attributename an ON an.id = av.attribute_id
WHERE cav.category_id = @categoryId
ORDER BY an.sort ASC, an.id ASC, cav.sort ASC, cav.id ASC
`;
export const DELETE_BY_CATEGORY_ID = `
DELETE FROM categoryattributevalue
WHERE category_id = @categoryId
`;
export const INSERT_ROW = `
INSERT INTO categoryattributevalue (category_id, attributevalue_id, sort)
OUTPUT INSERTED.id, INSERTED.category_id AS categoryId, INSERTED.attributevalue_id AS attributeValueId, INSERTED.sort
VALUES (@categoryId, @attributeValueId, @sort)
`;
export const GET_VALUE_DETAIL = `
SELECT
av.id AS attributeValueId,
av.value,
av.sort,
an.id AS attributeId,
an.name AS attributeName,
an.exclusive,
an.company_id AS companyId
FROM attributevalue av
INNER JOIN attributename an ON an.id = av.attribute_id
WHERE av.id = @attributeValueId
`;

View File

@@ -0,0 +1,30 @@
export const LIST_BY_CATEGORY_ID = `
SELECT
cp.id,
cp.category_id AS categoryId,
cp.property_id AS propertyId,
pn.name AS name,
pn.exclusive,
cp.value,
cp.sort
FROM categoryproperty cp
INNER JOIN propertyname pn ON pn.id = cp.property_id
WHERE cp.category_id = @categoryId
ORDER BY cp.sort ASC, cp.id ASC
`;
export const DELETE_BY_CATEGORY_ID = `
DELETE FROM categoryproperty
WHERE category_id = @categoryId
`;
export const DELETE_BY_CATEGORY_AND_PROPERTY_ID = `
DELETE FROM categoryproperty
WHERE category_id = @categoryId AND property_id = @propertyId
`;
export const INSERT_ROW = `
INSERT INTO categoryproperty (category_id, property_id, value, sort)
OUTPUT INSERTED.id, INSERTED.category_id AS categoryId, INSERTED.property_id AS propertyId, INSERTED.value, INSERTED.sort
VALUES (@categoryId, @propertyId, @value, @sort)
`;

View File

@@ -108,3 +108,28 @@ VALUES (
@taxrate
)
`;
export const CHECK_ARTICLE_IS_FATHER = `
SELECT
a.id,
a.is_father AS isFather,
COALESCE(
(SELECT at.name FROM articletext at WHERE at.article_id = a.id AND at.language_id = co.default_language_id),
(SELECT MIN(at2.name) FROM articletext at2 WHERE at2.article_id = a.id),
a.sku
) AS articleName,
COALESCE(
(SELECT MIN(asup.pu) FROM articlesupplier asup WHERE asup.article_id = a.id AND asup.sku = @sku),
(SELECT MIN(asup2.pu) FROM articlesupplier asup2 WHERE asup2.article_id = a.id),
a.unitamount,
1
) AS pu
FROM article a
INNER JOIN manifest m ON m.company_id = a.company_id
INNER JOIN company co ON co.id = m.company_id
WHERE m.id = @manifestId
AND (a.sku = @sku OR EXISTS (
SELECT 1 FROM articlesupplier asup WHERE asup.article_id = a.id AND asup.sku = @sku
))
`;

View File

@@ -5,7 +5,8 @@ SELECT
token,
pairingpin,
paired_at AS pairedAt,
clientserial AS clientserial
clientserial AS clientserial,
maxknowntombstoneid AS maxknowntombstoneid
FROM posterminal
WHERE company_id = @companyId
ORDER BY id
@@ -19,7 +20,8 @@ SELECT
token,
pairingpin,
paired_at AS pairedAt,
clientserial AS clientserial
clientserial AS clientserial,
maxknowntombstoneid AS maxknowntombstoneid
FROM posterminal
WHERE id = @id
`;
@@ -32,7 +34,8 @@ SELECT
token,
pairingpin,
paired_at AS pairedAt,
clientserial AS clientserial
clientserial AS clientserial,
maxknowntombstoneid AS maxknowntombstoneid
FROM posterminal
WHERE pairingpin = @pairingpin
`;
@@ -44,17 +47,23 @@ WHERE id = @id
`;
export const CREATE = `
INSERT INTO posterminal (company_id, name, token, pairingpin, paired_at, clientserial)
OUTPUT INSERTED.id, INSERTED.name, INSERTED.token, INSERTED.pairingpin, INSERTED.paired_at AS pairedAt, INSERTED.clientserial AS clientserial
VALUES (@companyId, @name, @token, @pairingpin, @pairedAt, @clientserial)
INSERT INTO posterminal (company_id, name, token, pairingpin, paired_at, clientserial, maxknowntombstoneid)
OUTPUT INSERTED.id, INSERTED.name, INSERTED.token, INSERTED.pairingpin, INSERTED.paired_at AS pairedAt, INSERTED.clientserial AS clientserial, INSERTED.maxknowntombstoneid AS maxknowntombstoneid
VALUES (@companyId, @name, @token, @pairingpin, @pairedAt, @clientserial, @maxknowntombstoneid)
`;
export const UPDATE = `
UPDATE posterminal
SET name = @name, token = @token, pairingpin = @pairingpin, paired_at = @pairedAt, clientserial = @clientserial
SET name = @name, token = @token, pairingpin = @pairingpin, paired_at = @pairedAt, clientserial = @clientserial, maxknowntombstoneid = @maxknowntombstoneid
WHERE id = @id AND company_id = @companyId
`;
export const SET_MAX_KNOWN_TOMBSTONE_ID = `
UPDATE posterminal
SET maxknowntombstoneid = @maxknowntombstoneid
WHERE id = @id
`;
export const DELETE_BY_COMPANY_AND_ID = `
DELETE FROM posterminal
WHERE id = @id AND company_id = @companyId
@@ -122,7 +131,8 @@ SELECT
token,
pairingpin,
paired_at AS pairedAt,
clientserial AS clientserial
clientserial AS clientserial,
maxknowntombstoneid AS maxknowntombstoneid
FROM posterminal
WHERE token = @token
`;

View File

@@ -352,10 +352,11 @@ BEGIN
ALTER TABLE article ADD fatherattributename_id INT NULL;
ALTER TABLE article ADD CONSTRAINT FK_article_fatherattributename FOREIGN KEY (fatherattributename_id) REFERENCES attributename(id) ON DELETE NO ACTION;
END
END
ELSE IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('article') AND name = 'track_stock')
BEGIN
ALTER TABLE article ADD track_stock BIT NOT NULL CONSTRAINT DF_article_track_stock DEFAULT 1;
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('article') AND name = 'track_stock')
BEGIN
ALTER TABLE article ADD track_stock BIT NOT NULL CONSTRAINT DF_article_track_stock DEFAULT 1;
END
END
`;
@@ -374,6 +375,27 @@ BEGIN
END
`;
export const INIT_ARTICLETOMBSTONE = `
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'articletombstone')
BEGIN
CREATE TABLE articletombstone (
id INT IDENTITY(1,1) PRIMARY KEY,
company_id INT NOT NULL,
article_id INT NULL,
sku NVARCHAR(100) NULL,
name NVARCHAR(255) NULL,
taxrate DECIMAL(18,4) NULL,
net FLOAT NULL,
deleted_at DATETIME2 NOT NULL CONSTRAINT DF_articletombstone_deleted_at DEFAULT SYSUTCDATETIME(),
CONSTRAINT CK_articletombstone_article_or_sku CHECK (article_id IS NOT NULL OR sku IS NOT NULL),
CONSTRAINT FK_articletombstone_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
);
CREATE INDEX IX_articletombstone_company_deleted
ON articletombstone (company_id, deleted_at);
END
`;
export const INIT_ARTICLEEAN = `
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'articleean')
BEGIN
@@ -791,10 +813,18 @@ BEGIN
pairingpin NVARCHAR(50) NOT NULL,
paired_at DATETIME2 NULL,
clientserial NVARCHAR(255) NULL,
maxknowntombstoneid INT NULL,
CONSTRAINT FK_posterminal_company FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX UQ_posterminal_token ON posterminal(token) WHERE token IS NOT NULL;
END
ELSE
BEGIN
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('posterminal') AND name = 'maxknowntombstoneid')
BEGIN
ALTER TABLE posterminal ADD maxknowntombstoneid INT NULL;
END
END
`;
export const INIT_POSTERMINALCATEGORY = `
@@ -980,6 +1010,36 @@ BEGIN
END
`;
export const INIT_CATEGORYPROPERTY = `
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'categoryproperty')
BEGIN
CREATE TABLE categoryproperty (
id INT IDENTITY(1,1) PRIMARY KEY,
category_id INT NOT NULL,
property_id INT NOT NULL,
value NVARCHAR(MAX) NOT NULL,
sort INT NOT NULL CONSTRAINT DF_categoryproperty_sort DEFAULT 0,
CONSTRAINT FK_categoryproperty_category FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
CONSTRAINT FK_categoryproperty_property FOREIGN KEY (property_id) REFERENCES propertyname(id) ON DELETE CASCADE
);
END
`;
export const INIT_CATEGORYATTRIBUTEVALUE = `
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'categoryattributevalue')
BEGIN
CREATE TABLE categoryattributevalue (
id INT IDENTITY(1,1) PRIMARY KEY,
category_id INT NOT NULL,
attributevalue_id INT NOT NULL,
sort INT NOT NULL CONSTRAINT DF_categoryattributevalue_sort DEFAULT 0,
CONSTRAINT FK_categoryattributevalue_category FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
CONSTRAINT FK_categoryattributevalue_attributevalue FOREIGN KEY (attributevalue_id) REFERENCES attributevalue(id) ON DELETE CASCADE,
CONSTRAINT UQ_categoryattributevalue_category_attributevalue UNIQUE (category_id, attributevalue_id)
);
END
`;
/** DDL scripts in dependency order for schema init. */
export const SCHEMA_SCRIPTS = [
INIT_META,
@@ -1017,6 +1077,8 @@ export const SCHEMA_SCRIPTS = [
INIT_ARTICLE_SUPPLIER,
INIT_ARTICLEPROPERTY,
INIT_ARTICLEATTRIBUTEVALUE,
INIT_CATEGORYPROPERTY,
INIT_CATEGORYATTRIBUTEVALUE,
INIT_MANIFEST,
INIT_MANIFESTARTICLE,
INIT_WAREHOUSE,
@@ -1026,6 +1088,7 @@ export const SCHEMA_SCRIPTS = [
INIT_PEEK_NEXT_NUMBER_WITH_PREFIX_AND_PADDING,
INIT_COMPANYUSER,
INIT_ARTICLEHISTORY,
INIT_ARTICLETOMBSTONE,
INIT_ENTITYHISTORY,
INIT_SYNCPOS,
INIT_COMPANYSETTING,

View File

@@ -426,6 +426,9 @@ export class BetterSqlite3Provider extends BetterSqlite3Executor {
if (posterminalCols.length > 0 && !posterminalCols.includes('clientserial')) {
this.db.exec(`ALTER TABLE posterminal ADD COLUMN clientserial TEXT`);
}
if (posterminalCols.length > 0 && !posterminalCols.includes('maxknowntombstoneid')) {
this.db.exec(`ALTER TABLE posterminal ADD COLUMN maxknowntombstoneid INTEGER`);
}
const propertynameCols = this.db.pragma('table_info("propertyname")').map((c) => c.name);
if (propertynameCols.length > 0 && !propertynameCols.includes('exclusive')) {

View File

@@ -7,6 +7,29 @@ export const {
GET_CHILDREN_IDS, GET_LIST_IDS,
} = queries;
export const CREATE_TOMBSTONE = `
INSERT INTO articletombstone (company_id, article_id, sku, name, taxrate, net)
SELECT
a.company_id,
a.id AS article_id,
a.sku,
COALESCE(
(SELECT at.name FROM articletext at WHERE at.article_id = a.id AND at.language_id = co.default_language_id),
(SELECT at.name FROM articletext at WHERE at.article_id = a.id ORDER BY at.id ASC LIMIT 1)
) AS name,
COALESCE(
(SELECT t.rate FROM price pr INNER JOIN tax t ON t.id = pr.tax_id WHERE pr.article_id = a.id AND pr.customergroup_id = co.poscustomergroup_id AND pr.minmultiplier = 1),
(SELECT t.rate FROM price pr INNER JOIN tax t ON t.id = pr.tax_id WHERE pr.article_id = a.id ORDER BY pr.id ASC LIMIT 1)
) AS taxrate,
COALESCE(
(SELECT pr.net FROM price pr WHERE pr.article_id = a.id AND pr.customergroup_id = co.poscustomergroup_id AND pr.minmultiplier = 1),
(SELECT pr.net FROM price pr WHERE pr.article_id = a.id ORDER BY pr.id ASC LIMIT 1)
) AS net
FROM article a
INNER JOIN company co ON co.id = a.company_id
WHERE a.id = @articleId
`;
export const DELETE_PICS_BY_ARTICLE = `
DELETE FROM pic
WHERE id IN (SELECT pic_id FROM articlepic WHERE article_id = @articleId)

View File

@@ -2,4 +2,12 @@ import * as source from '../../mssql/queries/articlehistory.js';
import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'articlehistory');
export const { INSERT, LIST_BY_ARTICLE_ID } = queries;
export const { INSERT, LIST_BY_ARTICLE_ID } = queries;
export const LIST_BY_ARTICLE_ID_LIMITED = `
SELECT id, companyuser_id AS companyuserId, date, text
FROM articlehistory
WHERE article_id = @articleId
ORDER BY date DESC, id DESC
LIMIT @limit
`;

View File

@@ -2,4 +2,8 @@ import * as source from '../../mssql/queries/articletext.js';
import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'articletext');
export const { CREATE, UPDATE_BY_ARTICLE_AND_LANGUAGE } = queries;
export const {
CREATE,
UPDATE_BY_ARTICLE_AND_LANGUAGE,
LIST_SLUGS_BY_COMPANY_AND_LANGUAGE,
} = queries;

View File

@@ -0,0 +1,10 @@
import * as source from '../../mssql/queries/categoryattributevalue.js';
import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'categoryattributevalue');
export const {
LIST_BY_CATEGORY_ID,
DELETE_BY_CATEGORY_ID,
INSERT_ROW,
GET_VALUE_DETAIL,
} = queries;

View File

@@ -0,0 +1,10 @@
import * as source from '../../mssql/queries/categoryproperty.js';
import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'categoryproperty');
export const {
LIST_BY_CATEGORY_ID,
DELETE_BY_CATEGORY_ID,
DELETE_BY_CATEGORY_AND_PROPERTY_ID,
INSERT_ROW,
} = queries;

View File

@@ -3,7 +3,7 @@ import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'manifestDoc');
export const {
CREATE_LINE, CREATE_MANIFEST, DELETE_LINES_BY_MANIFEST, DELETE_MANIFEST,
GET_MANIFEST_HEADER, GET_MANIFEST_LINES, LIST_MANIFESTS, ORDER_TYPE,
QUOTE_TYPE, UPDATE_MANIFEST,
CHECK_ARTICLE_IS_FATHER, CREATE_LINE, CREATE_MANIFEST, DELETE_LINES_BY_MANIFEST,
DELETE_MANIFEST, GET_MANIFEST_HEADER, GET_MANIFEST_LINES, LIST_MANIFESTS,
ORDER_TYPE, QUOTE_TYPE, UPDATE_MANIFEST,
} = queries;

View File

@@ -5,7 +5,7 @@ const queries = translateQueries(source, 'posterminal');
export const {
CREATE, DELETE_BY_COMPANY_AND_ID, GET_BY_ID, LIST_BY_COMPANY,
LIST_CATEGORY_IDS, POSTERMINAL_IDS_BY_COMPANY, SET_OFF, SET_OFF_ALL, UPDATE,
FIND_BY_PAIRINGPIN, PAIR,
FIND_BY_PAIRINGPIN, PAIR, SET_MAX_KNOWN_TOMBSTONE_ID,
FIND_BY_TOKEN, COUNT_PRODUCTS, COUNT_CATEGORIES, COUNT_CUSTOMERS,
COUNT_CUSTOMER_GROUPS, COUNT_COMPOSITE_PRODUCTS, MAX_ORDER_ID,
LIST_POS_PRODUCT_CATEGORIES, LIST_POS_CUSTOMER_GROUP_IDS, LIST_POS_PRODUCT_PRICES,

View File

@@ -495,6 +495,23 @@ CREATE TABLE IF NOT EXISTS articlehistory (
);
`;
export const INIT_ARTICLETOMBSTONE = `
CREATE TABLE IF NOT EXISTS articletombstone (
id INTEGER PRIMARY KEY,
company_id INTEGER NOT NULL,
article_id INTEGER,
sku TEXT COLLATE NOCASE,
name TEXT,
taxrate NUMERIC,
net REAL,
deleted_at TEXT NOT NULL DEFAULT (${UTC_NOW}),
CHECK (article_id IS NOT NULL OR sku IS NOT NULL),
FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS IX_articletombstone_company_deleted
ON articletombstone (company_id, deleted_at);
`;
export const INIT_ENTITYHISTORY = `
CREATE TABLE IF NOT EXISTS entityhistory (
id INTEGER PRIMARY KEY,
@@ -539,6 +556,7 @@ CREATE TABLE IF NOT EXISTS posterminal (
pairingpin TEXT NOT NULL,
paired_at TEXT,
clientserial TEXT,
maxknowntombstoneid INTEGER,
FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS UQ_posterminal_token
@@ -684,6 +702,30 @@ CREATE TABLE IF NOT EXISTS articleattributevalue (
);
`;
export const INIT_CATEGORYPROPERTY = `
CREATE TABLE IF NOT EXISTS categoryproperty (
id INTEGER PRIMARY KEY,
category_id INTEGER NOT NULL,
property_id INTEGER NOT NULL,
value TEXT NOT NULL,
sort INTEGER NOT NULL DEFAULT 0,
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
FOREIGN KEY (property_id) REFERENCES propertyname(id) ON DELETE CASCADE
);
`;
export const INIT_CATEGORYATTRIBUTEVALUE = `
CREATE TABLE IF NOT EXISTS categoryattributevalue (
id INTEGER PRIMARY KEY,
category_id INTEGER NOT NULL,
attributevalue_id INTEGER NOT NULL,
sort INTEGER NOT NULL DEFAULT 0,
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
FOREIGN KEY (attributevalue_id) REFERENCES attributevalue(id) ON DELETE CASCADE,
UNIQUE (category_id, attributevalue_id)
);
`;
/** DDL scripts in dependency order for SQLite schema initialization. */
export const SCHEMA_SCRIPTS = [
INIT_META,
@@ -720,6 +762,8 @@ export const SCHEMA_SCRIPTS = [
INIT_ARTICLE_SUPPLIER,
INIT_ARTICLEPROPERTY,
INIT_ARTICLEATTRIBUTEVALUE,
INIT_CATEGORYPROPERTY,
INIT_CATEGORYATTRIBUTEVALUE,
INIT_MANIFEST,
INIT_MANIFESTARTICLE,
INIT_WAREHOUSE,
@@ -727,6 +771,7 @@ export const SCHEMA_SCRIPTS = [
INIT_NUMBERS,
INIT_COMPANYUSER,
INIT_ARTICLEHISTORY,
INIT_ARTICLETOMBSTONE,
INIT_ENTITYHISTORY,
INIT_SYNCPOS,
INIT_COMPANYSETTING,