This commit is contained in:
seb
2026-10-22 23:33:00 +02:00
parent d6e5da93cb
commit e31566e6ee
4 changed files with 121 additions and 2 deletions

View File

@@ -254,6 +254,28 @@ INSERT INTO categoryarticle (category_id, article_id)
VALUES (@categoryId, @articleId)
`;
export const LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE = `
SELECT DISTINCT pt.id AS posterminal_id
FROM posterminal pt
INNER JOIN posterminalcategory pc ON pc.posterminal_id = pt.id
INNER JOIN categoryarticle ca ON ca.category_id = pc.category_id
WHERE ca.article_id = @articleId
AND pt.company_id = @companyId
AND pt.token IS NOT NULL
`;
export const INSERT_POSTERMINAL_OBITUARY = `
INSERT INTO posterminalobituary (posterminal_id, entity_type, entity_id)
VALUES (@posterminalId, @entityType, @entityId)
`;
export const CLEAR_POSTERMINAL_OBITUARY = `
DELETE FROM posterminalobituary
WHERE posterminal_id = @posterminalId
AND entity_type = @entityType
AND entity_id = @entityId
`;
export const GET_BRAND_BY_COMPANY_AND_ID = `
SELECT id
FROM brand

View File

@@ -3,11 +3,13 @@ import { translateQueries } from './translate.js';
const queries = translateQueries(source, 'article');
export const {
ADD_CATEGORY, ADD_EAN, ARTICLE_LIST_COLUMNS, CHECK_ARTICLE_WAREHOUSE_STOCKS, CHECK_HAS_WAREHOUSE, CREATE, CREATE_CHILD,
ADD_CATEGORY, ADD_EAN, ARTICLE_LIST_COLUMNS, CHECK_ARTICLE_WAREHOUSE_STOCKS, CHECK_HAS_WAREHOUSE,
CLEAR_POSTERMINAL_OBITUARY, CREATE, CREATE_CHILD,
DELETE_CATEGORIES_BY_ARTICLE, DELETE_EANS_BY_ARTICLE, EAN_EXISTS, EAN_EXISTS_FOR_OTHER_ARTICLE,
GET_BRAND_BY_COMPANY_AND_ID,
GET_CATEGORY_ID_BY_SKU, GET_CATEGORY_TREE_FLAT, GET_ID_BY_SKU,
LIST_CHILDREN_BY_PARENT_ID,
INSERT_POSTERMINAL_OBITUARY,
LIST_CHILDREN_BY_PARENT_ID, LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE,
SET_PARENT_SORT,
SET_IS_PARENT, TOGGLE_PARENT, TOUCH_UPDATED_AT, UNLINK_CHILD, UPDATE_BRAND, UPDATE_PARENT_BY_SKU, UPDATE_TRACK_STOCK, UPDATE_UNIT,
UPDATE_UNITAMOUNT, UPDATE_UNIT_AND_AMOUNT, UPDATE_WEIGHT,

View File

@@ -1,11 +1,17 @@
import {
ADD_CATEGORY as MSSQL_ADD_CATEGORY,
CLEAR_POSTERMINAL_OBITUARY as MSSQL_CLEAR_OBITUARY,
DELETE_CATEGORIES_BY_ARTICLE as MSSQL_DELETE_CATEGORIES,
INSERT_POSTERMINAL_OBITUARY as MSSQL_INSERT_OBITUARY,
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as MSSQL_LIST_TERMINALS,
TOUCH_UPDATED_AT as MSSQL_TOUCH,
} from '../../providers/mssql/queries/article.js';
import {
ADD_CATEGORY as SQLITE_ADD_CATEGORY,
CLEAR_POSTERMINAL_OBITUARY as SQLITE_CLEAR_OBITUARY,
DELETE_CATEGORIES_BY_ARTICLE as SQLITE_DELETE_CATEGORIES,
INSERT_POSTERMINAL_OBITUARY as SQLITE_INSERT_OBITUARY,
LIST_PAIRED_POSTERMINAL_IDS_BY_ARTICLE as SQLITE_LIST_TERMINALS,
TOUCH_UPDATED_AT as SQLITE_TOUCH,
} from '../../providers/sqlite3/queries/article.js';
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
@@ -23,6 +29,9 @@ export default function setCategoryIdsBySku(provider) {
const addCategorySql = isSqlite ? SQLITE_ADD_CATEGORY : MSSQL_ADD_CATEGORY;
const deleteCategoriesSql = isSqlite ? SQLITE_DELETE_CATEGORIES : MSSQL_DELETE_CATEGORIES;
const touchArticleSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
const listTerminalsSql = isSqlite ? SQLITE_LIST_TERMINALS : MSSQL_LIST_TERMINALS;
const insertObituarySql = isSqlite ? SQLITE_INSERT_OBITUARY : MSSQL_INSERT_OBITUARY;
const clearObituarySql = isSqlite ? SQLITE_CLEAR_OBITUARY : MSSQL_CLEAR_OBITUARY;
/**
* Replaces the category membership of an article by its SKU.
@@ -77,6 +86,15 @@ export default function setCategoryIdsBySku(provider) {
}
}
// Find paired POS terminals where this article was visible before the category change
const terminalsBeforeRes = await runner.query(listTerminalsSql, {
articleId,
companyId,
});
const terminalsBefore = new Set(
terminalsBeforeRes.rows.map((r) => r.posterminal_id),
);
await runner.query(deleteCategoriesSql, { articleId });
for (const categoryId of normalized) {
@@ -86,6 +104,42 @@ export default function setCategoryIdsBySku(provider) {
});
}
// Find paired POS terminals where this article is visible after the category change
const terminalsAfterRes = await runner.query(listTerminalsSql, {
articleId,
companyId,
});
const terminalsAfter = new Set(
terminalsAfterRes.rows.map((r) => r.posterminal_id),
);
// 1. Terminals that had the article enabled before, but no longer have it in any enabled category:
// Record an obituary so POS sync removes the orphaned product.
for (const posterminalId of terminalsBefore) {
if (!terminalsAfter.has(posterminalId)) {
await runner.query(clearObituarySql, {
posterminalId,
entityType: 'article',
entityId: articleId,
});
await runner.query(insertObituarySql, {
posterminalId,
entityType: 'article',
entityId: articleId,
});
}
}
// 2. Terminals where the article IS enabled now:
// Clear any pending obituary so POS sync does not delete the active product.
for (const posterminalId of terminalsAfter) {
await runner.query(clearObituarySql, {
posterminalId,
entityType: 'article',
entityId: articleId,
});
}
// Write history if categories changed
await recordCategoryChangeHistory(runner, {
articleId,