This commit is contained in:
seb
2026-10-12 18:36:57 +02:00
parent 10b1d53f9d
commit 64d1772842
8 changed files with 72 additions and 24 deletions

View File

@@ -19,7 +19,13 @@ SELECT
p.hash AS fullHash,
p.thumbw AS thumbW,
p.thumbh AS thumbH,
p.thumbhash AS thumbHash
p.thumbhash AS thumbHash,
(
SELECT COUNT(*)
FROM categoryarticle ca
INNER JOIN article a ON a.id = ca.article_id
WHERE ca.category_id = t.id AND a.parentarticle_id IS NULL
) AS articleCount
FROM tree t
LEFT JOIN categorytext ct
ON ct.category_id = t.id AND ct.language_id = @languageId
@@ -33,6 +39,19 @@ LEFT JOIN pic p ON p.id = first_pic.pic_id
ORDER BY t.sort, t.id
`;
export const COUNT_ARTICLES_IN_TREE = `
WITH tree AS (
SELECT id FROM category WHERE id = @rootId
UNION ALL
SELECT c.id FROM category c INNER JOIN tree t ON c.parent_id = t.id
)
SELECT COUNT(DISTINCT ca.article_id) AS total
FROM categoryarticle ca
INNER JOIN article a ON a.id = ca.article_id
WHERE ca.category_id IN (SELECT id FROM tree)
AND a.parentarticle_id IS NULL
`;
import {
ARTICLE_LIST_COLUMNS,
ARTICLE_LIST_JOINS,

View File

@@ -52,11 +52,13 @@ SELECT
c.name,
c.root_category_id AS rootCategoryId,
c.default_language_id AS languageId,
l.iso639,
tr.rate AS taxrate,
rtr.rate AS reducedtaxrate,
tfr.rate AS taxfreerate
FROM company c
INNER JOIN companyuser cu ON cu.company_id = c.id
LEFT JOIN language l ON l.id = c.default_language_id
LEFT JOIN tax tr ON tr.id = c.taxrate
LEFT JOIN tax rtr ON rtr.id = c.reducedtaxrate
LEFT JOIN tax tfr ON tfr.id = c.taxfreerate

View File

@@ -79,7 +79,13 @@ WITH RECURSIVE tree AS (
SELECT
t.id, t.parent_id AS parentId, t.sort, ct.name, ct.slug,
p.hash AS fullHash, p.thumbw AS thumbW, p.thumbh AS thumbH,
p.thumbhash AS thumbHash
p.thumbhash AS thumbHash,
(
SELECT COUNT(*)
FROM categoryarticle ca
INNER JOIN article a ON a.id = ca.article_id
WHERE ca.category_id = t.id AND a.parentarticle_id IS NULL
) AS articleCount
FROM tree t
LEFT JOIN categorytext ct
ON ct.category_id = t.id AND ct.language_id = @languageId
@@ -89,4 +95,17 @@ LEFT JOIN pic p ON p.id = (
ORDER BY cp.sort, cp.id LIMIT 1
)
ORDER BY t.sort, t.id
`;
export const COUNT_ARTICLES_IN_TREE = `
WITH RECURSIVE tree AS (
SELECT id FROM category WHERE id = @rootId
UNION ALL
SELECT c.id FROM category c INNER JOIN tree t ON c.parent_id = t.id
)
SELECT COUNT(DISTINCT ca.article_id) AS total
FROM categoryarticle ca
INNER JOIN article a ON a.id = ca.article_id
WHERE ca.category_id IN (SELECT id FROM tree)
AND a.parentarticle_id IS NULL
`;

View File

@@ -1,52 +1,60 @@
import { GET_TREE_FOR_COMPANY as MSSQL_GET_TREE } from '../../providers/mssql/queries/category.js';
import { GET_TREE_FOR_COMPANY as SQLITE_GET_TREE } from '../../providers/sqlite3/queries/category.js';
import {
GET_TREE_FOR_COMPANY as MSSQL_GET_TREE,
COUNT_ARTICLES_IN_TREE as MSSQL_COUNT_ARTICLES,
} from '../../providers/mssql/queries/category.js';
import {
GET_TREE_FOR_COMPANY as SQLITE_GET_TREE,
COUNT_ARTICLES_IN_TREE as SQLITE_COUNT_ARTICLES,
} from '../../providers/sqlite3/queries/category.js';
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
import queryCategoryArticles from './queryCategoryArticles.js';
import getCategoryPosterminalIds from '../posterminal/getCategoryPosterminalIds.js';
import makeRunner from '../runner.js';
export default function getTreeForCompany(provider) {
const access = resolveSelectedCompanyAccess(provider);
const articles = queryCategoryArticles(provider);
const posterminalIds = getCategoryPosterminalIds(provider);
const sql =
provider?.dialect === 'sqlite3' ? SQLITE_GET_TREE : MSSQL_GET_TREE;
const isSqlite = provider?.dialect === 'sqlite3';
const sql = isSqlite ? SQLITE_GET_TREE : MSSQL_GET_TREE;
const countSql = isSqlite ? SQLITE_COUNT_ARTICLES : MSSQL_COUNT_ARTICLES;
/**
* Returns the full category tree for the user's selected company together
* with its articles and the posterminal ids assigned to each category.
* with the article count and the posterminal ids assigned to each category.
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<{languageId: number, tree: Array<object>, articles: Array<object>}>} The category tree, articles and language.
* @returns {Promise<{languageId: number, tree: Array<{id: number, parentId: number|null, sort: number, name: string|null, slug: string|null, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null, articleCount: number, posterminalIds: number[]}>, articleCount: number}>} The category tree and article count.
*
* @example
* const tree = await store.category.getTreeForCompany(42);
* // => { languageId, tree: [{ id, posterminalIds, ... }], articles: [...] }
* // => { languageId, tree: [{ id, articleCount, posterminalIds, ... }], articleCount: 25 }
*/
return async (googleAuthId, tx) => {
const { companyId, rootCategoryId, languageId, posCustomerGroupId } =
const { companyId, rootCategoryId, languageId } =
await access(googleAuthId, tx);
const runner = makeRunner(provider, tx);
const [treeResult, articleRows, ptMap] = await Promise.all([
const [treeResult, countResult, ptMap] = await Promise.all([
runner.query(sql, {
rootId: rootCategoryId,
languageId,
}),
articles({ categoryId: rootCategoryId, languageId, posCustomerGroupId }, tx),
runner.query(countSql, {
rootId: rootCategoryId,
}),
posterminalIds(companyId, tx),
]);
const tree = treeResult.rows.map((row) => ({
...row,
articleCount: Number(row.articleCount ?? 0),
posterminalIds: ptMap[row.id] ?? [],
}));
return {
languageId,
tree,
articles: articleRows,
articleCount: Number(countResult.rows[0]?.total ?? 0),
};
};
}

View File

@@ -10,11 +10,11 @@ export default function list(provider) {
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<Array<object>>} The accessible company rows.
* @returns {Promise<Array<{id: number, name: string, rootCategoryId: number, languageId: number, iso639: string|null, taxrate: number, reducedtaxrate: number, taxfreerate: number}>>} The accessible company rows.
*
* @example
* const companies = await store.company.list(42);
* // => [{ id, name, ... }]
* // => [{ id, name, rootCategoryId, languageId, iso639, taxrate, reducedtaxrate, taxfreerate }]
*/
return async (googleAuthId, tx) => {
const result = await makeRunner(provider, tx).query(sql, { googleAuthId });