u
This commit is contained in:
146
scripts/test-stueckliste-stock.js
Normal file
146
scripts/test-stueckliste-stock.js
Normal file
@@ -0,0 +1,146 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import LibDashStore from '../src/index.js';
|
||||
import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js';
|
||||
|
||||
async function run() {
|
||||
console.log('--- Testing Stückliste Stock Reporting and Adjustment ---');
|
||||
|
||||
const tempDir = mkdtempSync(join(tmpdir(), 'test-stueckliste-'));
|
||||
const dbFile = join(tempDir, 'test.db');
|
||||
const storageDir = join(tempDir, 'storage');
|
||||
|
||||
const provider = new BetterSqlite3Provider({
|
||||
filename: dbFile,
|
||||
storageDir,
|
||||
});
|
||||
|
||||
await provider.initialize();
|
||||
const store = await new LibDashStore(provider);
|
||||
|
||||
try {
|
||||
const googleAuthId = await store.google_auth.add('stueckliste-stock@example.com');
|
||||
const company = await store.company.create({
|
||||
name: 'Stückliste Stock Corp',
|
||||
iso639: 'de',
|
||||
taxrate: 19,
|
||||
reducedtaxrate: 7,
|
||||
googleAuthId,
|
||||
});
|
||||
await store.google_auth.setSelectedCompany(googleAuthId, company.id);
|
||||
|
||||
// Create 2 warehouses
|
||||
const wh1 = await store.warehouse.create(googleAuthId, { name: 'Hauptlager' });
|
||||
const wh2 = await store.warehouse.create(googleAuthId, { name: 'Filiale' });
|
||||
|
||||
// Create 2 component articles
|
||||
const comp1 = await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: company.rootCategoryId,
|
||||
name: 'Component Article 1',
|
||||
});
|
||||
const comp2 = await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: company.rootCategoryId,
|
||||
name: 'Component Article 2',
|
||||
});
|
||||
|
||||
// Create a bundle article
|
||||
const bundle = await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: company.rootCategoryId,
|
||||
name: 'Stückliste Bundle',
|
||||
});
|
||||
|
||||
// Configure Stückliste: 1x comp1 + 2x comp2
|
||||
await store.articlelist.setItemsByArticleSku(googleAuthId, bundle.sku, [
|
||||
{ sku: comp1.sku, count: 1, sort: 0 },
|
||||
{ sku: comp2.sku, count: 2, sort: 1 },
|
||||
]);
|
||||
|
||||
// Initial check: all have 0 stock
|
||||
const initialBundle = await store.article.getBySku(googleAuthId, bundle.sku);
|
||||
assert.equal(initialBundle.article.warehouses.find((w) => w.id === wh1.id).stock, 0);
|
||||
assert.equal(initialBundle.article.warehouses.find((w) => w.id === wh2.id).stock, 0);
|
||||
|
||||
// Book 10x comp1 and 10x comp2 into Hauptlager
|
||||
await store.stock.adjust(googleAuthId, {
|
||||
lines: [
|
||||
{ sku: comp1.sku, warehouseId: wh1.id, amount: 10, text: 'Initial comp1' },
|
||||
{ sku: comp2.sku, warehouseId: wh1.id, amount: 10, text: 'Initial comp2' },
|
||||
],
|
||||
});
|
||||
|
||||
// Check bundle stock in Hauptlager: min(10/1, 10/2) = 5
|
||||
const afterCompStock = await store.article.getBySku(googleAuthId, bundle.sku);
|
||||
const wh1BundleStock = afterCompStock.article.warehouses.find((w) => w.id === wh1.id).stock;
|
||||
const wh2BundleStock = afterCompStock.article.warehouses.find((w) => w.id === wh2.id).stock;
|
||||
assert.equal(wh1BundleStock, 5, 'Bundle stock in Hauptlager should be 5 (min(10/1, 10/2))');
|
||||
assert.equal(wh2BundleStock, 0, 'Bundle stock in Filiale should be 0');
|
||||
|
||||
// Book in 3x Stückliste bundle into Filiale
|
||||
const adjustResult = await store.stock.adjust(googleAuthId, {
|
||||
sku: bundle.sku,
|
||||
warehouseId: wh2.id,
|
||||
amount: 3,
|
||||
text: 'Production bundle book-in',
|
||||
});
|
||||
|
||||
// Verify adjust result lines
|
||||
assert.equal(adjustResult.lines.length, 2, 'Should expand into 2 component lines');
|
||||
const comp1Line = adjustResult.lines.find((l) => l.sku === comp1.sku);
|
||||
const comp2Line = adjustResult.lines.find((l) => l.sku === comp2.sku);
|
||||
assert.equal(comp1Line.amount, 3, 'Component 1 should get 3 * 1 = 3');
|
||||
assert.equal(comp2Line.amount, 6, 'Component 2 should get 3 * 2 = 6');
|
||||
|
||||
// Verify bundle article itself has NO entries in the ledger
|
||||
const bundleLedger = await store.ledger.listBySku(googleAuthId, bundle.sku);
|
||||
assert.equal(bundleLedger.length, 0, 'Bundle article must have NO ledger entries');
|
||||
|
||||
// Verify component articles have their ledger entries
|
||||
const comp1Ledger = await store.ledger.listBySku(googleAuthId, comp1.sku, { warehouse_id: wh2.id });
|
||||
const comp2Ledger = await store.ledger.listBySku(googleAuthId, comp2.sku, { warehouse_id: wh2.id });
|
||||
assert.equal(comp1Ledger.length, 1);
|
||||
assert.equal(comp1Ledger[0].amount, 3);
|
||||
assert.equal(comp2Ledger.length, 1);
|
||||
assert.equal(comp2Ledger[0].amount, 6);
|
||||
|
||||
// Verify bundle stock report in Filiale is now 3 (min(3/1, 6/2) = 3)
|
||||
const afterBundleBookIn = await store.article.getBySku(googleAuthId, bundle.sku);
|
||||
const wh2AfterBookIn = afterBundleBookIn.article.warehouses.find((w) => w.id === wh2.id).stock;
|
||||
assert.equal(wh2AfterBookIn, 3, 'Bundle stock in Filiale should be 3');
|
||||
|
||||
// Test booking out 1x bundle from Filiale
|
||||
await store.stock.adjust(googleAuthId, {
|
||||
sku: bundle.sku,
|
||||
warehouseId: wh2.id,
|
||||
amount: -1,
|
||||
text: 'Sale bundle book-out',
|
||||
});
|
||||
|
||||
const afterRemoval = await store.article.getBySku(googleAuthId, bundle.sku);
|
||||
const wh2AfterRemoval = afterRemoval.article.warehouses.find((w) => w.id === wh2.id).stock;
|
||||
assert.equal(wh2AfterRemoval, 2, 'Bundle stock in Filiale should be 2 after -1 removal');
|
||||
|
||||
// Verify components stock after removal in Filiale: comp1 = 2, comp2 = 4
|
||||
const comp1After = await store.article.getBySku(googleAuthId, comp1.sku);
|
||||
const comp2After = await store.article.getBySku(googleAuthId, comp2.sku);
|
||||
assert.equal(comp1After.article.warehouses.find((w) => w.id === wh2.id).stock, 2);
|
||||
assert.equal(comp2After.article.warehouses.find((w) => w.id === wh2.id).stock, 4);
|
||||
|
||||
console.log('✓ All Stückliste stock reporting and adjustment tests passed successfully!');
|
||||
} finally {
|
||||
try {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error('Test failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user