This commit is contained in:
seb
2026-07-15 01:25:38 +02:00
parent 7fa839da4d
commit 056c9e18cd
21 changed files with 1181 additions and 64 deletions

View File

@@ -248,6 +248,18 @@ function isWalkInOrder(order) {
return (billing.lastName || '') === 'Laufkunde' && !(billing.firstName || '').trim();
}
function resolveAuftragCKundenNr(order) {
return isWalkInOrder(order) ? '0' : String(order.customerNumber || '');
}
/** POS settings.invoiceSetting: 0 = external/POS invoice (nIstExterneRechnung=1). */
function resolveNIstExterneRechnung(order) {
const inv = order.settings?.invoiceSetting;
if (inv === undefined || inv === null) return 1;
if (inv === true || inv === 1 || inv === '1' || String(inv).toLowerCase() === 'true') return 0;
return 1;
}
async function lookupKassenkunde(transaction, defaults) {
const result = await new sql.Request(transaction).query(
"SELECT TOP 1 kKunde, kKundenGruppe FROM dbo.tKunde WHERE cKassenKunde = 'Y' ORDER BY kKunde"
@@ -374,9 +386,15 @@ async function insertOrderItem(transaction, kAuftrag, item) {
/**
* JTL PosOrderCreationService.CheckIfOrderExists — skip re-import when the POS
* order id is already mapped to a Wawi order for this subshop.
* order id is already mapped to a Wawi order for this subshop with the same
* external receipt number.
*/
async function findExistingPosOrderMapping(kPosAuftrag) {
function externalOrderNumbersMatch(mapped, incoming) {
if (!incoming) return true;
return String(mapped || '').toLowerCase() === String(incoming).toLowerCase();
}
async function findExistingPosOrderMapping(kPosAuftrag, externalOrderNumber) {
const kShopSubShop = getActiveShopSubshopId();
if (!Number.isInteger(kPosAuftrag) || !kShopSubShop) {
return null;
@@ -387,7 +405,7 @@ async function findExistingPosOrderMapping(kPosAuftrag) {
.input('kPosAuftrag', sql.Int, kPosAuftrag)
.input('kShopSubShop', sql.Int, kShopSubShop)
.query(`
SELECT TOP 1 m.kAuftrag, a.cAuftragsNr
SELECT TOP 1 m.kAuftrag, a.cAuftragsNr, ISNULL(a.cExterneAuftragsnummer, '') AS cExterneAuftragsnummer
FROM Pos.tAuftragMapping m
LEFT JOIN Verkauf.tAuftrag a ON a.kAuftrag = m.kAuftrag
WHERE m.kPosAuftrag = @kPosAuftrag
@@ -400,6 +418,9 @@ async function findExistingPosOrderMapping(kPosAuftrag) {
if (!row?.kAuftrag) {
return null;
}
if (!externalOrderNumbersMatch(row.cExterneAuftragsnummer, externalOrderNumber)) {
return null;
}
return row;
}
@@ -412,20 +433,21 @@ async function upsertPosOrderMapping(transaction, kAuftrag, kPosAuftrag) {
if (!Number.isInteger(kPosAuftrag) || !kShopSubShop) {
return;
}
await new sql.Request(transaction)
.input('kPosAuftrag', sql.Int, kPosAuftrag)
.input('kShopSubShop', sql.Int, kShopSubShop)
.query(`
DELETE FROM Pos.tAuftragMapping
WHERE kPosAuftrag = @kPosAuftrag
AND kShopSubShop = @kShopSubShop
`);
await new sql.Request(transaction)
.input('kAuftrag', sql.Int, kAuftrag)
.input('kPosAuftrag', sql.Int, kPosAuftrag)
.input('kShopSubShop', sql.Int, kShopSubShop)
.query(`
MERGE INTO Pos.tAuftragMapping WITH (HOLDLOCK) AS Target
USING (SELECT @kAuftrag AS kAuftrag, @kPosAuftrag AS kPosAuftrag, @kShopSubShop AS kShopSubShop) AS Source
ON Target.kPosAuftrag = Source.kPosAuftrag
AND Target.kShopSubShop = Source.kShopSubShop
WHEN MATCHED THEN
UPDATE SET Target.kAuftrag = Source.kAuftrag
WHEN NOT MATCHED BY TARGET THEN
INSERT (kAuftrag, kPosAuftrag, kShopSubShop)
VALUES (Source.kAuftrag, Source.kPosAuftrag, Source.kShopSubShop);
INSERT INTO Pos.tAuftragMapping (kAuftrag, kPosAuftrag, kShopSubShop)
VALUES (@kAuftrag, @kPosAuftrag, @kShopSubShop)
`);
}
@@ -488,12 +510,14 @@ async function insertPayment(transaction, kAuftrag, payment, order, orderDate, z
export async function createOrder(order) {
const kPosAuftrag = Number.parseInt(order.externalId, 10);
const externalOrderNumber = order.externalOrderNumber || '';
if (Number.isInteger(kPosAuftrag) && kPosAuftrag > 0) {
const existing = await findExistingPosOrderMapping(kPosAuftrag);
const existing = await findExistingPosOrderMapping(kPosAuftrag, externalOrderNumber);
if (existing) {
return {
orderId: String(existing.kAuftrag),
orderNumber: existing.cAuftragsNr || '',
alreadyExists: true,
};
}
}
@@ -523,24 +547,25 @@ export async function createOrder(order) {
.input('cWaehrung', sql.NVarChar, order.currencyIso || 'EUR')
.input('kPlattform', sql.Int, defaults.kPlattform)
.input('kShop', sql.Int, getActiveShopId() || null)
.input('cKundenNr', sql.NVarChar, String(order.customerNumber || ''))
.input('cKundenNr', sql.NVarChar, resolveAuftragCKundenNr(order))
.input('cVersandlandISO', sql.NVarChar, (order.shippingAddress?.countryIso || 'DE').toUpperCase())
.input('kVersandArt', sql.Int, defaults.kVersandArt)
.input('kZahlungsart', sql.Int, zahlungsart.kZahlungsart)
.input('kKundengruppe', sql.Int, kKundengruppe)
.input('cExterneAuftragsnummer', sql.NVarChar, order.externalOrderNumber || '')
.input('nIstExterneRechnung', sql.Int, resolveNIstExterneRechnung(order))
.query(`
DECLARE @t TABLE ([kAuftrag] INT);
INSERT INTO Verkauf.tAuftrag
(cAuftragsNr, dErstellt, nKomplettAusgeliefert, kBenutzer, kKunde, kBenutzerErstellt, nType, fFaktor,
kFirmaHistory, kSprache, cVersandlandWaehrung, fVersandlandWaehrungFaktor, fFinanzierungskosten,
cWaehrung, kPlattform, kShop, cKundenNr, cVersandlandISO, kVersandArt, kZahlungsart, kKundengruppe,
cExterneAuftragsnummer)
cExterneAuftragsnummer, nIstExterneRechnung, cInet, nIstReadOnly, kShopauftrag, nLieferPrioritaet)
OUTPUT inserted.kAuftrag INTO @t
VALUES (@cAuftragsNr, @dErstellt, 0, @kBenutzer, @kKunde, @kBenutzer, 1, 1.0,
@kFirmaHistory, @kSprache, @cWaehrung, 1.0, 0.0,
@cWaehrung, @kPlattform, @kShop, @cKundenNr, @cVersandlandISO, @kVersandArt, @kZahlungsart, @kKundengruppe,
@cExterneAuftragsnummer);
@cExterneAuftragsnummer, @nIstExterneRechnung, 'Y', 2, 0, 10);
SELECT kAuftrag FROM @t;
`);
@@ -578,7 +603,7 @@ export async function createOrder(order) {
await transaction.commit();
return { orderId: String(kAuftrag), orderNumber: cAuftragsNr };
return { orderId: String(kAuftrag), orderNumber: cAuftragsNr, alreadyExists: false };
} catch (err) {
try {
await transaction.rollback();