u
This commit is contained in:
@@ -10,33 +10,37 @@ const log = createLogger('import');
|
||||
// #region Order / Manifest Importer
|
||||
|
||||
/**
|
||||
* Imports order manifests and line items, resolving customer entities.
|
||||
* Imports order manifests and line items, resolving customer entities, payments, and shippings.
|
||||
*
|
||||
* @param {object} params
|
||||
* @param {object} params.store - Store singleton
|
||||
* @param {number} params.googleAuthId
|
||||
* @param {Array<Record<string, string>>} params.manRecords
|
||||
* @param {Array<Record<string, string>>} params.itemRecords
|
||||
* @param {Map<string, string>} [params.jtlArtIdToSku]
|
||||
* @param {object} params.progressTracker
|
||||
* @returns {Promise<{ ordersImported: number, ordersSkipped: number }>}
|
||||
* @returns {Promise<{ ordersImported: number, ordersSkipped: number, paymentsImported: number, shippingsImported: number }>}
|
||||
*/
|
||||
export async function importOrders({
|
||||
store,
|
||||
googleAuthId,
|
||||
manRecords,
|
||||
itemRecords,
|
||||
jtlArtIdToSku = new Map(),
|
||||
progressTracker,
|
||||
}) {
|
||||
let ordersImported = 0;
|
||||
let ordersSkipped = 0;
|
||||
let paymentsImported = 0;
|
||||
let shippingsImported = 0;
|
||||
|
||||
if (manRecords.length === 0 || itemRecords.length === 0) {
|
||||
return { ordersImported, ordersSkipped };
|
||||
return { ordersImported, ordersSkipped, paymentsImported, shippingsImported };
|
||||
}
|
||||
|
||||
const itemsByAuftrag = new Map();
|
||||
for (const it of itemRecords) {
|
||||
const kAuftrag = String(it.kAuftrag || '').trim();
|
||||
const kAuftrag = String(it.manifestid ?? it.kAuftrag ?? '').trim();
|
||||
if (!kAuftrag) continue;
|
||||
if (!itemsByAuftrag.has(kAuftrag)) {
|
||||
itemsByAuftrag.set(kAuftrag, []);
|
||||
@@ -88,8 +92,38 @@ export async function importOrders({
|
||||
}
|
||||
};
|
||||
|
||||
const accountMap = new Map();
|
||||
try {
|
||||
const accounts = await store.account.list(googleAuthId);
|
||||
for (const acc of accounts) {
|
||||
if (acc.name) {
|
||||
accountMap.set(acc.name.trim().toLowerCase(), acc.id);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn('Could not list accounts:', err.message);
|
||||
}
|
||||
|
||||
const resolveAccountId = async (accountName) => {
|
||||
const cleanAccName = (accountName || 'Bar').trim();
|
||||
const key = cleanAccName.toLowerCase();
|
||||
if (accountMap.has(key)) return accountMap.get(key);
|
||||
|
||||
try {
|
||||
const created = await store.account.create(googleAuthId, {
|
||||
type: cleanAccName,
|
||||
name: cleanAccName,
|
||||
});
|
||||
accountMap.set(key, created.id);
|
||||
return created.id;
|
||||
} catch (err) {
|
||||
log.warn(`Could not create account "${cleanAccName}":`, err.message);
|
||||
return accountMap.values().next().value || null;
|
||||
}
|
||||
};
|
||||
|
||||
for (const m of manRecords) {
|
||||
const orderNumber = cleanValue(m.cAuftragsNr);
|
||||
const orderNumber = cleanValue(m.nr ?? m.cAuftragsNr);
|
||||
if (!orderNumber || existingOrderNumbers.has(orderNumber)) {
|
||||
ordersSkipped++;
|
||||
progressTracker.counts.receiptsdone++;
|
||||
@@ -97,7 +131,8 @@ export async function importOrders({
|
||||
continue;
|
||||
}
|
||||
|
||||
const rawItems = itemsByAuftrag.get(String(m.kAuftrag || '').trim()) || [];
|
||||
const manifestKey = String(m.id ?? m.kAuftrag ?? '').trim();
|
||||
const rawItems = itemsByAuftrag.get(manifestKey) || [];
|
||||
if (rawItems.length === 0) {
|
||||
ordersSkipped++;
|
||||
progressTracker.counts.receiptsdone++;
|
||||
@@ -105,15 +140,18 @@ export async function importOrders({
|
||||
continue;
|
||||
}
|
||||
|
||||
rawItems.sort((a, b) => (Number(a.sort ?? a.nSort) || 0) - (Number(b.sort ?? b.nSort) || 0));
|
||||
|
||||
const lines = rawItems.map((it) => {
|
||||
const sku = cleanValue(it.cArtNr) || null;
|
||||
const rawName = cleanValue(it.cName || it.cNameStandard);
|
||||
const articleId = cleanValue(it.articleid ?? it.kArtikel);
|
||||
const sku = cleanValue(it.sku ?? it.cArtNr) || (articleId && jtlArtIdToSku?.get?.(articleId)) || null;
|
||||
const rawName = cleanValue(it.name ?? it.cName ?? it.cNameStandard);
|
||||
const name = rawName || (sku ? `Artikel ${sku}` : 'Artikel');
|
||||
const amount = parseGermanFloat(it.fAnzahl, 1);
|
||||
const net = parseGermanFloat(it.fVKNetto, 0);
|
||||
const taxrate = parseGermanFloat(it.fMwSt, 19);
|
||||
const rebate = parseGermanFloat(it.fRabatt, 0);
|
||||
const comment = cleanValue(it.cHinweis) || null;
|
||||
const amount = parseGermanFloat(it.amount ?? it.fAnzahl, 1);
|
||||
const net = parseGermanFloat(it.net ?? it.fVKNetto, 0);
|
||||
const taxrate = parseGermanFloat(it.taxrate ?? it.fMwSt, 19);
|
||||
const rebate = parseGermanFloat(it.rebate ?? it.fRabatt, 0);
|
||||
const comment = cleanValue(it.comment ?? it.cHinweis) || null;
|
||||
|
||||
return {
|
||||
sku,
|
||||
@@ -126,18 +164,19 @@ export async function importOrders({
|
||||
};
|
||||
});
|
||||
|
||||
const custName = cleanValue(m.cName) || 'Laufkunde';
|
||||
const custFirstName = cleanValue(m.cVorname);
|
||||
const custName = cleanValue(m.name ?? m.cName) || 'Laufkunde';
|
||||
const custFirstName = cleanValue(m.firstName ?? m.cVorname);
|
||||
const entityId = await resolveEntityId(custName, custFirstName);
|
||||
|
||||
const dateStr = cleanValue(m.dErstellt);
|
||||
const dateStr = cleanValue(m.created_at ?? m.dErstellt);
|
||||
const parsedDate = dateStr ? new Date(dateStr) : new Date();
|
||||
const validDate = !Number.isNaN(parsedDate.getTime()) ? parsedDate.toISOString() : new Date().toISOString();
|
||||
|
||||
let createdOrder = null;
|
||||
try {
|
||||
await store.order.create(googleAuthId, {
|
||||
createdOrder = await store.order.create(googleAuthId, {
|
||||
number: orderNumber,
|
||||
externalNumber: cleanValue(m.cExterneAuftragsnummer) || null,
|
||||
externalNumber: cleanValue(m.extnr ?? m.cExterneAuftragsnummer) || null,
|
||||
date: validDate,
|
||||
createdAt: validDate,
|
||||
entityId: entityId || undefined,
|
||||
@@ -149,16 +188,67 @@ export async function importOrders({
|
||||
log.warn(`Failed to create order ${orderNumber}:`, err.message);
|
||||
}
|
||||
|
||||
if (createdOrder) {
|
||||
// Handle Payment
|
||||
const isPayed = String(m.payed ?? '').trim() === '1';
|
||||
const paymentType = cleanValue(m.paymentType);
|
||||
if (isPayed && paymentType) {
|
||||
const orderTotal = Math.round(
|
||||
lines.reduce(
|
||||
(sum, l) => sum + (l.amount * l.net * (1 - (l.rebate || 0) / 100) * (1 + (l.taxrate || 0) / 100)),
|
||||
0
|
||||
) * 100
|
||||
) / 100;
|
||||
|
||||
if (orderTotal > 0) {
|
||||
try {
|
||||
const accountId = await resolveAccountId(paymentType);
|
||||
if (accountId) {
|
||||
await store.payment.create(googleAuthId, {
|
||||
accountId,
|
||||
manifestId: createdOrder.id,
|
||||
type: paymentType,
|
||||
amount: orderTotal,
|
||||
});
|
||||
paymentsImported++;
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn(`Failed to create payment for order ${orderNumber}:`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Delivery / Shipping
|
||||
const shippingType = cleanValue(m.shippingType);
|
||||
if (shippingType) {
|
||||
const isShipped = String(m.shipped ?? '').trim() === '1';
|
||||
const shippingState = isShipped ? 'shipped' : 'open';
|
||||
|
||||
try {
|
||||
await store.shipping.create(googleAuthId, {
|
||||
manifestId: createdOrder.id,
|
||||
type: shippingType,
|
||||
state: shippingState,
|
||||
});
|
||||
shippingsImported++;
|
||||
} catch (err) {
|
||||
log.warn(`Failed to create shipping for order ${orderNumber}:`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progressTracker.counts.receiptsdone++;
|
||||
progressTracker.emitProgress();
|
||||
}
|
||||
|
||||
progressTracker.emitProgress(true);
|
||||
log.info(`Orders complete: ${ordersImported} created, ${ordersSkipped} skipped`);
|
||||
log.info(`Orders complete: ${ordersImported} created, ${ordersSkipped} skipped, ${paymentsImported} payments, ${shippingsImported} shippings`);
|
||||
|
||||
return {
|
||||
ordersImported,
|
||||
ordersSkipped,
|
||||
paymentsImported,
|
||||
shippingsImported,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user