u
This commit is contained in:
190
src/services/companyImport/articleImporter.js
Normal file
190
src/services/companyImport/articleImporter.js
Normal file
@@ -0,0 +1,190 @@
|
||||
// MARK: - Imports
|
||||
// #region Imports
|
||||
import { cleanValue, parseGermanFloat } from './csvParser.js';
|
||||
import { createLogger } from '../../util/logger.js';
|
||||
// #endregion
|
||||
|
||||
const log = createLogger('import');
|
||||
|
||||
// MARK: - Article Importer
|
||||
// #region Article Importer
|
||||
|
||||
/**
|
||||
* Imports articles (insert or update), setting prices, categories, barcodes, and brands.
|
||||
*
|
||||
* @param {object} params
|
||||
* @param {object} params.store - Store singleton
|
||||
* @param {number} params.googleAuthId
|
||||
* @param {Array<Record<string, string>>} params.includedArticles
|
||||
* @param {Map<string, number>} params.jtlCatIdToDashCatId
|
||||
* @param {number} params.hauptDashId
|
||||
* @param {Map<string, number>} params.brandNameToId
|
||||
* @param {object} params.progressTracker
|
||||
* @returns {Promise<{ jtlArtIdToSku: Map<string, string>, articlesImported: number, articlesUpdated: number }>}
|
||||
*/
|
||||
export async function importArticles({
|
||||
store,
|
||||
googleAuthId,
|
||||
includedArticles,
|
||||
jtlCatIdToDashCatId,
|
||||
hauptDashId,
|
||||
brandNameToId,
|
||||
progressTracker,
|
||||
}) {
|
||||
const jtlArtIdToSku = new Map();
|
||||
let articlesImported = 0;
|
||||
let articlesUpdated = 0;
|
||||
|
||||
for (const a of includedArticles) {
|
||||
const jtlArtId = String(a.kArtikel);
|
||||
const sku = cleanValue(a.cArtNr);
|
||||
if (!sku) {
|
||||
progressTracker.counts.articlesdone++;
|
||||
continue;
|
||||
}
|
||||
|
||||
jtlArtIdToSku.set(jtlArtId, sku);
|
||||
|
||||
let name = cleanValue(a.cName);
|
||||
let desc = cleanValue(a.descriptions);
|
||||
|
||||
if (!name && desc) {
|
||||
try {
|
||||
const parsed = JSON.parse(desc);
|
||||
const item = Array.isArray(parsed) ? parsed[0] : parsed;
|
||||
if (item?.cName) name = String(item.cName).trim();
|
||||
if (item?.cBeschreibung) desc = String(item.cBeschreibung).trim();
|
||||
} catch {}
|
||||
}
|
||||
if (!name) name = `Artikel ${sku}`;
|
||||
|
||||
// Category mapping
|
||||
const assignedDashCatIds = [];
|
||||
const rawCatStr = String(a.categories || '').trim();
|
||||
if (rawCatStr) {
|
||||
let parsedIds = [];
|
||||
if (rawCatStr.startsWith('[') || rawCatStr.startsWith('{')) {
|
||||
try {
|
||||
const raw = JSON.parse(rawCatStr);
|
||||
parsedIds = (Array.isArray(raw) ? raw : [raw]).map((it) => String(it.kKategorie || it));
|
||||
} catch {
|
||||
parsedIds = rawCatStr.split(/[\r\n,;]+/).map((s) => s.trim()).filter(Boolean);
|
||||
}
|
||||
} else {
|
||||
parsedIds = rawCatStr.split(/[\r\n,;]+/).map((s) => s.trim()).filter(Boolean);
|
||||
}
|
||||
for (const jtlCId of parsedIds) {
|
||||
if (jtlCatIdToDashCatId.has(jtlCId)) {
|
||||
assignedDashCatIds.push(jtlCatIdToDashCatId.get(jtlCId));
|
||||
}
|
||||
}
|
||||
}
|
||||
const primaryCatId = assignedDashCatIds[0] || hauptDashId;
|
||||
|
||||
const trackStock = a.cLagerAktiv === 'Y' ? 1 : 0;
|
||||
const netPrice = parseGermanFloat(a.fVKNetto, 0);
|
||||
const taxRate = a.kSteuerklasse === '3' ? 7 : 19;
|
||||
const barcode = cleanValue(a.cBarcode);
|
||||
|
||||
const hersteller = cleanValue(a.Hersteller);
|
||||
const brandId = hersteller ? (brandNameToId.get(hersteller.toLowerCase()) || null) : null;
|
||||
|
||||
let existingArticle = null;
|
||||
try {
|
||||
const res = await store.article.getBySku(googleAuthId, sku);
|
||||
existingArticle = res.article;
|
||||
} catch {
|
||||
existingArticle = null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (existingArticle) {
|
||||
await store.article.updateBySku(googleAuthId, sku, {
|
||||
name,
|
||||
track_stock: trackStock,
|
||||
desc: desc || undefined,
|
||||
});
|
||||
|
||||
await store.article.setPricesBySku(googleAuthId, sku, [
|
||||
{ net: netPrice, tax: taxRate },
|
||||
]);
|
||||
|
||||
if (assignedDashCatIds.length > 0) {
|
||||
await store.article.setCategoryIdsBySku(googleAuthId, sku, assignedDashCatIds);
|
||||
}
|
||||
|
||||
if (barcode) {
|
||||
try {
|
||||
const currentEans = existingArticle.eans || [];
|
||||
if (!currentEans.includes(barcode)) {
|
||||
await store.article.setEansBySku(googleAuthId, sku, [...currentEans, barcode]);
|
||||
}
|
||||
} catch (eanErr) {
|
||||
log.warn(`Could not set EAN for ${sku}:`, eanErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (brandId && existingArticle.brand?.id !== brandId) {
|
||||
try {
|
||||
await store.article.setBrandIdBySku(googleAuthId, sku, brandId);
|
||||
} catch (bErr) {
|
||||
log.warn(`Could not set brand for ${sku}:`, bErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
articlesUpdated++;
|
||||
} else {
|
||||
await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: primaryCatId,
|
||||
name,
|
||||
sku,
|
||||
track_stock: trackStock,
|
||||
desc: desc || undefined,
|
||||
});
|
||||
|
||||
await store.article.setPricesBySku(googleAuthId, sku, [
|
||||
{ net: netPrice, tax: taxRate },
|
||||
]);
|
||||
|
||||
if (assignedDashCatIds.length > 1) {
|
||||
await store.article.setCategoryIdsBySku(googleAuthId, sku, assignedDashCatIds);
|
||||
}
|
||||
|
||||
if (barcode) {
|
||||
try {
|
||||
await store.article.setEansBySku(googleAuthId, sku, [barcode]);
|
||||
} catch (eanErr) {
|
||||
log.warn(`Could not set EAN for ${sku}:`, eanErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (brandId) {
|
||||
try {
|
||||
await store.article.setBrandIdBySku(googleAuthId, sku, brandId);
|
||||
} catch (bErr) {
|
||||
log.warn(`Could not set brand for ${sku}:`, bErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
articlesImported++;
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn(`Failed to save article ${sku} ("${name}"):`, err.message);
|
||||
}
|
||||
|
||||
progressTracker.counts.articlesdone++;
|
||||
progressTracker.emitProgress();
|
||||
}
|
||||
|
||||
progressTracker.emitProgress(true);
|
||||
log.info(`Articles complete: New: ${articlesImported}, Updated: ${articlesUpdated}`);
|
||||
|
||||
return {
|
||||
jtlArtIdToSku,
|
||||
articlesImported,
|
||||
articlesUpdated,
|
||||
};
|
||||
}
|
||||
|
||||
// #endregion
|
||||
Reference in New Issue
Block a user