This commit is contained in:
seb
2026-09-24 23:26:25 +02:00
parent 075b1f0ddc
commit f8f61a1212
40 changed files with 1245 additions and 337 deletions

View File

@@ -2,6 +2,8 @@ import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js'
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
import { CREATE as MSSQL_CREATE_PRICE } from '../../providers/mssql/queries/price.js';
import { CREATE as SQLITE_CREATE_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 resolveArticleBySku from '../article/resolveArticleBySku.js';
import ensureLieferantenGroup from '../supplier/ensureLieferantenGroup.js';
import taxEnsure from '../tax/ensure.js';
@@ -20,6 +22,7 @@ export default function create(provider) {
const queries = isSqlite ? sqliteQueries : mssqlQueries;
const createPriceSql = isSqlite ? SQLITE_CREATE_PRICE : MSSQL_CREATE_PRICE;
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
/**
* Assigns a supplier to an article, optionally creating a purchase price.
@@ -82,7 +85,11 @@ export default function create(provider) {
}
const runCreate = async (runner) => {
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
const { articleId, companyId, companyuserId } = await resolve(
googleAuthId,
sku,
runner,
);
await assertSupplier(runner, companyId, entityId);
@@ -153,7 +160,28 @@ export default function create(provider) {
companyId,
});
return shapeArticleSupplier(loadRes.rows[0]);
const supplierRow = loadRes.rows[0];
const supplierName =
supplierRow?.supplierName ?? (entityId ? `Lieferant #${entityId}` : 'Lieferant');
const details = [];
const actualSku = supplierRow?.sku ?? supplierSku;
if (actualSku) {
details.push(`Artikelnr: "${actualSku}"`);
}
const actualPrice = supplierRow?.priceNet ?? netPrice;
if (actualPrice !== null && actualPrice !== undefined) {
details.push(`EK: ${actualPrice}`);
}
const suffix = details.length ? ` (${details.join(', ')})` : '';
await runner.query(insertHistorySql, {
articleId,
companyuserId,
text: `Lieferant "${supplierName}" hinzugefügt${suffix}`,
});
return shapeArticleSupplier(supplierRow);
};
if (tx) {

View File

@@ -1,5 +1,7 @@
import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js';
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.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';
@@ -7,6 +9,7 @@ export default function del(provider) {
const resolve = resolveArticleBySku(provider);
const isSqlite = provider?.dialect === 'sqlite3';
const queries = isSqlite ? sqliteQueries : mssqlQueries;
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
/**
* Deletes a supplier assignment and cleans up its associated purchase price.
@@ -27,7 +30,11 @@ export default function del(provider) {
}
const runDelete = async (runner) => {
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
const { articleId, companyId, companyuserId } = await resolve(
googleAuthId,
sku,
runner,
);
const existingRes = await runner.query(queries.GET_BY_ID_AND_ARTICLE_ID, {
id,
@@ -51,6 +58,21 @@ export default function del(provider) {
articleId,
});
}
const supplierName =
existing.supplierName ?? (existing.entityId ? `Lieferant #${existing.entityId}` : 'Lieferant');
const details = [];
if (existing.sku) {
details.push(`Artikelnr: "${existing.sku}"`);
}
const suffix = details.length ? ` (${details.join(', ')})` : '';
await runner.query(insertHistorySql, {
articleId,
companyuserId,
text: `Lieferant "${supplierName}" entfernt${suffix}`,
});
};
if (tx) {

View File

@@ -2,6 +2,8 @@ import * as mssqlQueries from '../../providers/mssql/queries/articlesupplier.js'
import * as sqliteQueries from '../../providers/sqlite3/queries/articlesupplier.js';
import { CREATE as MSSQL_CREATE_PRICE } from '../../providers/mssql/queries/price.js';
import { CREATE as SQLITE_CREATE_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 resolveArticleBySku from '../article/resolveArticleBySku.js';
import ensureLieferantenGroup from '../supplier/ensureLieferantenGroup.js';
import taxEnsure from '../tax/ensure.js';
@@ -19,6 +21,7 @@ export default function update(provider) {
const queries = isSqlite ? sqliteQueries : mssqlQueries;
const createPriceSql = isSqlite ? SQLITE_CREATE_PRICE : MSSQL_CREATE_PRICE;
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
/**
* Updates an existing supplier assignment and its associated purchase price.
@@ -76,7 +79,11 @@ export default function update(provider) {
}
const runUpdate = async (runner) => {
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
const { articleId, companyId, companyuserId } = await resolve(
googleAuthId,
sku,
runner,
);
const existingRes = await runner.query(queries.GET_BY_ID_AND_ARTICLE_ID, {
id,
@@ -161,6 +168,22 @@ export default function update(provider) {
priceId = priceRes.rows[0]?.id ?? priceRes.insertId;
}
}
} else if (priceId != null && (patch.taxId !== undefined || patch.taxRate !== undefined)) {
let taxId = patch.taxId;
if (taxId == null || !Number.isFinite(taxId)) {
if (patch.taxRate != null && Number.isFinite(patch.taxRate)) {
taxId = await ensureTax(patch.taxRate, runner);
} else {
taxId = existing.priceTaxId;
}
}
await runner.query(queries.UPDATE_PRICE, {
id: priceId,
articleId,
net: existing.priceNet,
taxId,
});
}
const nextSku =
@@ -184,6 +207,70 @@ export default function update(provider) {
priceId,
});
const supplierName =
existing.supplierName ?? (existing.entityId ? `Lieferant #${existing.entityId}` : 'Lieferant');
const historyLines = [];
if (patch.sku !== undefined) {
const oldSku = existing.sku ?? '';
const newSku = nextSku ?? '';
if (oldSku !== newSku) {
historyLines.push(
`Lieferant "${supplierName}": Lieferanten-Artikelnr. geändert von "${oldSku}" auf "${newSku}"`,
);
}
}
if (patch.pu !== undefined && Number(patch.pu) !== Number(existing.pu)) {
historyLines.push(
`Lieferant "${supplierName}": VPE geändert von "${existing.pu}" auf "${nextPu}"`,
);
}
if (patch.stock !== undefined) {
const oldStock = existing.stock != null ? String(existing.stock) : '';
const newStock = nextStock != null ? String(nextStock) : '';
if (oldStock !== newStock) {
historyLines.push(
`Lieferant "${supplierName}": Lagerbestand geändert von "${oldStock}" auf "${newStock}"`,
);
}
}
if (patch.netPrice !== undefined) {
if (patch.netPrice === null) {
if (existing.priceId != null && existing.priceNet != null) {
historyLines.push(
`Lieferant "${supplierName}": Einkaufspreis geändert von "${existing.priceNet}" auf ""`,
);
}
} else {
const oldPrice = existing.priceNet != null ? String(existing.priceNet) : '';
const newPrice = String(patch.netPrice);
if (oldPrice !== newPrice) {
historyLines.push(
`Lieferant "${supplierName}": Einkaufspreis geändert von "${oldPrice}" auf "${newPrice}"`,
);
}
}
}
if (patch.taxRate !== undefined && patch.taxRate !== null && existing.priceTaxRate != null) {
if (Number(existing.priceTaxRate) !== Number(patch.taxRate)) {
historyLines.push(
`Lieferant "${supplierName}": MwSt. geändert von "${existing.priceTaxRate}%" auf "${patch.taxRate}%"`,
);
}
}
if (historyLines.length) {
await runner.query(insertHistorySql, {
articleId,
companyuserId,
text: historyLines.join('\n'),
});
}
const loadRes = await runner.query(queries.GET_BY_ID_AND_ARTICLE_ID, {
id,
articleId,