delivery seemds to work.

This commit is contained in:
seb
2026-07-13 03:40:14 +02:00
parent 03dde8eff8
commit 955fe2c164
12 changed files with 985 additions and 573 deletions

View File

@@ -1,6 +1,7 @@
import sql from 'mssql';
import { getPool } from '../db.js';
import { getActiveShopId, getActiveShopSubshopId } from '../shop.js';
import { deliverOrder } from './delivery/index.js';
const config = {
kBenutzer: Number(process.env.JTL_KBENUTZER) || 1,
@@ -389,13 +390,12 @@ async function insertPosOrderPositionMapping(transaction, kAuftragPosition, kPos
* order is created, `Settings.Deliver` (default true, see decompiled
* jtlCore.Classes.Sync.PosOrderSteps.DeliveryStep:199,
* `bool flag = orderEntity.Settings?.Deliver ?? true;`) decides whether the
* order is delivered immediately. JTL's real implementation books stock via
* the full Auslieferung/warehouse engine; we reproduce its DB end-state
* directly via the same stored procedures it ultimately relies on
* (Versand.spLieferscheinErstellen / spLieferscheinPosErstellen), which also
* call Verkauf.spAuftragEckdatenBerechnen and are what actually derive
* nKomplettAusgeliefert. Digital-voucher partial delivery (IstGutscheinDigital)
* is intentionally not reproduced.
* order is delivered immediately. Digital-voucher partial delivery
* (IstGutscheinDigital) is intentionally not reproduced.
*
* The actual delivery mechanics (Pickliste creation, real stock decrement,
* numbered Lieferschein) live in ./delivery/ - see delivery.md for the full
* investigation behind it.
*/
function isOrderDelivered(order) {
const deliver = order.settings?.deliver;
@@ -405,48 +405,6 @@ function isOrderDelivered(order) {
return deliver === true || String(deliver) === '1' || String(deliver).toLowerCase() === 'true';
}
async function createLieferschein(transaction, kAuftrag) {
const request = new sql.Request(transaction);
request.input('kBestellung', sql.Int, kAuftrag);
request.input('kBenutzer', sql.Int, config.kBenutzer);
request.input('cLieferscheinNr', sql.NVarChar(50), null);
request.input('cHinweis', sql.NVarChar(255), null);
request.input('dMailVersand', sql.DateTime, null);
request.input('dGedruckt', sql.DateTime, null);
request.input('nFulfillment', sql.Int, null);
request.input('kLieferantenBestellung', sql.Int, null);
request.input('kSessionId', sql.Int, null);
request.output('kLieferschein', sql.Int);
const result = await request.execute('Versand.spLieferscheinErstellen');
return result.output.kLieferschein;
}
async function createLieferscheinPos(transaction, kLieferschein, kAuftragPosition, quantity) {
const request = new sql.Request(transaction);
request.input('kLieferschein', sql.Int, kLieferschein);
request.input('kBestellPos', sql.Int, kAuftragPosition);
request.input('fAnzahl', sql.Decimal(25, 13), quantity);
request.input('cHinweis', sql.NVarChar(4000), '');
request.output('kLieferscheinPos', sql.Int);
await request.execute('Versand.spLieferscheinPosErstellen');
}
/**
* Delivers the full ordered quantity of every position (no partial delivery),
* mirroring DeliveryStep's non-voucher path. Uses the server's current time
* throughout (see createOrder), so there is never a past order date to
* backdate Versanddatum against.
*/
async function deliverOrder(transaction, kAuftrag, deliveredItems) {
if (!deliveredItems.length) {
return;
}
const kLieferschein = await createLieferschein(transaction, kAuftrag);
for (const { kAuftragPosition, quantity } of deliveredItems) {
await createLieferscheinPos(transaction, kLieferschein, kAuftragPosition, quantity);
}
}
async function insertPayment(transaction, kAuftrag, payment, order, orderDate, zahlungsartCache) {
const zahlungsart = await resolveZahlungsart(transaction, payment.paymentMethodName || order.paymentMethodName, zahlungsartCache);
const kZahlung = await allocatePk(transaction, 'tZahlung');
@@ -539,7 +497,7 @@ export async function createOrder(order) {
}
if (isOrderDelivered(order)) {
await deliverOrder(transaction, kAuftrag, deliveredItems);
await deliverOrder(transaction, config.kBenutzer, kAuftrag, defaults.kVersandArt, deliveredItems);
}
await new sql.Request(transaction).input('kAuftrag', sql.Int, kAuftrag).query(`