u
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import * as mssqlQueries from '../../providers/mssql/queries/manifestDoc.js';
|
||||
import * as sqliteQueries from '../../providers/sqlite3/queries/manifestDoc.js';
|
||||
import * as mssqlLedgerQueries from '../../providers/mssql/queries/ledger.js';
|
||||
import * as sqliteLedgerQueries from '../../providers/sqlite3/queries/ledger.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveArticleBySku from '../article/resolveArticleBySku.js';
|
||||
import { recordStockAdjustmentHistory } from '../articlehistory/record.js';
|
||||
import { recordStockAdjustmentHistory, recordWarehouseHistory } from '../articlehistory/record.js';
|
||||
import { computePrevHash, shape } from '../ledger/add.js';
|
||||
import nextNumber from '../numbers/nextNumber.js';
|
||||
import ledgerAdd from '../ledger/add.js';
|
||||
import makeRunner from '../runner.js';
|
||||
@@ -24,6 +27,7 @@ export default function adjust(provider) {
|
||||
const addLedger = ledgerAdd(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||
const ledgerQueries = isSqlite ? sqliteLedgerQueries : mssqlLedgerQueries;
|
||||
|
||||
/**
|
||||
* Adjusts article stock manually by creating an implicit manifest of type "adjustment",
|
||||
@@ -42,6 +46,139 @@ export default function adjust(provider) {
|
||||
* @returns {Promise<{manifest: {id: number, number: string, type: string, date: string, createdAt: string}, lines: Array<object>, ledger: Array<object>}>}
|
||||
*/
|
||||
return async (googleAuthId, input = {}, tx) => {
|
||||
const rawManifestarticleId = input.manifestarticleId ?? input.manifestarticle_id;
|
||||
if (rawManifestarticleId != null) {
|
||||
const manifestarticleId = Number(rawManifestarticleId);
|
||||
if (!Number.isInteger(manifestarticleId) || manifestarticleId <= 0) {
|
||||
throw new Error('Invalid manifest article id');
|
||||
}
|
||||
|
||||
const amount = Number(input.amount);
|
||||
if (!Number.isFinite(amount) || amount === 0) {
|
||||
throw new Error('Amount must be a non-zero number');
|
||||
}
|
||||
|
||||
const runManifestarticleAdjust = async (runner, activeTx) => {
|
||||
const { companyId, companyuserId } = await access(googleAuthId, runner);
|
||||
|
||||
const checkRes = await runner.query(
|
||||
`SELECT ma.id, ma.manifest_id, ma.sku, ma.name, m.company_id, m.type AS manifest_type, m.number AS manifest_number
|
||||
FROM manifestarticle ma
|
||||
INNER JOIN manifest m ON m.id = ma.manifest_id
|
||||
WHERE ma.id = @manifestarticleId AND m.company_id = @companyId`,
|
||||
{ manifestarticleId, companyId },
|
||||
);
|
||||
const manifestArticle = checkRes.rows[0];
|
||||
if (!manifestArticle) {
|
||||
throw new Error('Manifest article not found');
|
||||
}
|
||||
|
||||
const sku = manifestArticle.sku ? String(manifestArticle.sku).trim() : '';
|
||||
if (!sku) {
|
||||
throw new Error('Manifest article has no SKU');
|
||||
}
|
||||
|
||||
const trackRes = await runner.query(
|
||||
`SELECT a.id, a.sku, a.track_stock, a.is_parent, a.articlelist_id FROM article a
|
||||
WHERE a.company_id = @companyId
|
||||
AND (a.sku = @sku OR EXISTS (SELECT 1 FROM articlesupplier asup WHERE asup.article_id = a.id AND asup.sku = @sku))`,
|
||||
{ companyId, sku },
|
||||
);
|
||||
const art = trackRes.rows[0];
|
||||
if (!art) {
|
||||
throw new Error(`Article not found (${sku})`);
|
||||
}
|
||||
|
||||
if (art.is_parent) {
|
||||
throw new Error(`A parent article cannot have stock (${sku})`);
|
||||
}
|
||||
if (art.articlelist_id != null) {
|
||||
throw new Error(`A Stückliste cannot have manual stock adjustments (${sku})`);
|
||||
}
|
||||
if (Number(art.track_stock ?? 1) === 0) {
|
||||
throw new Error(`Stock tracking is disabled for article (${sku})`);
|
||||
}
|
||||
|
||||
let warehouseId = input.warehouseId ?? input.warehouse_id;
|
||||
let warehouseName = '';
|
||||
if (warehouseId != null) {
|
||||
warehouseId = Number(warehouseId);
|
||||
if (!Number.isInteger(warehouseId) || warehouseId <= 0) {
|
||||
throw new Error('Warehouse must be a positive integer');
|
||||
}
|
||||
const whCheck = await runner.query(
|
||||
ledgerQueries.CHECK_WAREHOUSE_ACCESS,
|
||||
{ warehouseId, companyId },
|
||||
);
|
||||
if (!whCheck.rows[0]) throw new Error('Warehouse not found');
|
||||
warehouseName = whCheck.rows[0].name;
|
||||
} else {
|
||||
const defWh = await runner.query(
|
||||
ledgerQueries.GET_DEFAULT_WAREHOUSE,
|
||||
{ companyId },
|
||||
);
|
||||
if (!defWh.rows[0]) throw new Error('Warehouse not found');
|
||||
warehouseId = defWh.rows[0].id;
|
||||
warehouseName = defWh.rows[0].name;
|
||||
}
|
||||
|
||||
const text = input.text ?? input.transactionText ?? input.transaction_text ??
|
||||
(amount > 0 ? `Stock addition (+${amount})` : `Stock deduction (${amount})`);
|
||||
|
||||
const latest = await runner.query(ledgerQueries.GET_LATEST_ROW);
|
||||
const prevRow = latest.rows[0];
|
||||
const prevHash = computePrevHash(prevRow);
|
||||
|
||||
const inserted = await runner.query(ledgerQueries.INSERT_ROW, {
|
||||
manifestarticleId,
|
||||
warehouseId,
|
||||
transactionType: 'WAREHOUSE',
|
||||
amount,
|
||||
transactionText: text,
|
||||
hashVersion: 1,
|
||||
prevHash,
|
||||
});
|
||||
const ledgerRow = inserted.rows[0];
|
||||
|
||||
// Write warehouse history for tracked article
|
||||
if (manifestArticle.manifest_type === 'delivery') {
|
||||
await recordWarehouseHistory(runner, {
|
||||
articleId: art.id,
|
||||
companyuserId,
|
||||
manifestNumber: manifestArticle.manifest_number,
|
||||
manifestType: 'delivery',
|
||||
warehouseName,
|
||||
amount,
|
||||
transactionText: text,
|
||||
});
|
||||
} else if (manifestArticle.manifest_type === 'shipment') {
|
||||
await recordWarehouseHistory(runner, {
|
||||
articleId: art.id,
|
||||
companyuserId,
|
||||
manifestNumber: manifestArticle.manifest_number,
|
||||
manifestType: 'shipment',
|
||||
warehouseName,
|
||||
amount,
|
||||
transactionText: text,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
manifestarticle_id: manifestarticleId,
|
||||
warehouse_id: warehouseId,
|
||||
amount,
|
||||
text,
|
||||
ledger: shape(ledgerRow),
|
||||
};
|
||||
};
|
||||
|
||||
if (tx) return runManifestarticleAdjust(makeRunner(provider, tx), tx);
|
||||
if (typeof provider?.transaction === 'function') {
|
||||
return provider.transaction((runner, activeTx) => runManifestarticleAdjust(runner, activeTx));
|
||||
}
|
||||
return runManifestarticleAdjust(makeRunner(provider));
|
||||
}
|
||||
|
||||
const rawLines = Array.isArray(input.lines)
|
||||
? input.lines
|
||||
: [
|
||||
|
||||
Reference in New Issue
Block a user