u
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
GET_BRAND_BY_COMPANY_AND_ID as SQLITE_GET_BRAND,
|
||||
UPDATE_BRAND as SQLITE_UPDATE_BRAND,
|
||||
} from '../../providers/sqlite3/queries/article.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -17,6 +19,7 @@ export default function setBrandIdBySku(provider) {
|
||||
|
||||
const getBrandSql = isSqlite ? SQLITE_GET_BRAND : MSSQL_GET_BRAND;
|
||||
const updateBrandSql = isSqlite ? SQLITE_UPDATE_BRAND : MSSQL_UPDATE_BRAND;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Sets (or clears) the brand of an article by its SKU.
|
||||
@@ -34,7 +37,7 @@ export default function setBrandIdBySku(provider) {
|
||||
*/
|
||||
return async (googleAuthId, sku, brandId, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { articleId, languageId, companyId } = await resolve(
|
||||
const { articleId, languageId, companyId, companyuserId } = await resolve(
|
||||
googleAuthId,
|
||||
sku,
|
||||
runner,
|
||||
@@ -44,7 +47,15 @@ export default function setBrandIdBySku(provider) {
|
||||
throw new Error('Invalid brandId');
|
||||
}
|
||||
|
||||
// Read old brand for history
|
||||
const oldBrandRes = await runner.query(
|
||||
`SELECT b.name FROM article a LEFT JOIN brand b ON b.id = a.brand_id WHERE a.id = @articleId`,
|
||||
{ articleId },
|
||||
);
|
||||
const oldBrandName = oldBrandRes.rows[0]?.name ?? '';
|
||||
|
||||
let resolvedBrandId = null;
|
||||
let newBrandName = '';
|
||||
if (brandId !== null) {
|
||||
const brand = await runner.query(getBrandSql, {
|
||||
brandId,
|
||||
@@ -54,6 +65,7 @@ export default function setBrandIdBySku(provider) {
|
||||
throw new Error('Brand not found');
|
||||
}
|
||||
resolvedBrandId = brandId;
|
||||
newBrandName = brand.rows[0].name ?? '';
|
||||
}
|
||||
|
||||
const result = await runner.query(updateBrandSql, {
|
||||
@@ -65,6 +77,15 @@ export default function setBrandIdBySku(provider) {
|
||||
throw new Error('Article not found');
|
||||
}
|
||||
|
||||
// Write history if brand changed
|
||||
if (oldBrandName !== newBrandName) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Marke geändert von "${oldBrandName}" auf "${newBrandName}"`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
ADD_CATEGORY as SQLITE_ADD_CATEGORY,
|
||||
DELETE_CATEGORIES_BY_ARTICLE as SQLITE_DELETE_CATEGORIES,
|
||||
} from '../../providers/sqlite3/queries/article.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
@@ -19,6 +21,7 @@ export default function setCategoryIdsBySku(provider) {
|
||||
|
||||
const addCategorySql = isSqlite ? SQLITE_ADD_CATEGORY : MSSQL_ADD_CATEGORY;
|
||||
const deleteCategoriesSql = isSqlite ? SQLITE_DELETE_CATEGORIES : MSSQL_DELETE_CATEGORIES;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Replaces the category membership of an article by its SKU.
|
||||
@@ -52,12 +55,19 @@ export default function setCategoryIdsBySku(provider) {
|
||||
}
|
||||
|
||||
const runSet = async (runner) => {
|
||||
const { articleId, languageId, companyId } = await resolve(
|
||||
const { articleId, languageId, companyId, companyuserId } = await resolve(
|
||||
googleAuthId,
|
||||
sku,
|
||||
runner,
|
||||
);
|
||||
|
||||
// Read old category IDs for history
|
||||
const oldCatRes = await runner.query(
|
||||
'SELECT category_id FROM categoryarticle WHERE article_id = @articleId ORDER BY category_id',
|
||||
{ articleId },
|
||||
);
|
||||
const oldCategoryIds = oldCatRes.rows.map((r) => r.category_id);
|
||||
|
||||
for (const categoryId of normalized) {
|
||||
// Ensures the category belongs to the same company as the article.
|
||||
const access = await categoryAccess(googleAuthId, categoryId, runner);
|
||||
@@ -75,6 +85,17 @@ export default function setCategoryIdsBySku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
// Write history if categories changed
|
||||
const oldStr = oldCategoryIds.join(', ');
|
||||
const newStr = [...normalized].sort((a, b) => a - b).join(', ');
|
||||
if (oldStr !== newStr) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Kategorien geändert von [${oldStr}] auf [${newStr}]`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
ADD_EAN as SQLITE_ADD_EAN,
|
||||
DELETE_EANS_BY_ARTICLE as SQLITE_DELETE_EANS,
|
||||
} from '../../providers/sqlite3/queries/article.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
@@ -18,6 +20,7 @@ export default function setEansBySku(provider) {
|
||||
|
||||
const addEanSql = isSqlite ? SQLITE_ADD_EAN : MSSQL_ADD_EAN;
|
||||
const deleteEansSql = isSqlite ? SQLITE_DELETE_EANS : MSSQL_DELETE_EANS;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Replaces the EAN list of an article by its SKU.
|
||||
@@ -52,7 +55,14 @@ export default function setEansBySku(provider) {
|
||||
}
|
||||
|
||||
const runSet = async (runner) => {
|
||||
const { articleId, languageId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, languageId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
// Read old EANs for history
|
||||
const oldEanRes = await runner.query(
|
||||
'SELECT ean FROM articleean WHERE article_id = @articleId ORDER BY ean',
|
||||
{ articleId },
|
||||
);
|
||||
const oldEans = oldEanRes.rows.map((r) => r.ean);
|
||||
|
||||
await runner.query(deleteEansSql, { articleId });
|
||||
|
||||
@@ -67,6 +77,17 @@ export default function setEansBySku(provider) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Write history if EANs changed
|
||||
const oldStr = oldEans.join(', ');
|
||||
const newStr = [...normalized].sort().join(', ');
|
||||
if (oldStr !== newStr) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `EANs geändert von "${oldStr}" auf "${newStr}"`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
CREATE as SQLITE_CREATE_PRICE,
|
||||
DELETE_BY_ARTICLE_AND_CUSTOMERGROUP as SQLITE_DELETE_PRICE,
|
||||
} from '../../providers/sqlite3/queries/price.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import taxEnsure from '../tax/ensure.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
@@ -55,6 +57,7 @@ export default function setPricesBySku(provider) {
|
||||
|
||||
const createPriceSql = isSqlite ? SQLITE_CREATE_PRICE : MSSQL_CREATE_PRICE;
|
||||
const deletePriceSql = isSqlite ? SQLITE_DELETE_PRICE : MSSQL_DELETE_PRICE;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Replaces the price list of an article by its SKU.
|
||||
@@ -74,7 +77,7 @@ export default function setPricesBySku(provider) {
|
||||
const normalized = normalizePrices(prices);
|
||||
|
||||
const runSet = async (runner) => {
|
||||
const { articleId, languageId, posCustomerGroupId } = await resolve(
|
||||
const { articleId, languageId, posCustomerGroupId, companyuserId } = await resolve(
|
||||
googleAuthId,
|
||||
sku,
|
||||
runner,
|
||||
@@ -88,6 +91,17 @@ export default function setPricesBySku(provider) {
|
||||
throw new Error('A father article cannot have prices');
|
||||
}
|
||||
|
||||
// Read old prices for history
|
||||
const oldPriceRes = await runner.query(
|
||||
`SELECT p.net, t.rate AS taxRate, p.minmultiplier
|
||||
FROM price p
|
||||
LEFT JOIN tax t ON t.id = p.tax_id
|
||||
WHERE p.article_id = @articleId AND p.customergroup_id = @posCustomerGroupId
|
||||
ORDER BY p.minmultiplier ASC`,
|
||||
{ articleId, posCustomerGroupId },
|
||||
);
|
||||
const oldPrices = oldPriceRes.rows;
|
||||
|
||||
const taxIds = new Map();
|
||||
for (const entry of normalized) {
|
||||
if (!taxIds.has(entry.tax)) {
|
||||
@@ -110,6 +124,18 @@ export default function setPricesBySku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
// Write history if prices changed
|
||||
const fmtPrice = (p) => `${p.net}@${p.taxRate ?? 0}%`;
|
||||
const oldStr = oldPrices.map(fmtPrice).join(', ');
|
||||
const newStr = normalized.map((e) => `${e.price}@${e.tax}%`).join(', ');
|
||||
if (oldStr !== newStr) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Preise geändert von [${oldStr}] auf [${newStr}]`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { UPDATE_TRACK_STOCK as MSSQL_UPDATE_TRACK_STOCK } from '../../providers/mssql/queries/article.js';
|
||||
import { UPDATE_TRACK_STOCK as SQLITE_UPDATE_TRACK_STOCK } from '../../providers/sqlite3/queries/article.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -11,6 +13,7 @@ export default function setTrackStockBySku(provider) {
|
||||
provider?.dialect === 'sqlite3'
|
||||
? SQLITE_UPDATE_TRACK_STOCK
|
||||
: MSSQL_UPDATE_TRACK_STOCK;
|
||||
const insertHistorySql = provider?.dialect === 'sqlite3' ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Sets the track_stock flag of an article by its SKU.
|
||||
@@ -32,7 +35,15 @@ export default function setTrackStockBySku(provider) {
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { articleId, languageId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, languageId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
// Read old track_stock for history
|
||||
const oldRes = await runner.query(
|
||||
'SELECT track_stock FROM article WHERE id = @articleId',
|
||||
{ articleId },
|
||||
);
|
||||
const oldTrack = Boolean(oldRes.rows[0]?.track_stock ?? 1);
|
||||
const newTrack = Boolean(trackStock);
|
||||
|
||||
const result = await runner.query(sql, {
|
||||
articleId,
|
||||
@@ -43,6 +54,15 @@ export default function setTrackStockBySku(provider) {
|
||||
throw new Error('Article not found');
|
||||
}
|
||||
|
||||
// Write history if track_stock changed
|
||||
if (oldTrack !== newTrack) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Bestandsführung geändert von "${oldTrack ? 'Ja' : 'Nein'}" auf "${newTrack ? 'Ja' : 'Nein'}"`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { UPDATE_WEIGHT as MSSQL_UPDATE_WEIGHT } from '../../providers/mssql/queries/article.js';
|
||||
import { UPDATE_WEIGHT as SQLITE_UPDATE_WEIGHT } from '../../providers/sqlite3/queries/article.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -8,6 +10,7 @@ export default function setWeightBySku(provider) {
|
||||
const resolve = resolveArticleBySku(provider);
|
||||
const load = queryBySku(provider);
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_UPDATE_WEIGHT : MSSQL_UPDATE_WEIGHT;
|
||||
const insertHistorySql = provider?.dialect === 'sqlite3' ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Sets the weight of an article by its SKU.
|
||||
@@ -29,7 +32,14 @@ export default function setWeightBySku(provider) {
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { articleId, languageId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, languageId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
// Read old weight for history
|
||||
const oldRes = await runner.query(
|
||||
'SELECT weight FROM article WHERE id = @articleId',
|
||||
{ articleId },
|
||||
);
|
||||
const oldWeight = oldRes.rows[0]?.weight ?? 0;
|
||||
|
||||
const result = await runner.query(sql, {
|
||||
articleId,
|
||||
@@ -40,6 +50,15 @@ export default function setWeightBySku(provider) {
|
||||
throw new Error('Article not found');
|
||||
}
|
||||
|
||||
// Write history if weight changed
|
||||
if (Number(oldWeight) !== weight) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Gewicht geändert von "${oldWeight}" auf "${weight}"`,
|
||||
});
|
||||
}
|
||||
|
||||
const article = await load(articleId, languageId, runner);
|
||||
if (!article) {
|
||||
throw new Error('Article not found');
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
INSERT_ROW as SQLITE_INSERT,
|
||||
GET_VALUE_DETAIL as SQLITE_GET_DETAIL,
|
||||
} from '../../providers/sqlite3/queries/articleattributevalue.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
@@ -17,6 +19,7 @@ export default function setByArticleSku(provider) {
|
||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||
const getDetailSql = isSqlite ? SQLITE_GET_DETAIL : MSSQL_GET_DETAIL;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Replaces all attribute values for an article by its SKU.
|
||||
@@ -34,7 +37,19 @@ export default function setByArticleSku(provider) {
|
||||
}
|
||||
|
||||
const runSet = async (runner) => {
|
||||
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, companyId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
// Read old attribute values for history
|
||||
const oldAttrRes = await runner.query(
|
||||
`SELECT aav.attributevalue_id AS attributeValueId, an.name AS attributeName, av.value
|
||||
FROM articleattributevalue aav
|
||||
INNER JOIN attributevalue av ON av.id = aav.attributevalue_id
|
||||
INNER JOIN attributename an ON an.id = av.attributename_id
|
||||
WHERE aav.article_id = @articleId
|
||||
ORDER BY aav.sort ASC, aav.id ASC`,
|
||||
{ articleId },
|
||||
);
|
||||
const oldAttrs = oldAttrRes.rows;
|
||||
|
||||
const validated = [];
|
||||
const seenValues = new Set();
|
||||
@@ -137,6 +152,18 @@ export default function setByArticleSku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
// Write history if attribute values changed
|
||||
const fmtAttr = (a) => `${a.attributeName}: ${a.value}`;
|
||||
const oldStr = oldAttrs.map(fmtAttr).join(', ');
|
||||
const newStr = validated.map(fmtAttr).join(', ');
|
||||
if (oldStr !== newStr) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Attributwerte geändert von [${oldStr}] auf [${newStr}]`,
|
||||
});
|
||||
}
|
||||
|
||||
return inserted;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as mssqlQueries from '../../providers/mssql/queries/articlelist.js';
|
||||
import * as sqliteQueries from '../../providers/sqlite3/queries/articlelist.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import getItemsByArticleSku from './getItemsByArticleSku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -42,6 +44,7 @@ export default function setItemsByArticleSku(provider) {
|
||||
const getItems = getItemsByArticleSku(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Sets or clears the Stückliste (bundle items) for an article.
|
||||
@@ -58,7 +61,7 @@ export default function setItemsByArticleSku(provider) {
|
||||
}
|
||||
|
||||
const run = async (runner) => {
|
||||
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, companyId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
const artRes = await runner.query(
|
||||
'SELECT id, is_father, articlelist_id, optionslist_id FROM article WHERE id = @articleId',
|
||||
@@ -76,6 +79,18 @@ export default function setItemsByArticleSku(provider) {
|
||||
// If items is empty: clear Stückliste
|
||||
if (items.length === 0) {
|
||||
if (article.articlelist_id != null) {
|
||||
// Read old items for history before clearing
|
||||
const oldItemRes = await runner.query(
|
||||
`SELECT a.sku, at.name, ala.count
|
||||
FROM articlelistarticle ala
|
||||
INNER JOIN article a ON a.id = ala.article_id
|
||||
LEFT JOIN articletext at ON at.article_id = a.id
|
||||
WHERE ala.articlelist_id = @articlelistId
|
||||
ORDER BY ala.sort ASC, ala.id ASC`,
|
||||
{ articlelistId: article.articlelist_id },
|
||||
);
|
||||
const oldItemNames = oldItemRes.rows.map((r) => `${r.count}x ${r.name || r.sku}`);
|
||||
|
||||
await runner.query(queries.SET_ARTICLE_ARTICLELIST_ID, {
|
||||
articleId,
|
||||
articlelistId: null,
|
||||
@@ -83,6 +98,14 @@ export default function setItemsByArticleSku(provider) {
|
||||
await runner.query(queries.DELETE_ARTICLELIST, {
|
||||
id: article.articlelist_id,
|
||||
});
|
||||
|
||||
if (oldItemNames.length) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Stückliste geleert (war: [${oldItemNames.join(', ')}])`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -195,7 +218,17 @@ export default function setItemsByArticleSku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
return getItems(googleAuthId, sku, runner);
|
||||
const result = await getItems(googleAuthId, sku, runner);
|
||||
|
||||
// Write history for Stückliste change
|
||||
const newNames = result.map((r) => `${r.count}x ${r.name || r.sku}`);
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Stückliste gesetzt: [${newNames.join(', ')}]`,
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
if (tx) {
|
||||
|
||||
@@ -12,6 +12,8 @@ import {
|
||||
import {
|
||||
GET_BY_COMPANY_AND_ID as SQLITE_GET_PROP,
|
||||
} from '../../providers/sqlite3/queries/propertyname.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
@@ -21,6 +23,7 @@ export default function setByArticleSku(provider) {
|
||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
const insertSql = isSqlite ? SQLITE_INSERT : MSSQL_INSERT;
|
||||
const getPropSql = isSqlite ? SQLITE_GET_PROP : MSSQL_GET_PROP;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Replaces all properties for an article by its SKU.
|
||||
@@ -38,7 +41,18 @@ export default function setByArticleSku(provider) {
|
||||
}
|
||||
|
||||
const runSet = async (runner) => {
|
||||
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, companyId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
// Read old properties for history
|
||||
const oldPropsRes = await runner.query(
|
||||
`SELECT ap.property_id AS propertyId, pn.name, ap.value
|
||||
FROM articleproperty ap
|
||||
INNER JOIN propertyname pn ON pn.id = ap.property_id
|
||||
WHERE ap.article_id = @articleId
|
||||
ORDER BY ap.sort ASC, ap.id ASC`,
|
||||
{ articleId },
|
||||
);
|
||||
const oldProps = oldPropsRes.rows;
|
||||
|
||||
const validated = [];
|
||||
const seenExclusiveProps = new Set();
|
||||
@@ -97,6 +111,18 @@ export default function setByArticleSku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
// Write history if properties changed
|
||||
const fmtProp = (p) => `${p.name}=${p.value}`;
|
||||
const oldStr = oldProps.map(fmtProp).join(', ');
|
||||
const newStr = validated.map(fmtProp).join(', ');
|
||||
if (oldStr !== newStr) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Eigenschaften geändert von [${oldStr}] auf [${newStr}]`,
|
||||
});
|
||||
}
|
||||
|
||||
return inserted;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as mssqlQueries from '../../providers/mssql/queries/optionslist.js';
|
||||
import * as sqliteQueries from '../../providers/sqlite3/queries/optionslist.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import getOptionsByArticleSku from './getOptionsByArticleSku.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -42,6 +44,7 @@ export default function setOptionsByArticleSku(provider) {
|
||||
const getOptions = getOptionsByArticleSku(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Sets or clears the options list for an article.
|
||||
@@ -58,7 +61,7 @@ export default function setOptionsByArticleSku(provider) {
|
||||
}
|
||||
|
||||
const run = async (runner) => {
|
||||
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
|
||||
const { articleId, companyId, companyuserId } = await resolve(googleAuthId, sku, runner);
|
||||
|
||||
const artRes = await runner.query(
|
||||
'SELECT id, is_father, articlelist_id, optionslist_id FROM article WHERE id = @articleId',
|
||||
@@ -76,6 +79,18 @@ export default function setOptionsByArticleSku(provider) {
|
||||
// If options is empty: clear optionslist
|
||||
if (options.length === 0) {
|
||||
if (article.optionslist_id != null) {
|
||||
// Read old options for history before clearing
|
||||
const oldOptRes = await runner.query(
|
||||
`SELECT a.sku, at.name
|
||||
FROM optionslistarticle ola
|
||||
INNER JOIN article a ON a.id = ola.article_id
|
||||
LEFT JOIN articletext at ON at.article_id = a.id
|
||||
WHERE ola.optionslist_id = @optionslistId
|
||||
ORDER BY ola.sort ASC, ola.id ASC`,
|
||||
{ optionslistId: article.optionslist_id },
|
||||
);
|
||||
const oldOptNames = oldOptRes.rows.map((r) => r.name || r.sku);
|
||||
|
||||
await runner.query(queries.SET_ARTICLE_OPTIONSLIST_ID, {
|
||||
articleId,
|
||||
optionslistId: null,
|
||||
@@ -83,6 +98,14 @@ export default function setOptionsByArticleSku(provider) {
|
||||
await runner.query(queries.DELETE_OPTIONSLIST, {
|
||||
id: article.optionslist_id,
|
||||
});
|
||||
|
||||
if (oldOptNames.length) {
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Optionsliste geleert (war: [${oldOptNames.join(', ')}])`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -202,7 +225,17 @@ export default function setOptionsByArticleSku(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
return getOptions(googleAuthId, sku, runner);
|
||||
const result = await getOptions(googleAuthId, sku, runner);
|
||||
|
||||
// Write history for options list change
|
||||
const newNames = result.map((r) => r.name || r.sku);
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId,
|
||||
companyuserId,
|
||||
text: `Optionsliste gesetzt: [${newNames.join(', ')}]`,
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
if (tx) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as mssqlQueries from '../../providers/mssql/queries/manifestDoc.js';
|
||||
import * as sqliteQueries from '../../providers/sqlite3/queries/manifestDoc.js';
|
||||
import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
|
||||
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import nextNumber from '../numbers/nextNumber.js';
|
||||
@@ -23,6 +25,7 @@ export default function adjust(provider) {
|
||||
const addLedger = ledgerAdd(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
|
||||
|
||||
/**
|
||||
* Adjusts article stock manually by creating an implicit manifest of type "adjustment",
|
||||
@@ -107,7 +110,7 @@ export default function adjust(provider) {
|
||||
});
|
||||
|
||||
const run = async (runner, activeTx) => {
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
const { companyId, companyuserId } = await access(googleAuthId, runner);
|
||||
|
||||
// Validate all articles exist and belong to the user's company
|
||||
const resolvedArticles = [];
|
||||
@@ -228,6 +231,16 @@ export default function adjust(provider) {
|
||||
});
|
||||
|
||||
createdLedgerEntries.push(ledgerRow);
|
||||
|
||||
// Write article history for the adjusted article
|
||||
if (item.articleId) {
|
||||
const sign = item.amount > 0 ? '+' : '';
|
||||
await runner.query(insertHistorySql, {
|
||||
articleId: item.articleId,
|
||||
companyuserId,
|
||||
text: `Bestandskorrektur ${sign}${item.amount} (${item.text})`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user