u
This commit is contained in:
@@ -474,7 +474,8 @@ export function register(app, basePath = '') {
|
||||
}
|
||||
|
||||
try {
|
||||
fs.rmSync(importDir, { recursive: true, force: true });
|
||||
// Do not clean the import upload directory so files remain available for inspection/analysis
|
||||
// fs.rmSync(importDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(importDir, { recursive: true });
|
||||
|
||||
// Preserve the raw zip archive
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { getStore } from '../db/store.js';
|
||||
import { createLogger } from '../util/logger.js';
|
||||
|
||||
const log = createLogger('import');
|
||||
|
||||
/**
|
||||
* Parses RFC 4180 CSV text into an array of objects keyed by header.
|
||||
@@ -254,7 +257,6 @@ export async function executeCompanyImport({
|
||||
// Fallback: Haupt category ID for unmapped items
|
||||
const hauptDashId = jtlCatIdToDashCatId.get('1') || rootCategoryId;
|
||||
|
||||
// ─── Phase 2: Article Import Pass 1 (Create or Update) ───────────────────
|
||||
const includedArticles = artRecords.filter((a) => {
|
||||
let cats = [];
|
||||
try {
|
||||
@@ -268,8 +270,63 @@ export async function executeCompanyImport({
|
||||
return true;
|
||||
});
|
||||
|
||||
// ─── Phase 2: Brand (Hersteller) Import ──────────────────────────────────
|
||||
const brandMap = new Map(); // brandName -> Set of picture relative paths
|
||||
for (const a of includedArticles) {
|
||||
const hersteller = String(a.Hersteller || '').trim();
|
||||
if (!hersteller) continue;
|
||||
if (!brandMap.has(hersteller)) {
|
||||
brandMap.set(hersteller, new Set());
|
||||
}
|
||||
const rawPics = String(a.manufacturerPictureFiles || '').trim();
|
||||
if (rawPics) {
|
||||
for (const p of rawPics.split(/[;,]/).map((s) => s.trim()).filter(Boolean)) {
|
||||
brandMap.get(hersteller).add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const brandNameToId = new Map();
|
||||
let createdBrandCount = 0;
|
||||
let brandPicCount = 0;
|
||||
const brandEntries = Array.from(brandMap.entries());
|
||||
log.info(`Processing ${brandEntries.length} brands (Hersteller)...`);
|
||||
|
||||
for (let i = 0; i < brandEntries.length; i++) {
|
||||
const [brandName, picSet] = brandEntries[i];
|
||||
try {
|
||||
const brand = await store.brand.upsert(googleAuthId, { name: brandName });
|
||||
brandNameToId.set(brandName.toLowerCase(), brand.id);
|
||||
createdBrandCount++;
|
||||
|
||||
// If brand doesn't have an image yet, import from manufacturerPictureFiles
|
||||
if ((!brand.pics || brand.pics.length === 0) && picSet.size > 0) {
|
||||
for (const picRel of picSet) {
|
||||
const picPath = path.resolve(importDir, picRel);
|
||||
if (fs.existsSync(picPath)) {
|
||||
try {
|
||||
const imgBuf = fs.readFileSync(picPath);
|
||||
await store.brand.addImage(googleAuthId, brand.id, imgBuf);
|
||||
brandPicCount++;
|
||||
break; // 1 primary logo per brand
|
||||
} catch (err) {
|
||||
log.warn(`Brand image error for "${brandName}" (${picRel}):`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn(`Failed to upsert brand "${brandName}":`, err.message);
|
||||
}
|
||||
|
||||
onProgress('brands', i + 1, brandEntries.length, brandName);
|
||||
}
|
||||
|
||||
log.info(`Brands resolved: ${brandNameToId.size}/${brandEntries.length}, brand images: ${brandPicCount}`);
|
||||
|
||||
// ─── Phase 3: Article Import Pass 1 (Create or Update) ───────────────────
|
||||
const totalArticles = includedArticles.length;
|
||||
console.log(`[Import] Articles to process: ${totalArticles}`);
|
||||
log.info(`Articles to process: ${totalArticles}`);
|
||||
onProgress('articles', 0, totalArticles, 'Starting articles import');
|
||||
|
||||
let articlesImported = 0;
|
||||
@@ -355,6 +412,17 @@ export async function executeCompanyImport({
|
||||
}
|
||||
}
|
||||
|
||||
// Update brand if provided
|
||||
const hersteller = String(a.Hersteller || '').trim();
|
||||
const brandId = hersteller ? (brandNameToId.get(hersteller.toLowerCase()) || null) : null;
|
||||
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 {
|
||||
// Create new article
|
||||
@@ -385,6 +453,17 @@ export async function executeCompanyImport({
|
||||
}
|
||||
}
|
||||
|
||||
// Set brand if provided
|
||||
const hersteller = String(a.Hersteller || '').trim();
|
||||
const brandId = hersteller ? (brandNameToId.get(hersteller.toLowerCase()) || null) : null;
|
||||
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) {
|
||||
@@ -470,6 +549,9 @@ export async function executeCompanyImport({
|
||||
categories: jtlCatIdToDashCatId.size,
|
||||
categoriesCreated: createdCatCount,
|
||||
categoryPictures: catPicCount,
|
||||
brands: brandNameToId.size,
|
||||
brandsCreated: createdBrandCount,
|
||||
brandPictures: brandPicCount,
|
||||
articlesTotal: totalArticles,
|
||||
articlesImported,
|
||||
articlesUpdated,
|
||||
|
||||
Reference in New Issue
Block a user