u
This commit is contained in:
145
scripts/test-delivery-link-check.js
Normal file
145
scripts/test-delivery-link-check.js
Normal file
@@ -0,0 +1,145 @@
|
||||
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 Delivery Link Check & Sync in dashdbschema ---');
|
||||
|
||||
const tempDir = mkdtempSync(join(tmpdir(), 'test-delivery-link-check-'));
|
||||
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('link-check-test@example.com');
|
||||
const company = await store.company.create({
|
||||
name: 'Link Check Corp',
|
||||
iso639: 'de',
|
||||
taxrate: 19,
|
||||
reducedtaxrate: 7,
|
||||
googleAuthId,
|
||||
});
|
||||
await store.google_auth.setSelectedCompany(googleAuthId, company.id);
|
||||
|
||||
await store.warehouse.create(googleAuthId, { name: 'Hauptlager' });
|
||||
|
||||
const supplier = await store.supplier.create(googleAuthId, {
|
||||
name: 'eks',
|
||||
});
|
||||
|
||||
const art = await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: company.rootCategoryId,
|
||||
name: 'Club Mate 0,5l',
|
||||
track_stock: 1,
|
||||
});
|
||||
|
||||
// Assign supplier with default pu=1, without EK
|
||||
await store.articlesupplier.create(googleAuthId, art.sku, {
|
||||
entityId: supplier.id,
|
||||
sku: 'mate',
|
||||
pu: 1,
|
||||
});
|
||||
|
||||
let asup = await store.articlesupplier.listByArticleSku(googleAuthId, art.sku);
|
||||
assert.equal(asup.length, 1);
|
||||
assert.equal(asup[0].pu, 1);
|
||||
assert.equal(asup[0].price, null);
|
||||
|
||||
// Create delivery with manifest line: sku: 'mate', pu: 20, net: 12
|
||||
const delivery = await store.delivery.create(googleAuthId, {
|
||||
date: '2026-10-25T10:00:00Z',
|
||||
externalNumber: 'LS-000001',
|
||||
supplierId: supplier.id,
|
||||
lines: [
|
||||
{ sku: 'mate', name: 'Club Mate 0,5l', pu: 20, amount: 2, net: 12, taxrate: 19 },
|
||||
],
|
||||
});
|
||||
|
||||
assert(delivery.id > 0);
|
||||
assert.equal(delivery.lines[0].pu, 20);
|
||||
|
||||
// Verify articlesupplier link was updated!
|
||||
asup = await store.articlesupplier.listByArticleSku(googleAuthId, art.sku);
|
||||
assert.equal(asup.length, 1);
|
||||
assert.equal(asup[0].pu, 20, 'VPE in articlesupplier must be synced to 20');
|
||||
assert.equal(asup[0].price.net, 12, 'Net price in articlesupplier must be synced to 12');
|
||||
assert.equal(asup[0].price.taxRate, 19, 'Tax rate in articlesupplier must be synced to 19');
|
||||
|
||||
// Verify article history
|
||||
const history = await store.article.getHistoryBySku(googleAuthId, art.sku);
|
||||
const historyTexts = (Array.isArray(history) ? history : history.history).map((h) => h.text);
|
||||
console.log('Article history entries:', historyTexts);
|
||||
|
||||
assert(
|
||||
historyTexts.some((t) => t.includes('Lieferant "eks" aktualisiert (VPE: 20, EK: € 12,00, MwSt.: 19%)')),
|
||||
'Must record history entry for supplier update with VPE, EK, and MwSt'
|
||||
);
|
||||
|
||||
// Now update delivery with new line pu: 24, net: 11.50, and taxrate: 7
|
||||
await store.delivery.update(googleAuthId, delivery.id, {
|
||||
lines: [
|
||||
{ sku: 'mate', name: 'Club Mate 0,5l', pu: 24, amount: 3, net: 11.5, taxrate: 7 },
|
||||
],
|
||||
});
|
||||
|
||||
asup = await store.articlesupplier.listByArticleSku(googleAuthId, art.sku);
|
||||
assert.equal(asup[0].pu, 24, 'VPE in articlesupplier must be synced to 24 on update');
|
||||
assert.equal(asup[0].price.net, 11.5, 'Net price in articlesupplier must be synced to 11.5 on update');
|
||||
assert.equal(asup[0].price.taxRate, 7, 'Tax rate in articlesupplier must be synced to 7 on update');
|
||||
|
||||
const historyAfterUpdate = await store.article.getHistoryBySku(googleAuthId, art.sku);
|
||||
const historyAfterTexts = (Array.isArray(historyAfterUpdate) ? historyAfterUpdate : historyAfterUpdate.history).map((h) => h.text);
|
||||
console.log('Article history entries after delivery update:', historyAfterTexts);
|
||||
assert(
|
||||
historyAfterTexts.some((t) => t.includes('Lieferant "eks" aktualisiert (VPE: 24, EK: € 11,50, MwSt.: 7%)')),
|
||||
'Must record history entry for supplier update on delivery update'
|
||||
);
|
||||
|
||||
// Now test booking the delivery with amount: 3, pu: 24
|
||||
// Should add 3 * 24 = 72 to stock and record clear history!
|
||||
await store.delivery.book(googleAuthId, delivery.id);
|
||||
|
||||
const artDetail = await store.article.getBySku(googleAuthId, art.sku);
|
||||
const totalStock = (artDetail.article.warehouses || []).reduce((acc, w) => acc + (w.stock || 0), 0);
|
||||
console.log('Article stock after booking delivery with amount 3, pu 24:', totalStock);
|
||||
assert.equal(totalStock, 72, 'Physical warehouse stock must be amount * pu (3 * 24 = 72)');
|
||||
|
||||
const historyAfterBooking = await store.article.getHistoryBySku(googleAuthId, art.sku);
|
||||
const bookingTexts = (Array.isArray(historyAfterBooking) ? historyAfterBooking : historyAfterBooking.history).map((h) => h.text);
|
||||
console.log('Article history entries after delivery booking:', bookingTexts);
|
||||
|
||||
assert(
|
||||
bookingTexts.some((t) => t.includes('Lager: "Hauptlager"') && t.includes('Menge: 72 (3 x VPE 24)')),
|
||||
'Warehouse history must clearly show Menge: 72 (3 x VPE 24)'
|
||||
);
|
||||
assert(
|
||||
bookingTexts.some((t) => t.includes('Lieferant: "eks"') && t.includes('Menge: 3, VPE: 24')),
|
||||
'Acceptance history must clearly show Menge: 3, VPE: 24'
|
||||
);
|
||||
|
||||
console.log('✓ Delivery link check and sync passed successfully!');
|
||||
} finally {
|
||||
try {
|
||||
provider.close();
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -93,6 +93,43 @@ export class MssqlProvider {
|
||||
#config;
|
||||
#connecting;
|
||||
|
||||
async #tryCreateDatabaseIfMissing() {
|
||||
if (!this.#config?.database) return false;
|
||||
const targetDb = String(this.#config.database);
|
||||
if (targetDb.toLowerCase() === 'master') return false;
|
||||
|
||||
const masterConfig = {
|
||||
...this.#config,
|
||||
database: 'master',
|
||||
pool: { min: 0, max: 1, idleTimeoutMillis: 5000 },
|
||||
};
|
||||
|
||||
let masterPool;
|
||||
try {
|
||||
masterPool = await new sql.ConnectionPool(masterConfig).connect();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const checkReq = masterPool.request();
|
||||
checkReq.input('dbname', sql.NVarChar, targetDb);
|
||||
const res = await checkReq.query('SELECT DB_ID(@dbname) AS dbid');
|
||||
if (res.recordset[0]?.dbid != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const createReq = masterPool.request();
|
||||
createReq.input('dbname', sql.NVarChar, targetDb);
|
||||
await createReq.query(
|
||||
"DECLARE @sql NVARCHAR(MAX) = N'CREATE DATABASE ' + QUOTENAME(@dbname); EXEC sp_executesql @sql;"
|
||||
);
|
||||
return true;
|
||||
} finally {
|
||||
await masterPool.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying pool, creating and connecting it on first use
|
||||
* when the provider was constructed from a config object.
|
||||
@@ -101,15 +138,26 @@ export class MssqlProvider {
|
||||
ensurePool() {
|
||||
if (this.pool.connected) return Promise.resolve(this.pool);
|
||||
if (!this.#connecting) {
|
||||
this.#connecting = this.pool
|
||||
.connect()
|
||||
.then((pool) => {
|
||||
return pool;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.#connecting = undefined;
|
||||
this.#connecting = (async () => {
|
||||
try {
|
||||
return await this.pool.connect();
|
||||
} catch (err) {
|
||||
if (err.code === 'ELOGIN') {
|
||||
try {
|
||||
const created = await this.#tryCreateDatabaseIfMissing();
|
||||
if (created) {
|
||||
return await this.pool.connect();
|
||||
}
|
||||
} catch {
|
||||
// ignore creation error and fall through to rethrow original error
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
})().catch((err) => {
|
||||
this.#connecting = undefined;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
return this.#connecting;
|
||||
}
|
||||
|
||||
@@ -462,12 +462,12 @@ export const GET_ARTICLE_BY_SKU_FULL = `
|
||||
co.default_language_id AS languageId,
|
||||
co.poscustomergroup_id AS posCustomerGroupId,
|
||||
cu.id AS companyuserId
|
||||
FROM article a
|
||||
INNER JOIN company co ON co.id = a.company_id
|
||||
INNER JOIN google_auth ga ON ga.id = @googleAuthId
|
||||
INNER JOIN companyuser cu
|
||||
FROM article a WITH (NOLOCK)
|
||||
INNER JOIN company co WITH (NOLOCK) ON co.id = a.company_id
|
||||
INNER JOIN google_auth ga WITH (NOLOCK) ON ga.id = @googleAuthId
|
||||
INNER JOIN companyuser cu WITH (NOLOCK)
|
||||
ON cu.company_id = a.company_id AND cu.google_auth_id = @googleAuthId
|
||||
LEFT JOIN categoryarticle ca ON ca.article_id = a.id
|
||||
LEFT JOIN categoryarticle ca WITH (NOLOCK) ON ca.article_id = a.id
|
||||
WHERE a.sku = @sku
|
||||
AND (ga.selected_company IS NULL OR a.company_id = ga.selected_company)
|
||||
)
|
||||
@@ -503,7 +503,7 @@ SELECT
|
||||
bp.thumbhash AS brandThumbHash,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM optionslistarticle ola
|
||||
FROM optionslistarticle ola WITH (NOLOCK)
|
||||
WHERE ola.optionslist_id = a.optionslist_id
|
||||
) AS optionsCount,
|
||||
a.optionslist_id AS optionslistId,
|
||||
@@ -516,16 +516,16 @@ SELECT
|
||||
ola.count,
|
||||
ola.sort,
|
||||
ola.mandated
|
||||
FROM optionslistarticle ola
|
||||
INNER JOIN article a_opt ON a_opt.id = ola.article_id
|
||||
LEFT JOIN articletext at_opt ON at_opt.article_id = a_opt.id AND at_opt.language_id = auth.languageId
|
||||
FROM optionslistarticle ola WITH (NOLOCK)
|
||||
INNER JOIN article a_opt WITH (NOLOCK) ON a_opt.id = ola.article_id
|
||||
LEFT JOIN articletext at_opt WITH (NOLOCK) ON at_opt.article_id = a_opt.id AND at_opt.language_id = auth.languageId
|
||||
WHERE ola.optionslist_id = a.optionslist_id
|
||||
ORDER BY ola.sort ASC, ola.id ASC
|
||||
FOR JSON PATH
|
||||
) AS optionslistItemsJson,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM articlelistarticle ala
|
||||
FROM articlelistarticle ala WITH (NOLOCK)
|
||||
WHERE ala.articlelist_id = a.articlelist_id
|
||||
) AS articleListCount,
|
||||
a.articlelist_id AS articlelistId,
|
||||
@@ -537,16 +537,16 @@ SELECT
|
||||
at_item.name,
|
||||
ala.count,
|
||||
ala.sort
|
||||
FROM articlelistarticle ala
|
||||
INNER JOIN article a_item ON a_item.id = ala.article_id
|
||||
LEFT JOIN articletext at_item ON at_item.article_id = a_item.id AND at_item.language_id = auth.languageId
|
||||
FROM articlelistarticle ala WITH (NOLOCK)
|
||||
INNER JOIN article a_item WITH (NOLOCK) ON a_item.id = ala.article_id
|
||||
LEFT JOIN articletext at_item WITH (NOLOCK) ON at_item.article_id = a_item.id AND at_item.language_id = auth.languageId
|
||||
WHERE ala.articlelist_id = a.articlelist_id
|
||||
ORDER BY ala.sort ASC, ala.id ASC
|
||||
FOR JSON PATH
|
||||
) AS articlelistItemsJson,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM article child
|
||||
FROM article child WITH (NOLOCK)
|
||||
WHERE child.parentarticle_id = a.id
|
||||
) AS childCount,
|
||||
a.is_parent AS isParent,
|
||||
@@ -563,11 +563,11 @@ SELECT
|
||||
at_child.name,
|
||||
av.id AS attributeValueId,
|
||||
av.value AS attributeValue
|
||||
FROM article child
|
||||
LEFT JOIN articletext at_child ON at_child.article_id = child.id AND at_child.language_id = auth.languageId
|
||||
FROM article child WITH (NOLOCK)
|
||||
LEFT JOIN articletext at_child WITH (NOLOCK) ON at_child.article_id = child.id AND at_child.language_id = auth.languageId
|
||||
LEFT JOIN (
|
||||
articleattributevalue aav
|
||||
INNER JOIN attributevalue av ON av.id = aav.attributevalue_id AND av.attribute_id = a.parentattributename_id
|
||||
articleattributevalue aav WITH (NOLOCK)
|
||||
INNER JOIN attributevalue av WITH (NOLOCK) ON av.id = aav.attributevalue_id AND av.attribute_id = a.parentattributename_id
|
||||
) ON aav.article_id = child.id
|
||||
WHERE child.parentarticle_id = a.id
|
||||
ORDER BY child.parentsort ASC, child.id ASC
|
||||
@@ -575,7 +575,7 @@ SELECT
|
||||
) AS childrenJson,
|
||||
(
|
||||
SELECT ca2.category_id
|
||||
FROM categoryarticle ca2
|
||||
FROM categoryarticle ca2 WITH (NOLOCK)
|
||||
WHERE ca2.article_id = a.id
|
||||
ORDER BY ca2.category_id
|
||||
FOR JSON PATH
|
||||
@@ -590,15 +590,15 @@ SELECT
|
||||
p.thumbw AS thumbW,
|
||||
p.thumbh AS thumbH,
|
||||
p.thumbhash AS thumbHash
|
||||
FROM articlepic ap
|
||||
INNER JOIN pic p ON p.id = ap.pic_id
|
||||
FROM articlepic ap WITH (NOLOCK)
|
||||
INNER JOIN pic p WITH (NOLOCK) ON p.id = ap.pic_id
|
||||
WHERE ap.article_id = a.id
|
||||
ORDER BY ap.sort ASC, ap.id ASC
|
||||
FOR JSON PATH
|
||||
) AS photosJson,
|
||||
(
|
||||
SELECT ae.ean
|
||||
FROM articleean ae
|
||||
FROM articleean ae WITH (NOLOCK)
|
||||
WHERE ae.article_id = a.id
|
||||
ORDER BY ae.ean
|
||||
FOR JSON PATH
|
||||
@@ -609,8 +609,8 @@ SELECT
|
||||
pr.net,
|
||||
t.rate AS taxRate,
|
||||
pr.customergroup_id AS customergroupId
|
||||
FROM price pr
|
||||
INNER JOIN tax t ON t.id = pr.tax_id
|
||||
FROM price pr WITH (NOLOCK)
|
||||
INNER JOIN tax t WITH (NOLOCK) ON t.id = pr.tax_id
|
||||
WHERE pr.article_id = a.id
|
||||
ORDER BY pr.customergroup_id, pr.minmultiplier
|
||||
FOR JSON PATH
|
||||
@@ -632,11 +632,11 @@ SELECT
|
||||
SELECT
|
||||
m.[date] AS [date],
|
||||
SUM(ma.amount - COALESCE(ma_ledger.booked_amount, 0)) AS amount
|
||||
FROM manifest m
|
||||
INNER JOIN manifestarticle ma ON ma.manifest_id = m.id
|
||||
FROM manifest m WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma WITH (NOLOCK) ON ma.manifest_id = m.id
|
||||
LEFT JOIN (
|
||||
SELECT manifestarticle_id, SUM(amount) AS booked_amount
|
||||
FROM ledger
|
||||
FROM ledger WITH (NOLOCK)
|
||||
WHERE warehouse_id IS NULL
|
||||
GROUP BY manifestarticle_id
|
||||
) ma_ledger ON ma_ledger.manifestarticle_id = ma.id
|
||||
@@ -651,9 +651,9 @@ SELECT
|
||||
ORDER BY m.[date] ASC, m.id ASC
|
||||
FOR JSON PATH
|
||||
) AS incomingJson
|
||||
FROM articlesupplier asup
|
||||
INNER JOIN entity e ON e.id = asup.entity_id
|
||||
LEFT JOIN tax t ON t.id = asup.tax_id
|
||||
FROM articlesupplier asup WITH (NOLOCK)
|
||||
INNER JOIN entity e WITH (NOLOCK) ON e.id = asup.entity_id
|
||||
LEFT JOIN tax t WITH (NOLOCK) ON t.id = asup.tax_id
|
||||
WHERE asup.article_id = a.id
|
||||
ORDER BY asup.sort ASC, asup.id ASC
|
||||
FOR JSON PATH
|
||||
@@ -665,21 +665,21 @@ SELECT
|
||||
w.sort,
|
||||
CASE
|
||||
WHEN a.articlelist_id IS NOT NULL AND EXISTS (
|
||||
SELECT 1 FROM articlelistarticle ala WHERE ala.articlelist_id = a.articlelist_id
|
||||
SELECT 1 FROM articlelistarticle ala WITH (NOLOCK) WHERE ala.articlelist_id = a.articlelist_id
|
||||
) THEN COALESCE((
|
||||
SELECT CASE
|
||||
WHEN MIN(COALESCE(comp_stock.stock, 0) / ala.count) < 0 THEN 0
|
||||
ELSE FLOOR(MIN(COALESCE(comp_stock.stock, 0) / ala.count))
|
||||
END
|
||||
FROM articlelistarticle ala
|
||||
FROM articlelistarticle ala WITH (NOLOCK)
|
||||
LEFT JOIN (
|
||||
SELECT ca.id AS comp_id, SUM(l.amount) AS stock
|
||||
FROM ledger l
|
||||
INNER JOIN manifestarticle ma ON ma.id = l.manifestarticle_id
|
||||
INNER JOIN manifest m ON m.id = ma.manifest_id
|
||||
INNER JOIN article ca ON (
|
||||
FROM ledger l WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma WITH (NOLOCK) ON ma.id = l.manifestarticle_id
|
||||
INNER JOIN manifest m WITH (NOLOCK) ON m.id = ma.manifest_id
|
||||
INNER JOIN article ca WITH (NOLOCK) ON (
|
||||
ma.sku = ca.sku
|
||||
OR ma.sku IN (SELECT asup.sku FROM articlesupplier asup WHERE asup.article_id = ca.id)
|
||||
OR ma.sku IN (SELECT asup.sku FROM articlesupplier asup WITH (NOLOCK) WHERE asup.article_id = ca.id)
|
||||
)
|
||||
WHERE m.company_id = a.company_id
|
||||
AND l.warehouse_id = w.id
|
||||
@@ -690,16 +690,16 @@ SELECT
|
||||
WHEN a.articlelist_id IS NOT NULL THEN 0
|
||||
ELSE COALESCE(stock_calc.stock, 0)
|
||||
END AS stock
|
||||
FROM warehouse w
|
||||
FROM warehouse w WITH (NOLOCK)
|
||||
LEFT JOIN (
|
||||
SELECT l.warehouse_id, SUM(l.amount) AS stock
|
||||
FROM ledger l
|
||||
INNER JOIN manifestarticle ma ON ma.id = l.manifestarticle_id
|
||||
INNER JOIN manifest m ON m.id = ma.manifest_id
|
||||
FROM ledger l WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma WITH (NOLOCK) ON ma.id = l.manifestarticle_id
|
||||
INNER JOIN manifest m WITH (NOLOCK) ON m.id = ma.manifest_id
|
||||
WHERE m.company_id = a.company_id
|
||||
AND (
|
||||
ma.sku = a.sku
|
||||
OR ma.sku IN (SELECT asup.sku FROM articlesupplier asup WHERE asup.article_id = a.id)
|
||||
OR ma.sku IN (SELECT asup.sku FROM articlesupplier asup WITH (NOLOCK) WHERE asup.article_id = a.id)
|
||||
)
|
||||
GROUP BY l.warehouse_id
|
||||
) stock_calc ON stock_calc.warehouse_id = w.id
|
||||
@@ -715,20 +715,20 @@ SELECT
|
||||
COALESCE(os.customer_name, LTRIM(RTRIM(ISNULL(e.first_name + ' ', '') + ISNULL(e.name, '')))) AS customerName,
|
||||
ROUND(SUM(ma.amount) - COALESCE((
|
||||
SELECT SUM(ma_s.amount)
|
||||
FROM manifest m_s
|
||||
INNER JOIN manifestarticle ma_s ON ma_s.manifest_id = m_s.id
|
||||
LEFT JOIN shipmentsummary ss ON ss.manifest_id = m_s.id
|
||||
FROM manifest m_s WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma_s WITH (NOLOCK) ON ma_s.manifest_id = m_s.id
|
||||
LEFT JOIN shipmentsummary ss WITH (NOLOCK) ON ss.manifest_id = m_s.id
|
||||
WHERE m_s.company_id = m.company_id
|
||||
AND m_s.[type] = 'shipment'
|
||||
AND ISNULL(ss.state, 'new') != 'cancelled'
|
||||
AND m_s.[number] NOT LIKE '%#cancelled#%'
|
||||
AND ma_s.sku = a.sku
|
||||
AND m_s.[number] LIKE m.[number] + COALESCE((SELECT prefix FROM numbers WHERE company_id = m.company_id AND [type] = 'shipment'), '-L-') + '%'
|
||||
AND m_s.[number] LIKE m.[number] + COALESCE((SELECT prefix FROM numbers WITH (NOLOCK) WHERE company_id = m.company_id AND [type] = 'shipment'), '-L-') + '%'
|
||||
), 0), 3) AS amount
|
||||
FROM manifest m
|
||||
INNER JOIN manifestarticle ma ON ma.manifest_id = m.id
|
||||
LEFT JOIN ordersummary os ON os.manifest_id = m.id
|
||||
LEFT JOIN entity e ON e.id = m.entity_id
|
||||
FROM manifest m WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma WITH (NOLOCK) ON ma.manifest_id = m.id
|
||||
LEFT JOIN ordersummary os WITH (NOLOCK) ON os.manifest_id = m.id
|
||||
LEFT JOIN entity e WITH (NOLOCK) ON e.id = m.entity_id
|
||||
WHERE m.company_id = a.company_id
|
||||
AND m.[type] = 'order'
|
||||
AND ma.sku = a.sku
|
||||
@@ -736,35 +736,35 @@ SELECT
|
||||
GROUP BY m.id, m.[number], m.[date], m.company_id, os.customer_name, e.first_name, e.name
|
||||
HAVING (SUM(ma.amount) - COALESCE((
|
||||
SELECT SUM(ma_s.amount)
|
||||
FROM manifest m_s
|
||||
INNER JOIN manifestarticle ma_s ON ma_s.manifest_id = m_s.id
|
||||
LEFT JOIN shipmentsummary ss ON ss.manifest_id = m_s.id
|
||||
FROM manifest m_s WITH (NOLOCK)
|
||||
INNER JOIN manifestarticle ma_s WITH (NOLOCK) ON ma_s.manifest_id = m_s.id
|
||||
LEFT JOIN shipmentsummary ss WITH (NOLOCK) ON ss.manifest_id = m_s.id
|
||||
WHERE m_s.company_id = m.company_id
|
||||
AND m_s.[type] = 'shipment'
|
||||
AND ISNULL(ss.state, 'new') != 'cancelled'
|
||||
AND m_s.[number] NOT LIKE '%#cancelled#%'
|
||||
AND ma_s.sku = a.sku
|
||||
AND m_s.[number] LIKE m.[number] + COALESCE((SELECT prefix FROM numbers WHERE company_id = m.company_id AND [type] = 'shipment'), '-L-') + '%'
|
||||
AND m_s.[number] LIKE m.[number] + COALESCE((SELECT prefix FROM numbers WITH (NOLOCK) WHERE company_id = m.company_id AND [type] = 'shipment'), '-L-') + '%'
|
||||
), 0)) > 0
|
||||
ORDER BY m.[date] ASC, m.id ASC
|
||||
FOR JSON PATH
|
||||
) AS undeliveredOrdersJson
|
||||
FROM article a
|
||||
LEFT JOIN articletext at
|
||||
FROM article a WITH (NOLOCK)
|
||||
LEFT JOIN articletext at WITH (NOLOCK)
|
||||
ON at.article_id = a.id AND at.language_id = auth.languageId
|
||||
LEFT JOIN unit u ON u.id = a.unit_id
|
||||
LEFT JOIN unittext ut
|
||||
LEFT JOIN unit u WITH (NOLOCK) ON u.id = a.unit_id
|
||||
LEFT JOIN unittext ut WITH (NOLOCK)
|
||||
ON ut.unit_id = u.id AND ut.language_id = auth.languageId
|
||||
LEFT JOIN brand b ON b.id = a.brand_id
|
||||
LEFT JOIN brand b WITH (NOLOCK) ON b.id = a.brand_id
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 bp2.pic_id
|
||||
FROM brandpic bp2
|
||||
FROM brandpic bp2 WITH (NOLOCK)
|
||||
WHERE bp2.brand_id = b.id
|
||||
ORDER BY bp2.sort ASC, bp2.id ASC
|
||||
) first_brand_pic
|
||||
LEFT JOIN pic bp ON bp.id = first_brand_pic.pic_id
|
||||
LEFT JOIN article fa ON fa.id = a.parentarticle_id
|
||||
LEFT JOIN attributename fan ON fan.id = a.parentattributename_id
|
||||
LEFT JOIN pic bp WITH (NOLOCK) ON bp.id = first_brand_pic.pic_id
|
||||
LEFT JOIN article fa WITH (NOLOCK) ON fa.id = a.parentarticle_id
|
||||
LEFT JOIN attributename fan WITH (NOLOCK) ON fan.id = a.parentattributename_id
|
||||
WHERE a.id = auth.articleId
|
||||
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
|
||||
) AS articleJson
|
||||
|
||||
@@ -3,6 +3,7 @@ SELECT
|
||||
ma.id,
|
||||
ma.sku,
|
||||
ma.amount AS lineAmount,
|
||||
ma.pu AS linePu,
|
||||
ma.net,
|
||||
ma.rebate,
|
||||
ma.taxrate,
|
||||
@@ -67,7 +68,7 @@ SELECT TOP 1
|
||||
hash_version,
|
||||
prev_hash,
|
||||
created_at
|
||||
FROM ledger WITH (UPDLOCK, HOLDLOCK)
|
||||
FROM ledger WITH (UPDLOCK, ROWLOCK)
|
||||
ORDER BY id DESC;
|
||||
`;
|
||||
|
||||
|
||||
@@ -158,22 +158,61 @@ SELECT
|
||||
a.id,
|
||||
a.is_parent AS isParent,
|
||||
COALESCE(
|
||||
(SELECT at.name FROM articletext at WHERE at.article_id = a.id AND at.language_id = co.default_language_id),
|
||||
(SELECT MIN(at2.name) FROM articletext at2 WHERE at2.article_id = a.id),
|
||||
(SELECT at.name FROM articletext at WITH (NOLOCK) WHERE at.article_id = a.id AND at.language_id = co.default_language_id),
|
||||
(SELECT MIN(at2.name) FROM articletext at2 WITH (NOLOCK) WHERE at2.article_id = a.id),
|
||||
a.sku
|
||||
) AS articleName,
|
||||
COALESCE(
|
||||
(SELECT MIN(asup.pu) FROM articlesupplier asup WHERE asup.article_id = a.id AND asup.sku = @sku),
|
||||
(SELECT MIN(asup2.pu) FROM articlesupplier asup2 WHERE asup2.article_id = a.id),
|
||||
(SELECT MIN(asup.pu) FROM articlesupplier asup WITH (NOLOCK) WHERE asup.article_id = a.id AND asup.sku = @sku),
|
||||
(SELECT MIN(asup2.pu) FROM articlesupplier asup2 WITH (NOLOCK) WHERE asup2.article_id = a.id),
|
||||
a.unitamount,
|
||||
1
|
||||
) AS pu
|
||||
FROM article a
|
||||
INNER JOIN manifest m ON m.company_id = a.company_id
|
||||
INNER JOIN company co ON co.id = m.company_id
|
||||
FROM article a WITH (NOLOCK)
|
||||
INNER JOIN manifest m WITH (NOLOCK) ON m.company_id = a.company_id
|
||||
INNER JOIN company co WITH (NOLOCK) ON co.id = m.company_id
|
||||
WHERE m.id = @manifestId
|
||||
AND (a.sku = @sku OR EXISTS (
|
||||
SELECT 1 FROM articlesupplier asup WHERE asup.article_id = a.id AND asup.sku = @sku
|
||||
SELECT 1 FROM articlesupplier asup WITH (NOLOCK) WHERE asup.article_id = a.id AND asup.sku = @sku
|
||||
))
|
||||
`;
|
||||
|
||||
export const GET_MANIFEST_CONTEXT = `
|
||||
SELECT
|
||||
m.id,
|
||||
m.company_id AS companyId,
|
||||
m.[type] AS [type],
|
||||
m.entity_id AS entityId,
|
||||
e.name AS entityName
|
||||
FROM manifest m
|
||||
LEFT JOIN entity e ON e.id = m.entity_id
|
||||
WHERE m.id = @manifestId
|
||||
`;
|
||||
|
||||
export const GET_ARTICLE_SUPPLIER_LINK = `
|
||||
SELECT
|
||||
asup.id,
|
||||
asup.article_id AS articleId,
|
||||
asup.entity_id AS entityId,
|
||||
asup.sku,
|
||||
asup.pu,
|
||||
asup.net,
|
||||
asup.tax_id AS taxId,
|
||||
t.rate AS taxRate,
|
||||
e.name AS supplierName
|
||||
FROM articlesupplier asup
|
||||
LEFT JOIN entity e ON e.id = asup.entity_id
|
||||
LEFT JOIN tax t ON t.id = asup.tax_id
|
||||
WHERE asup.article_id = @articleId
|
||||
AND asup.entity_id = @entityId
|
||||
`;
|
||||
|
||||
export const UPDATE_ARTICLE_SUPPLIER_LINK = `
|
||||
UPDATE articlesupplier
|
||||
SET
|
||||
pu = @pu,
|
||||
net = @net,
|
||||
tax_id = @taxId
|
||||
WHERE id = @id
|
||||
`;
|
||||
|
||||
|
||||
@@ -360,6 +360,16 @@ BEGIN
|
||||
ALTER TABLE article ADD track_stock BIT NOT NULL CONSTRAINT DF_article_track_stock DEFAULT 0;
|
||||
END
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_article_sku' AND object_id = OBJECT_ID('article'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_article_sku ON article (sku);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_article_parentarticle_id' AND object_id = OBJECT_ID('article'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_article_parentarticle_id ON article (parentarticle_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_ARTICLEHISTORY = `
|
||||
@@ -624,6 +634,18 @@ BEGIN
|
||||
CREATE INDEX IX_articlesupplier_article_entity
|
||||
ON articlesupplier (article_id, entity_id);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_articlesupplier_sku' AND object_id = OBJECT_ID('articlesupplier'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_articlesupplier_sku
|
||||
ON articlesupplier (sku, article_id);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_articlesupplier_entity' AND object_id = OBJECT_ID('articlesupplier'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_articlesupplier_entity
|
||||
ON articlesupplier (entity_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_MANIFEST = `
|
||||
@@ -648,6 +670,12 @@ BEGIN
|
||||
CREATE UNIQUE NONCLUSTERED INDEX UQ_manifest_company_type_number
|
||||
ON manifest (company_id, [type], [number]);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_manifest_entity_id' AND object_id = OBJECT_ID('manifest'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_manifest_entity_id
|
||||
ON manifest (entity_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_MANIFESTARTICLE = `
|
||||
@@ -668,6 +696,18 @@ BEGIN
|
||||
CONSTRAINT FK_manifestarticle_manifest FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE
|
||||
);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_manifestarticle_manifest_id' AND object_id = OBJECT_ID('manifestarticle'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_manifestarticle_manifest_id
|
||||
ON manifestarticle (manifest_id);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_manifestarticle_sku' AND object_id = OBJECT_ID('manifestarticle'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_manifestarticle_sku
|
||||
ON manifestarticle (sku);
|
||||
END
|
||||
`;
|
||||
|
||||
|
||||
@@ -706,6 +746,18 @@ BEGIN
|
||||
CONSTRAINT FK_ledger_warehouse FOREIGN KEY (warehouse_id) REFERENCES warehouse(id) ON DELETE NO ACTION
|
||||
) WITH (LEDGER = ON (APPEND_ONLY = ON));
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ledger_manifestarticle_warehouse' AND object_id = OBJECT_ID('ledger'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_ledger_manifestarticle_warehouse
|
||||
ON ledger (manifestarticle_id, warehouse_id);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_ledger_warehouse_id' AND object_id = OBJECT_ID('ledger'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_ledger_warehouse_id
|
||||
ON ledger (warehouse_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_NUMBERS = `
|
||||
@@ -1146,6 +1198,12 @@ BEGIN
|
||||
CONSTRAINT FK_payment_manifest FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE
|
||||
);
|
||||
END
|
||||
|
||||
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_payment_manifest_id' AND object_id = OBJECT_ID('payment'))
|
||||
BEGIN
|
||||
CREATE NONCLUSTERED INDEX IX_payment_manifest_id
|
||||
ON payment (manifest_id);
|
||||
END
|
||||
`;
|
||||
|
||||
export const INIT_CARRIER = `
|
||||
|
||||
@@ -3,6 +3,7 @@ SELECT
|
||||
ma.id,
|
||||
ma.sku,
|
||||
ma.amount AS lineAmount,
|
||||
ma.pu AS linePu,
|
||||
ma.net,
|
||||
ma.rebate,
|
||||
ma.taxrate,
|
||||
|
||||
@@ -4,8 +4,8 @@ import { translateQueries } from './translate.js';
|
||||
const queries = translateQueries(source, 'manifestDoc');
|
||||
export const {
|
||||
CHECK_ARTICLE_IS_PARENT, COUNT_MANIFESTS, CREATE_LINE, CREATE_MANIFEST, DELETE_LINES_BY_MANIFEST,
|
||||
DELETE_MANIFEST, GET_MANIFEST_HEADER, GET_MANIFEST_LINES, LIST_MANIFESTS,
|
||||
ORDER_TYPE, QUOTE_TYPE, UPDATE_MANIFEST,
|
||||
DELETE_MANIFEST, GET_ARTICLE_SUPPLIER_LINK, GET_MANIFEST_CONTEXT, GET_MANIFEST_HEADER,
|
||||
GET_MANIFEST_LINES, LIST_MANIFESTS, ORDER_TYPE, QUOTE_TYPE, UPDATE_ARTICLE_SUPPLIER_LINK, UPDATE_MANIFEST,
|
||||
} = queries;
|
||||
|
||||
export const LIST_MANIFESTS_PAGED = `
|
||||
|
||||
@@ -31,6 +31,7 @@ export function sqliteQuery(sql) {
|
||||
if (typeof sql !== 'string') return sql;
|
||||
|
||||
let result = quoteIdentifiers(sql)
|
||||
.replace(/\bWITH\s*\(\s*(?:NOLOCK|UPDLOCK|ROWLOCK|HOLDLOCK|READPAST)(?:\s*,\s*(?:NOLOCK|UPDLOCK|ROWLOCK|HOLDLOCK|READPAST))*\s*\)/gi, '')
|
||||
.replace(/\bISNULL\s*\(/gi, 'IFNULL(')
|
||||
.replace(/\bSYSUTCDATETIME\s*\(\s*\)/gi, "strftime('%Y-%m-%dT%H:%M:%fZ', 'now')")
|
||||
.replace(/\bDATEDIFF_BIG\s*\(\s*second\s*,\s*'1970-01-01'\s*,\s*([^)]+?)\s*\)/gi, "CAST(strftime('%s', $1) AS INTEGER)")
|
||||
|
||||
@@ -243,6 +243,8 @@ CREATE TABLE IF NOT EXISTS article (
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS UQ_article_parentarticle_parentsort
|
||||
ON article(parentarticle_id, parentsort)
|
||||
WHERE parentarticle_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS IX_article_sku ON article (sku);
|
||||
CREATE INDEX IF NOT EXISTS IX_article_parentarticle_id ON article (parentarticle_id);
|
||||
`;
|
||||
|
||||
export const INIT_ARTICLEEAN = `
|
||||
@@ -417,6 +419,10 @@ CREATE TABLE IF NOT EXISTS articlesupplier (
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_articlesupplier_article_entity
|
||||
ON articlesupplier(article_id, entity_id);
|
||||
CREATE INDEX IF NOT EXISTS IX_articlesupplier_sku
|
||||
ON articlesupplier(sku, article_id);
|
||||
CREATE INDEX IF NOT EXISTS IX_articlesupplier_entity
|
||||
ON articlesupplier(entity_id);
|
||||
`;
|
||||
|
||||
export const INIT_MANIFEST = `
|
||||
@@ -434,6 +440,8 @@ CREATE TABLE IF NOT EXISTS manifest (
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS UQ_manifest_company_type_number
|
||||
ON manifest (company_id, "type", "number");
|
||||
CREATE INDEX IF NOT EXISTS IX_manifest_entity_id
|
||||
ON manifest (entity_id);
|
||||
`;
|
||||
|
||||
export const INIT_MANIFESTARTICLE = `
|
||||
@@ -451,6 +459,10 @@ CREATE TABLE IF NOT EXISTS manifestarticle (
|
||||
shippable INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_manifestarticle_manifest_id
|
||||
ON manifestarticle (manifest_id);
|
||||
CREATE INDEX IF NOT EXISTS IX_manifestarticle_sku
|
||||
ON manifestarticle (sku);
|
||||
`;
|
||||
|
||||
export const INIT_WAREHOUSE = `
|
||||
@@ -479,6 +491,10 @@ CREATE TABLE IF NOT EXISTS ledger (
|
||||
FOREIGN KEY (manifestarticle_id) REFERENCES manifestarticle(id) ON DELETE NO ACTION,
|
||||
FOREIGN KEY (warehouse_id) REFERENCES warehouse(id) ON DELETE NO ACTION
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_ledger_manifestarticle_warehouse
|
||||
ON ledger (manifestarticle_id, warehouse_id);
|
||||
CREATE INDEX IF NOT EXISTS IX_ledger_warehouse_id
|
||||
ON ledger (warehouse_id);
|
||||
`;
|
||||
|
||||
export const INIT_NUMBERS = `
|
||||
@@ -817,6 +833,8 @@ CREATE TABLE IF NOT EXISTS payment (
|
||||
FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS IX_payment_manifest_id
|
||||
ON payment (manifest_id);
|
||||
`;
|
||||
|
||||
export const INIT_CARRIER = `
|
||||
|
||||
@@ -149,7 +149,7 @@ export async function recordOrderHistory(runner, { articleId, companyuserId, dat
|
||||
}
|
||||
|
||||
/** Records incoming delivery acceptance: "Lieferung {manifestNumber} (Lieferant: "{supplierName}", EK brutto: {ekBrutto}, Menge: {amount})" */
|
||||
export async function recordAcceptanceHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, net, rebate, taxrate, amount, transactionText }) {
|
||||
export async function recordAcceptanceHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, net, rebate, taxrate, amount, pu, transactionText }) {
|
||||
const details = [];
|
||||
if (supplierName) details.push(`Lieferant: "${supplierName}"`);
|
||||
|
||||
@@ -159,11 +159,15 @@ export async function recordAcceptanceHistory(runner, { articleId, companyuserId
|
||||
details.push(`EK brutto: ${ekBrutto}`);
|
||||
}
|
||||
if (isFiniteNum(amount)) details.push(`Menge: ${amount}`);
|
||||
const numPu = pu != null ? Number(pu) : null;
|
||||
if (numPu != null && numPu > 1) {
|
||||
details.push(`VPE: ${numPu}`);
|
||||
}
|
||||
|
||||
const base = manifestNumber ? `Lieferung ${manifestNumber}` : (transactionText?.trim() || 'Lieferung');
|
||||
const meta = {
|
||||
type: 'acceptance', manifestNumber: manifestNumber ?? null, deliveryNumber: manifestNumber ?? null,
|
||||
supplierName: supplierName ?? null, amount: toNumOrNull(amount), net: toNumOrNull(net),
|
||||
supplierName: supplierName ?? null, amount: toNumOrNull(amount), pu: numPu ?? 1, net: toNumOrNull(net),
|
||||
rebate: rebate != null ? Number(rebate) : 0, taxrate: taxrate != null ? Number(taxrate) : 0,
|
||||
ekBrutto: toNumOrNull(ekBrutto), transactionText: transactionText ?? null,
|
||||
};
|
||||
@@ -185,28 +189,40 @@ export async function recordShipmentHistory(runner, { articleId, companyuserId,
|
||||
}
|
||||
|
||||
/** Records warehouse inventory ledger entry (Inbound "Lieferung" / Outbound "Lieferschein"). */
|
||||
export async function recordWarehouseHistory(runner, { articleId, companyuserId, date, manifestNumber, manifestType, warehouseName, amount, transactionText }) {
|
||||
export async function recordWarehouseHistory(runner, { articleId, companyuserId, date, manifestNumber, manifestType, warehouseName, amount, pu, manifestAmount, transactionText }) {
|
||||
const isShipment = manifestType === 'shipment' || (amount != null && Number(amount) < 0);
|
||||
const prefix = isShipment ? 'Lieferschein' : 'Lieferung';
|
||||
const displayAmount = amount != null ? Math.abs(Number(amount)) : null;
|
||||
|
||||
const numPu = pu != null ? Number(pu) : 1;
|
||||
const numManifestAmount = manifestAmount != null ? Math.abs(Number(manifestAmount)) : null;
|
||||
|
||||
const details = [];
|
||||
if (warehouseName) details.push(`Lager: "${warehouseName}"`);
|
||||
if (displayAmount != null && Number.isFinite(displayAmount)) details.push(`Menge: ${displayAmount}`);
|
||||
if (displayAmount != null && Number.isFinite(displayAmount)) {
|
||||
if (numPu > 1 && numManifestAmount != null) {
|
||||
details.push(`Menge: ${displayAmount} (${numManifestAmount} x VPE ${numPu})`);
|
||||
} else if (numPu > 1) {
|
||||
details.push(`Menge: ${displayAmount} (VPE: ${numPu})`);
|
||||
} else {
|
||||
details.push(`Menge: ${displayAmount}`);
|
||||
}
|
||||
}
|
||||
|
||||
const base = manifestNumber ? `${prefix} ${manifestNumber}` : (transactionText?.trim() || prefix);
|
||||
const meta = {
|
||||
type: isShipment ? 'warehouse_out' : 'warehouse_in', manifestNumber: manifestNumber ?? null,
|
||||
deliveryNumber: !isShipment ? (manifestNumber ?? null) : null, shipmentNumber: isShipment ? (manifestNumber ?? null) : null,
|
||||
warehouseName: warehouseName ?? null, amount: toNumOrNull(amount), transactionText: transactionText ?? null,
|
||||
warehouseName: warehouseName ?? null, amount: toNumOrNull(amount), pu: numPu,
|
||||
manifestAmount: numManifestAmount, transactionText: transactionText ?? null,
|
||||
};
|
||||
return recordArticleHistory(runner, { articleId, companyuserId, date, text: `${base}${fmtSuffix(details)}`, meta });
|
||||
}
|
||||
|
||||
/** Backward-compatible helper that records delivery / warehouse ledger entry in article history. */
|
||||
export async function recordDeliveryHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, warehouseName, net, rebate, taxrate, amount, transactionText, isDelivery = true }) {
|
||||
export async function recordDeliveryHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, warehouseName, net, rebate, taxrate, amount, pu, manifestAmount, transactionText, isDelivery = true }) {
|
||||
if (isDelivery && !warehouseName) {
|
||||
return recordAcceptanceHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, net, rebate, taxrate, amount, transactionText });
|
||||
return recordAcceptanceHistory(runner, { articleId, companyuserId, date, manifestNumber, supplierName, net, rebate, taxrate, amount, pu, transactionText });
|
||||
}
|
||||
|
||||
let historyText = transactionText;
|
||||
@@ -220,7 +236,17 @@ export async function recordDeliveryHistory(runner, { articleId, companyuserId,
|
||||
ekBrutto = round2(calculateGross(net, rebate, taxrate)).toFixed(2);
|
||||
details.push(`EK brutto: ${ekBrutto}`);
|
||||
}
|
||||
if (isFiniteNum(amount)) details.push(`Menge: ${amount}`);
|
||||
const numPu = pu != null ? Number(pu) : 1;
|
||||
const numManifestAmount = manifestAmount != null ? Math.abs(Number(manifestAmount)) : null;
|
||||
if (isFiniteNum(amount)) {
|
||||
if (numPu > 1 && numManifestAmount != null) {
|
||||
details.push(`Menge: ${amount} (${numManifestAmount} x VPE ${numPu})`);
|
||||
} else if (numPu > 1) {
|
||||
details.push(`Menge: ${amount} (VPE: ${numPu})`);
|
||||
} else {
|
||||
details.push(`Menge: ${amount}`);
|
||||
}
|
||||
}
|
||||
const base = manifestNumber ? `Lieferung ${manifestNumber}` : (transactionText?.trim() || 'Lieferung');
|
||||
historyText = `${base}${fmtSuffix(details)}`;
|
||||
} else if (warehouseName && transactionText && !transactionText.includes(warehouseName)) {
|
||||
@@ -230,6 +256,7 @@ export async function recordDeliveryHistory(runner, { articleId, companyuserId,
|
||||
const meta = {
|
||||
type: isDelivery ? 'delivery' : 'movement', manifestNumber: manifestNumber ?? null, deliveryNumber: manifestNumber ?? null,
|
||||
supplierName: supplierName ?? null, warehouseName: warehouseName ?? null, amount: toNumOrNull(amount),
|
||||
pu: pu != null ? Number(pu) : 1, manifestAmount: manifestAmount != null ? Number(manifestAmount) : null,
|
||||
net: toNumOrNull(net), rebate: rebate != null ? Number(rebate) : 0, taxrate: taxrate != null ? Number(taxrate) : 0,
|
||||
ekBrutto: toNumOrNull(ekBrutto), transactionText: transactionText ?? null,
|
||||
};
|
||||
@@ -393,13 +420,27 @@ export async function recordChildDeletedFromParentHistory(runner, { parentId, co
|
||||
// MARK: - Suppliers
|
||||
|
||||
/** Records adding a supplier to an article. */
|
||||
export async function recordSupplierAddHistory(runner, { articleId, companyuserId, supplierName, supplierSku, netPrice }) {
|
||||
export async function recordSupplierAddHistory(runner, { articleId, companyuserId, supplierName, supplierSku, netPrice, pu }) {
|
||||
const details = [];
|
||||
if (supplierSku) details.push(`Artikelnr: "${supplierSku}"`);
|
||||
if (netPrice != null) details.push(`EK: ${netPrice}`);
|
||||
const resolvedPu = pu != null && Number.isFinite(Number(pu)) ? Number(pu) : 1;
|
||||
details.push(`VPE: ${resolvedPu}`);
|
||||
|
||||
if (isFiniteNum(netPrice)) {
|
||||
const formattedPrice = formatCurrencyDe(netPrice);
|
||||
details.push(`EK: ${formattedPrice}`);
|
||||
} else {
|
||||
details.push('ohne EK');
|
||||
}
|
||||
|
||||
const text = `Lieferant "${supplierName}" hinzugefügt${fmtSuffix(details)}`;
|
||||
const meta = { type: 'supplier_add', supplierName, supplierSku: supplierSku ?? null, netPrice: netPrice ?? null };
|
||||
const meta = {
|
||||
type: 'supplier_add',
|
||||
supplierName,
|
||||
supplierSku: supplierSku ?? null,
|
||||
netPrice: toNumOrNull(netPrice),
|
||||
pu: resolvedPu,
|
||||
};
|
||||
return recordArticleHistory(runner, { articleId, companyuserId, text, meta });
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ export default function create(provider) {
|
||||
|
||||
const actualSku = supplierRow?.sku ?? supplierSku;
|
||||
const actualPrice = supplierRow?.priceNet ?? netPrice;
|
||||
const actualPu = supplierRow?.pu ?? pu;
|
||||
|
||||
await recordSupplierAddHistory(runner, {
|
||||
articleId,
|
||||
@@ -157,6 +158,7 @@ export default function create(provider) {
|
||||
supplierName,
|
||||
supplierSku: actualSku,
|
||||
netPrice: actualPrice,
|
||||
pu: actualPu,
|
||||
});
|
||||
|
||||
return shapeArticleSupplier(supplierRow);
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function create(provider) {
|
||||
|
||||
const lines = normalizeLines(body.lines ?? []);
|
||||
|
||||
const { companyId } = await access(googleAuthId);
|
||||
const { companyId, companyuserId } = await access(googleAuthId);
|
||||
|
||||
const run = async (runner, tx) => {
|
||||
const targetSupplierId = body.supplierId !== undefined ? body.supplierId : body.entityId;
|
||||
@@ -73,6 +73,7 @@ export default function create(provider) {
|
||||
manifestId,
|
||||
lines,
|
||||
ensureTax,
|
||||
companyuserId,
|
||||
});
|
||||
|
||||
await insertAttachments(
|
||||
|
||||
@@ -70,10 +70,10 @@ const SQL_DELIVERY_TOTALS_SQLITE = `
|
||||
COALESCE(SUM(line_net), 0) AS net_total,
|
||||
COALESCE(SUM(amount), 0) AS total_quantity,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END), 0) AS stock_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS stock_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 AND ((amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0)) THEN 1 ELSE 0 END), 0) AS stock_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END), 0) AS stock_quantity,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS stock_booked_quantity,
|
||||
COALESCE(SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS all_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN (amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0) THEN 1 ELSE 0 END), 0) AS all_booked_positions,
|
||||
COALESCE(SUM(booked_amount), 0) AS all_booked_quantity
|
||||
FROM line_data
|
||||
`;
|
||||
@@ -107,10 +107,10 @@ const SQL_DELIVERY_TOTALS_MSSQL = `
|
||||
COALESCE(SUM(line_net), 0) AS net_total,
|
||||
COALESCE(SUM(amount), 0) AS total_quantity,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END), 0) AS stock_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS stock_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 AND ((amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0)) THEN 1 ELSE 0 END), 0) AS stock_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END), 0) AS stock_quantity,
|
||||
COALESCE(SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END), 0) AS stock_booked_quantity,
|
||||
COALESCE(SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END), 0) AS all_booked_positions,
|
||||
COALESCE(SUM(CASE WHEN (amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0) THEN 1 ELSE 0 END), 0) AS all_booked_positions,
|
||||
COALESCE(SUM(booked_amount), 0) AS all_booked_quantity
|
||||
FROM line_data
|
||||
`;
|
||||
@@ -325,10 +325,10 @@ export async function rebuildDeliverySummaries(runner, companyId) {
|
||||
SUM(line_net) AS net_total,
|
||||
SUM(amount) AS total_quantity,
|
||||
SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END) AS stock_positions,
|
||||
SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS stock_booked_positions,
|
||||
SUM(CASE WHEN track_stock = 1 AND ((amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0)) THEN 1 ELSE 0 END) AS stock_booked_positions,
|
||||
SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END) AS stock_quantity,
|
||||
SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS stock_booked_quantity,
|
||||
SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS all_booked_positions,
|
||||
SUM(CASE WHEN (amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0) THEN 1 ELSE 0 END) AS all_booked_positions,
|
||||
SUM(booked_amount) AS all_booked_quantity
|
||||
FROM line_data
|
||||
GROUP BY manifest_id
|
||||
@@ -435,10 +435,10 @@ export async function rebuildDeliverySummaries(runner, companyId) {
|
||||
SUM(line_net) AS net_total,
|
||||
SUM(amount) AS total_quantity,
|
||||
SUM(CASE WHEN track_stock = 1 THEN 1 ELSE 0 END) AS stock_positions,
|
||||
SUM(CASE WHEN track_stock = 1 AND (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS stock_booked_positions,
|
||||
SUM(CASE WHEN track_stock = 1 AND ((amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0)) THEN 1 ELSE 0 END) AS stock_booked_positions,
|
||||
SUM(CASE WHEN track_stock = 1 THEN amount ELSE 0 END) AS stock_quantity,
|
||||
SUM(CASE WHEN track_stock = 1 THEN booked_amount ELSE 0 END) AS stock_booked_quantity,
|
||||
SUM(CASE WHEN (CASE WHEN amount > 0 THEN booked_amount >= amount ELSE booked_amount > 0 END) THEN 1 ELSE 0 END) AS all_booked_positions,
|
||||
SUM(CASE WHEN (amount > 0 AND booked_amount >= amount) OR (amount <= 0 AND booked_amount > 0) THEN 1 ELSE 0 END) AS all_booked_positions,
|
||||
SUM(booked_amount) AS all_booked_quantity
|
||||
FROM line_data
|
||||
GROUP BY manifest_id
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function update(provider) {
|
||||
normalizedLines = normalizeLines(patch.lines);
|
||||
}
|
||||
|
||||
const { companyId } = await access(googleAuthId);
|
||||
const { companyId, companyuserId } = await access(googleAuthId);
|
||||
|
||||
const run = async (runner, tx) => {
|
||||
const existing = await runner(queries.GET_DELIVERY_HEADER, {
|
||||
@@ -141,6 +141,7 @@ export default function update(provider) {
|
||||
manifestId: id,
|
||||
lines: normalizedLines,
|
||||
ensureTax,
|
||||
companyuserId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,10 @@ export default function add(provider) {
|
||||
memo: text,
|
||||
});
|
||||
|
||||
const linePu = manifestArticle.linePu != null && Number(manifestArticle.linePu) > 0
|
||||
? Number(manifestArticle.linePu)
|
||||
: 1;
|
||||
|
||||
// Record history for acceptance
|
||||
for (const match of articleMatches) {
|
||||
const touchSql = isSqlite ? SQLITE_TOUCH : MSSQL_TOUCH;
|
||||
@@ -223,6 +227,7 @@ export default function add(provider) {
|
||||
rebate: manifestArticle.rebate,
|
||||
taxrate: manifestArticle.taxrate,
|
||||
amount: Math.abs(amount),
|
||||
pu: linePu,
|
||||
transactionText: text,
|
||||
});
|
||||
}
|
||||
@@ -245,10 +250,12 @@ export default function add(provider) {
|
||||
warehouseName = defWh.rows[0].name;
|
||||
}
|
||||
|
||||
const stockRowAmount = Math.abs(amount) * linePu;
|
||||
|
||||
await insertLedgerRow({
|
||||
whId: effectiveWhId,
|
||||
type: 'WAREHOUSE',
|
||||
rowAmount: Math.abs(amount),
|
||||
rowAmount: stockRowAmount,
|
||||
memo: text,
|
||||
});
|
||||
|
||||
@@ -265,7 +272,9 @@ export default function add(provider) {
|
||||
manifestNumber: deliveryNumber,
|
||||
manifestType: 'delivery',
|
||||
warehouseName,
|
||||
amount: Math.abs(amount),
|
||||
amount: stockRowAmount,
|
||||
pu: linePu,
|
||||
manifestAmount: Math.abs(amount),
|
||||
transactionText: text,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import {
|
||||
CHECK_ARTICLE_IS_PARENT as MSSQL_CHECK_ARTICLE_IS_PARENT,
|
||||
CREATE_LINE as MSSQL_CREATE_LINE,
|
||||
GET_MANIFEST_CONTEXT as MSSQL_GET_MANIFEST_CONTEXT,
|
||||
GET_ARTICLE_SUPPLIER_LINK as MSSQL_GET_ARTICLE_SUPPLIER_LINK,
|
||||
UPDATE_ARTICLE_SUPPLIER_LINK as MSSQL_UPDATE_ARTICLE_SUPPLIER_LINK,
|
||||
} from '../providers/mssql/queries/manifestDoc.js';
|
||||
import {
|
||||
CHECK_ARTICLE_IS_PARENT as SQLITE_CHECK_ARTICLE_IS_PARENT,
|
||||
CREATE_LINE as SQLITE_CREATE_LINE,
|
||||
GET_MANIFEST_CONTEXT as SQLITE_GET_MANIFEST_CONTEXT,
|
||||
GET_ARTICLE_SUPPLIER_LINK as SQLITE_GET_ARTICLE_SUPPLIER_LINK,
|
||||
UPDATE_ARTICLE_SUPPLIER_LINK as SQLITE_UPDATE_ARTICLE_SUPPLIER_LINK,
|
||||
} from '../providers/sqlite3/queries/manifestDoc.js';
|
||||
import { formatCurrencyDe, recordArticleHistory } from './articlehistory/record.js';
|
||||
import makeRunner from './runner.js';
|
||||
|
||||
/**
|
||||
@@ -123,14 +130,23 @@ export async function insertLines(
|
||||
params = txOrParams;
|
||||
}
|
||||
|
||||
const { manifestId, lines, ensureTax } = params;
|
||||
const { manifestId, lines, ensureTax, companyuserId } = params;
|
||||
const isSqlite = runner?.dialect === 'sqlite3';
|
||||
const createLineSql = isSqlite ? SQLITE_CREATE_LINE : MSSQL_CREATE_LINE;
|
||||
const checkParentSql = isSqlite ? SQLITE_CHECK_ARTICLE_IS_PARENT : MSSQL_CHECK_ARTICLE_IS_PARENT;
|
||||
const getManifestContextSql = isSqlite ? SQLITE_GET_MANIFEST_CONTEXT : MSSQL_GET_MANIFEST_CONTEXT;
|
||||
const getArticleSupplierLinkSql = isSqlite ? SQLITE_GET_ARTICLE_SUPPLIER_LINK : MSSQL_GET_ARTICLE_SUPPLIER_LINK;
|
||||
const updateArticleSupplierLinkSql = isSqlite ? SQLITE_UPDATE_ARTICLE_SUPPLIER_LINK : MSSQL_UPDATE_ARTICLE_SUPPLIER_LINK;
|
||||
|
||||
const manifestCtxRes = await runner.query(getManifestContextSql, { manifestId });
|
||||
const manifestCtx = manifestCtxRes.rows[0];
|
||||
const isDelivery = String(manifestCtx?.type || '').toLowerCase() === 'delivery';
|
||||
const supplierEntityId = manifestCtx?.entityId != null ? Number(manifestCtx.entityId) : null;
|
||||
|
||||
for (const line of lines) {
|
||||
let resolvedName = line.name;
|
||||
let resolvedPu = line.pu;
|
||||
let connectedArticleId = null;
|
||||
|
||||
if (line.sku) {
|
||||
const parentCheck = await runner.query(checkParentSql, {
|
||||
@@ -147,11 +163,103 @@ export async function insertLines(
|
||||
if (resolvedPu == null && art?.pu != null) {
|
||||
resolvedPu = art.pu;
|
||||
}
|
||||
if (art?.id != null) {
|
||||
connectedArticleId = art.id;
|
||||
}
|
||||
}
|
||||
|
||||
resolvedName = resolvedName || line.sku || null;
|
||||
resolvedPu = resolvedPu ?? 1;
|
||||
|
||||
// Link table check: if delivery manifest has supplier entity and line connects to an article
|
||||
if (isDelivery && supplierEntityId && connectedArticleId) {
|
||||
const linkRes = await runner.query(getArticleSupplierLinkSql, {
|
||||
articleId: connectedArticleId,
|
||||
entityId: supplierEntityId,
|
||||
});
|
||||
const supplierLink = linkRes.rows[0];
|
||||
if (supplierLink) {
|
||||
const oldPu = supplierLink.pu != null ? Number(supplierLink.pu) : 1;
|
||||
const newPu = Number(resolvedPu);
|
||||
const puChanged = Number.isFinite(newPu) && newPu > 0 && newPu !== oldPu;
|
||||
|
||||
const oldNet = supplierLink.net != null ? Number(supplierLink.net) : null;
|
||||
const lineNet = line.net != null && Number.isFinite(Number(line.net)) ? Number(line.net) : null;
|
||||
const netChanged = lineNet !== null && lineNet > 0 && (oldNet === null || lineNet !== oldNet);
|
||||
|
||||
const oldTaxRate = supplierLink.taxRate != null ? Number(supplierLink.taxRate) : null;
|
||||
const oldTaxId = supplierLink.taxId ?? null;
|
||||
const lineTaxRate = line.taxrate != null && Number.isFinite(Number(line.taxrate)) && Number(line.taxrate) >= 0
|
||||
? Number(line.taxrate)
|
||||
: null;
|
||||
|
||||
let targetTaxId = oldTaxId;
|
||||
let taxChanged = false;
|
||||
|
||||
if (lineTaxRate !== null && (oldTaxId === null || oldTaxRate === null || lineTaxRate !== oldTaxRate)) {
|
||||
if (ensureTax) {
|
||||
targetTaxId = await ensureTax(lineTaxRate, runner);
|
||||
taxChanged = targetTaxId !== null && (targetTaxId !== oldTaxId || lineTaxRate !== oldTaxRate);
|
||||
}
|
||||
}
|
||||
|
||||
if (puChanged || netChanged || taxChanged) {
|
||||
const nextPu = puChanged ? newPu : oldPu;
|
||||
const nextNet = netChanged ? lineNet : oldNet;
|
||||
const nextTaxId = taxChanged ? targetTaxId : oldTaxId;
|
||||
|
||||
await runner.query(updateArticleSupplierLinkSql, {
|
||||
id: supplierLink.id,
|
||||
pu: nextPu,
|
||||
net: nextNet,
|
||||
taxId: nextTaxId,
|
||||
});
|
||||
|
||||
// Update in-memory row in case duplicate line items appear in same manifest
|
||||
supplierLink.pu = nextPu;
|
||||
supplierLink.net = nextNet;
|
||||
supplierLink.taxId = nextTaxId;
|
||||
if (lineTaxRate !== null) {
|
||||
supplierLink.taxRate = lineTaxRate;
|
||||
}
|
||||
|
||||
const supplierName = supplierLink.supplierName || manifestCtx?.entityName || `Lieferant #${supplierEntityId}`;
|
||||
const details = [];
|
||||
if (puChanged) {
|
||||
details.push(`VPE: ${nextPu}`);
|
||||
}
|
||||
if (netChanged) {
|
||||
details.push(`EK: ${formatCurrencyDe(nextNet)}`);
|
||||
}
|
||||
if (taxChanged && lineTaxRate !== null) {
|
||||
details.push(`MwSt.: ${lineTaxRate}%`);
|
||||
}
|
||||
|
||||
const text = `Lieferant "${supplierName}" aktualisiert (${details.join(', ')})`;
|
||||
const meta = {
|
||||
type: 'supplier_update',
|
||||
supplierName,
|
||||
supplierSku: supplierLink.sku ?? null,
|
||||
pu: nextPu,
|
||||
netPrice: nextNet != null ? Number(nextNet) : null,
|
||||
taxRate: lineTaxRate ?? oldTaxRate,
|
||||
taxId: nextTaxId,
|
||||
oldPu,
|
||||
oldNetPrice: oldNet,
|
||||
oldTaxRate,
|
||||
oldTaxId,
|
||||
};
|
||||
|
||||
await recordArticleHistory(runner, {
|
||||
articleId: connectedArticleId,
|
||||
companyuserId,
|
||||
text,
|
||||
meta,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ensureTax) {
|
||||
await ensureTax(line.taxrate, runner);
|
||||
}
|
||||
|
||||
@@ -119,6 +119,10 @@ export default function accept(provider) {
|
||||
}
|
||||
|
||||
const lineAmount = Number(manifestArticle.lineAmount || 0);
|
||||
const linePu = manifestArticle.linePu != null && Number(manifestArticle.linePu) > 0
|
||||
? Number(manifestArticle.linePu)
|
||||
: 1;
|
||||
const stockAmount = lineAmount * linePu;
|
||||
const deliveryNumber = manifestArticle.manifestNumber;
|
||||
const isReturn = lineAmount < 0;
|
||||
|
||||
@@ -179,6 +183,7 @@ export default function accept(provider) {
|
||||
rebate: manifestArticle.rebate,
|
||||
taxrate: manifestArticle.taxrate,
|
||||
amount: docAmount,
|
||||
pu: linePu,
|
||||
transactionText: docText,
|
||||
});
|
||||
}
|
||||
@@ -191,7 +196,9 @@ export default function accept(provider) {
|
||||
{
|
||||
manifestarticleId,
|
||||
warehouseId: item.warehouseId,
|
||||
amount: docAmount,
|
||||
amount: stockAmount,
|
||||
pu: linePu,
|
||||
manifestAmount: lineAmount,
|
||||
text: docText,
|
||||
},
|
||||
activeTx,
|
||||
|
||||
@@ -71,7 +71,7 @@ export default function adjust(provider) {
|
||||
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
|
||||
`SELECT ma.id, ma.manifest_id, ma.sku, ma.name, ma.amount, ma.pu, 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`,
|
||||
@@ -173,6 +173,13 @@ export default function adjust(provider) {
|
||||
await runner.query(touchSql, { articleId: art.id });
|
||||
await runner.query(touchStuecklisteSql, { articleId: art.id });
|
||||
|
||||
const effectivePu = input.pu != null
|
||||
? Number(input.pu)
|
||||
: (manifestArticle.pu != null && Number(manifestArticle.pu) > 0 ? Number(manifestArticle.pu) : 1);
|
||||
const effectiveManifestAmount = input.manifestAmount != null
|
||||
? Number(input.manifestAmount)
|
||||
: (manifestArticle.amount != null ? Number(manifestArticle.amount) : null);
|
||||
|
||||
// Write warehouse history for tracked article
|
||||
if (manifestArticle.manifest_type === 'delivery') {
|
||||
await recordWarehouseHistory(runner, {
|
||||
@@ -182,6 +189,8 @@ export default function adjust(provider) {
|
||||
manifestType: 'delivery',
|
||||
warehouseName,
|
||||
amount,
|
||||
pu: effectivePu,
|
||||
manifestAmount: effectiveManifestAmount,
|
||||
transactionText: text,
|
||||
});
|
||||
} else if (manifestArticle.manifest_type === 'shipment') {
|
||||
|
||||
Reference in New Issue
Block a user