This commit is contained in:
seb
2026-10-18 14:07:01 +02:00
parent 97c909d10b
commit bf4109d8ec
5 changed files with 130 additions and 14 deletions

View File

@@ -11,6 +11,7 @@ import { CREATE as SQLITE_CREATE_PIC } from '../../providers/sqlite3/queries/pic
import processAvifImage from '../../util/processAvifImage.js';
import newFullHash from '../../util/newFullHash.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import { recordImageAddHistory } from '../articlehistory/record.js';
import makeRunner from '../runner.js';
export default function addImage(provider) {
@@ -39,7 +40,7 @@ export default function addImage(provider) {
const fullHash = newFullHash(processed.full.buffer);
const runAdd = async (runner) => {
const { articleId } = await resolve(googleAuthId, sku, runner);
const { articleId, companyuserId } = await resolve(googleAuthId, sku, runner);
const sortResult = await runner.query(getSortSql, { articleId });
const sort = sortResult.rows[0].sort;
@@ -96,6 +97,13 @@ export default function addImage(provider) {
picId,
sort,
});
await recordImageAddHistory(runner, {
articleId,
companyuserId,
fullHash,
sort: effectiveSort,
});
}
return {

View File

@@ -1,6 +1,7 @@
import { DELETE_BY_ARTICLE_AND_HASH as MSSQL_QUERY } from '../../providers/mssql/queries/pic.js';
import { DELETE_BY_ARTICLE_AND_HASH as SQLITE_QUERY } from '../../providers/sqlite3/queries/pic.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import { recordImageDeleteHistory } from '../articlehistory/record.js';
import makeRunner from '../runner.js';
export default function deleteImage(provider) {
@@ -21,21 +22,36 @@ export default function deleteImage(provider) {
* await store.article.deleteImage(42, 'SKU-1', 'abc123');
*/
return async (googleAuthId, sku, fullHash, tx) => {
const { articleId } = await resolve(googleAuthId, sku, tx);
const runner = makeRunner(provider, tx);
const result = await runner.query(sql, { articleId, fullHash });
const runDelete = async (runner) => {
const { articleId, companyuserId } = await resolve(googleAuthId, sku, runner);
const result = await runner.query(sql, { articleId, fullHash });
if (!result.rowsAffected) {
throw new Error('Image not found');
}
if (provider?.dialect === 'sqlite3') {
if (runner.deletePic) {
await runner.deletePic(fullHash);
} else if (provider?.deletePic) {
await provider.deletePic(fullHash);
if (!result.rowsAffected) {
throw new Error('Image not found');
}
if (provider?.dialect === 'sqlite3') {
if (runner.deletePic) {
await runner.deletePic(fullHash);
} else if (provider?.deletePic) {
await provider.deletePic(fullHash);
}
}
await recordImageDeleteHistory(runner, {
articleId,
companyuserId,
fullHash,
});
};
if (tx) {
return runDelete(makeRunner(provider, tx));
}
if (typeof provider?.transaction === 'function') {
return provider.transaction(runDelete);
}
return runDelete(makeRunner(provider));
};
}

View File

@@ -1,6 +1,7 @@
import * as mssqlPic from '../../providers/mssql/queries/articlepic.js';
import * as sqlitePic from '../../providers/sqlite3/queries/articlepic.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import { recordImageOrderHistory } from '../articlehistory/record.js';
import makeRunner from '../runner.js';
export default function orderImages(provider) {
@@ -29,7 +30,7 @@ export default function orderImages(provider) {
}
const runOrder = async (runner) => {
const { articleId } = await resolve(googleAuthId, sku, runner);
const { articleId, companyuserId } = await resolve(googleAuthId, sku, runner);
const current = await runner.query(queries.LIST_HASHES_BY_ARTICLE, { articleId });
const existing = new Set(current.rows.map((r) => r.fullHash));
@@ -60,6 +61,16 @@ export default function orderImages(provider) {
}
}
const oldOrder = current.rows.map((r) => r.fullHash);
const isSameOrder = oldOrder.length === fullHashes.length && oldOrder.every((h, i) => h === fullHashes[i]);
if (!isSameOrder) {
await recordImageOrderHistory(runner, {
articleId,
companyuserId,
fullHashes,
});
}
return { fullHashes };
};

View File

@@ -1018,3 +1018,78 @@ export async function recordOptionsListChangeHistory(runner, {
meta,
});
}
/**
* Records image addition to an article.
*/
export async function recordImageAddHistory(runner, {
articleId,
companyuserId,
date,
fullHash,
sort,
}) {
const text = typeof sort === 'number'
? `Bild hinzugefügt (Position ${sort + 1})`
: 'Bild hinzugefügt';
const meta = {
type: 'image_add',
fullHash,
sort,
};
return recordArticleHistory(runner, {
articleId,
companyuserId,
date,
text,
meta,
});
}
/**
* Records image deletion from an article.
*/
export async function recordImageDeleteHistory(runner, {
articleId,
companyuserId,
date,
fullHash,
}) {
const text = 'Bild gelöscht';
const meta = {
type: 'image_delete',
fullHash,
};
return recordArticleHistory(runner, {
articleId,
companyuserId,
date,
text,
meta,
});
}
/**
* Records image reordering for an article.
*/
export async function recordImageOrderHistory(runner, {
articleId,
companyuserId,
date,
fullHashes,
}) {
const count = Array.isArray(fullHashes) ? fullHashes.length : 0;
const text = `Bildreihenfolge geändert (${count} Bilder)`;
const meta = {
type: 'image_order',
fullHashes,
};
return recordArticleHistory(runner, {
articleId,
companyuserId,
date,
text,
meta,
});
}

View File

@@ -626,6 +626,12 @@ describe('store.article', () => {
() => store.article.deleteImage(gid, art.sku, img2.fullHash),
{ message: 'Image not found' },
);
const history = await store.article.getHistoryBySku(gid, art.sku);
const texts = history.map((h) => h.text);
assert.ok(texts.some((t) => t.includes('Bild hinzugefügt')));
assert.ok(texts.some((t) => t.includes('Bildreihenfolge geändert')));
assert.ok(texts.some((t) => t.includes('Bild gelöscht')));
});
});