chore: Commit current state before refactoring
Includes deleted sql/ files, seeds, and documentation files. Prepares master for refactoring branch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,303 +0,0 @@
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
import { eq, sql } from 'drizzle-orm';
|
||||
|
||||
const { db } = await import('../../config/database.js');
|
||||
const { kurzy, ucastnici, registracie } = await import('../schema.js');
|
||||
|
||||
// Clear existing data
|
||||
async function clearData() {
|
||||
console.log('Clearing existing data...');
|
||||
await db.delete(registracie);
|
||||
await db.delete(ucastnici);
|
||||
await db.delete(kurzy);
|
||||
// Reset sequences
|
||||
await db.execute(sql`ALTER SEQUENCE kurzy_id_seq RESTART WITH 1`);
|
||||
await db.execute(sql`ALTER SEQUENCE ucastnici_id_seq RESTART WITH 1`);
|
||||
await db.execute(sql`ALTER SEQUENCE registracie_id_seq RESTART WITH 1`);
|
||||
console.log('Data cleared.');
|
||||
}
|
||||
|
||||
// Course data - now without dates (dates are per-registration)
|
||||
const coursesData = [
|
||||
{
|
||||
nazov: 'AI 1+2 (2 dni) - 290€',
|
||||
typKurzu: 'AI',
|
||||
cena: '290',
|
||||
},
|
||||
{
|
||||
nazov: 'AI 1 (1 deň) - 150€',
|
||||
typKurzu: 'AI',
|
||||
cena: '150',
|
||||
},
|
||||
{
|
||||
nazov: 'AI 2 (1 deň) - 150€',
|
||||
typKurzu: 'AI',
|
||||
cena: '150',
|
||||
},
|
||||
{
|
||||
nazov: 'AI v SEO (1 deň) - 150€',
|
||||
typKurzu: 'SEO',
|
||||
cena: '150',
|
||||
},
|
||||
{
|
||||
nazov: 'AI I+II Marec 2026',
|
||||
typKurzu: 'AI',
|
||||
cena: '290',
|
||||
},
|
||||
{
|
||||
nazov: 'AI I+II Apríl 2026',
|
||||
typKurzu: 'AI',
|
||||
cena: '290',
|
||||
},
|
||||
];
|
||||
|
||||
// Participants data from CSV - dates are now on registration level
|
||||
const participantsData = [
|
||||
// Umelá Inteligencia I+II 2. - 3. Február 2026
|
||||
{
|
||||
meno: 'Martin',
|
||||
priezvisko: 'Sovák',
|
||||
telefon: '0918986172',
|
||||
email: 'info@energium.sk',
|
||||
firma: 'energium sro',
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI 1+2 (2 dni) - 290€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Bratislava',
|
||||
ulica: 'Topolcianska 5',
|
||||
psc: '85105',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: false,
|
||||
poznamka: 'FA 2026020',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Michal',
|
||||
priezvisko: 'Farkaš',
|
||||
telefon: '0911209122',
|
||||
email: 'michal.farkas83@gmail.com',
|
||||
firma: 'SLOVWELD',
|
||||
formaKurzu: 'online',
|
||||
kurz: 'AI 1 (1 deň) - 150€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-02'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Dunajska Lužná',
|
||||
ulica: 'Mandlova 30',
|
||||
psc: '90042',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: true,
|
||||
poznamka: 'Fa 2025 338, Súhlasil so zmeneným termínom',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Alena',
|
||||
priezvisko: 'Šranková',
|
||||
telefon: '0917352580',
|
||||
email: 'alena.srankova@gmail.com',
|
||||
formaKurzu: 'online',
|
||||
kurz: 'AI 1+2 (2 dni) - 290€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Bratislava',
|
||||
ulica: 'Šándorova 1',
|
||||
psc: '82103',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: true,
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Katarina',
|
||||
priezvisko: 'Tomaníková',
|
||||
telefon: '0948 070 611',
|
||||
email: 'k.tomanikova@riseday.net',
|
||||
firma: 'Classica Shipping Limited',
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI 1+2 (2 dni) - 290€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Bratislava',
|
||||
ulica: 'Keltska 104',
|
||||
psc: '85110',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: true,
|
||||
poznamka: 'presunuta z oktobra, chce až január',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Róbert',
|
||||
priezvisko: 'Brišák',
|
||||
telefon: '0910583883',
|
||||
email: 'robert.brisak@ss-nizna.sk',
|
||||
firma: 'Spojená škola, Hattalova 471, 02743 Nižná',
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI 1+2 (2 dni) - 290€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Nižná',
|
||||
ulica: 'Hattalova 471',
|
||||
psc: '02743',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: false,
|
||||
poznamka: 'FA 2026019',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Marián',
|
||||
priezvisko: 'Bača',
|
||||
telefon: '0907994126',
|
||||
email: 'baca.marian@gmail.com',
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI 2 (1 deň) - 150€',
|
||||
datumOd: new Date('2026-02-03'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Petrovany',
|
||||
ulica: '8',
|
||||
psc: '08253',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: false,
|
||||
poznamka: 'Fa Gablasova',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
titul: 'Mgr. MBA',
|
||||
meno: 'Nikola',
|
||||
priezvisko: 'Horáčková',
|
||||
telefon: '0918482184',
|
||||
email: 'nikolahorackova11@gmail.com',
|
||||
kurz: 'AI 1+2 (2 dni) - 290€',
|
||||
datumOd: new Date('2026-02-02'),
|
||||
datumDo: new Date('2026-02-03'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Zákopčie',
|
||||
ulica: 'Zákopčie stred 12',
|
||||
psc: '023 11',
|
||||
fakturaVystavena: false,
|
||||
zaplatene: false,
|
||||
poznamka: 'vzdelávací poukaz',
|
||||
stav: 'potencialny',
|
||||
},
|
||||
// AI v SEO 13.2.2026
|
||||
{
|
||||
meno: 'Tomáš',
|
||||
priezvisko: 'Kupec',
|
||||
telefon: '0911030190',
|
||||
email: 'kupec.tom@gmail.com',
|
||||
firma: 'Jamajka',
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI v SEO (1 deň) - 150€',
|
||||
datumOd: new Date('2026-02-13'),
|
||||
datumDo: new Date('2026-02-13'),
|
||||
pocetUcastnikov: 1,
|
||||
mesto: 'Liptovská Sielnica',
|
||||
psc: '032 23',
|
||||
fakturaVystavena: true,
|
||||
zaplatene: false,
|
||||
poznamka: 'FA 2026021',
|
||||
stav: 'registrovany',
|
||||
},
|
||||
{
|
||||
meno: 'Anton',
|
||||
priezvisko: 'Považský',
|
||||
email: 'anton.povazsky@example.com', // No email in CSV, using placeholder
|
||||
formaKurzu: 'prezencne',
|
||||
kurz: 'AI v SEO (1 deň) - 150€',
|
||||
datumOd: new Date('2026-02-13'),
|
||||
datumDo: new Date('2026-02-13'),
|
||||
pocetUcastnikov: 1,
|
||||
fakturaVystavena: true,
|
||||
zaplatene: false,
|
||||
stav: 'registrovany',
|
||||
},
|
||||
];
|
||||
|
||||
async function importData() {
|
||||
console.log('Starting import...');
|
||||
|
||||
// Create courses (now without dates)
|
||||
console.log('\nCreating courses...');
|
||||
const createdKurzy = {};
|
||||
for (const course of coursesData) {
|
||||
const [created] = await db.insert(kurzy).values({
|
||||
nazov: course.nazov,
|
||||
typKurzu: course.typKurzu,
|
||||
cena: course.cena,
|
||||
aktivny: true,
|
||||
}).returning();
|
||||
createdKurzy[course.nazov] = created.id;
|
||||
console.log(` Created course: ${course.nazov} (ID: ${created.id})`);
|
||||
}
|
||||
|
||||
// Create participants and registrations (with dates)
|
||||
console.log('\nCreating participants and registrations...');
|
||||
for (const p of participantsData) {
|
||||
// Check if participant already exists by email
|
||||
let [existingUcastnik] = await db.select().from(ucastnici).where(eq(ucastnici.email, p.email)).limit(1);
|
||||
|
||||
let ucastnikId;
|
||||
if (existingUcastnik) {
|
||||
ucastnikId = existingUcastnik.id;
|
||||
console.log(` Using existing participant: ${p.email}`);
|
||||
} else {
|
||||
const [created] = await db.insert(ucastnici).values({
|
||||
titul: p.titul || null,
|
||||
meno: p.meno,
|
||||
priezvisko: p.priezvisko,
|
||||
email: p.email,
|
||||
telefon: p.telefon || null,
|
||||
firma: p.firma || null,
|
||||
mesto: p.mesto || null,
|
||||
ulica: p.ulica || null,
|
||||
psc: p.psc || null,
|
||||
}).returning();
|
||||
ucastnikId = created.id;
|
||||
console.log(` Created participant: ${p.meno} ${p.priezvisko} (${p.email})`);
|
||||
}
|
||||
|
||||
// Get kurz ID
|
||||
const kurzId = createdKurzy[p.kurz];
|
||||
if (!kurzId) {
|
||||
console.error(` ERROR: Course not found: ${p.kurz}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create registration with dates
|
||||
await db.insert(registracie).values({
|
||||
kurzId: kurzId,
|
||||
ucastnikId: ucastnikId,
|
||||
datumOd: p.datumOd || null,
|
||||
datumDo: p.datumDo || null,
|
||||
formaKurzu: p.formaKurzu || 'prezencne',
|
||||
pocetUcastnikov: p.pocetUcastnikov || 1,
|
||||
fakturaVystavena: p.fakturaVystavena || false,
|
||||
zaplatene: p.zaplatene || false,
|
||||
stav: p.stav || 'registrovany',
|
||||
poznamka: p.poznamka || null,
|
||||
});
|
||||
console.log(` Created registration for ${p.email} -> ${p.kurz} (${p.datumOd?.toLocaleDateString('sk-SK')} - ${p.datumDo?.toLocaleDateString('sk-SK')})`);
|
||||
}
|
||||
|
||||
console.log('\n=== Import completed ===');
|
||||
console.log(`Courses: ${coursesData.length}`);
|
||||
console.log(`Participants: ${participantsData.length}`);
|
||||
}
|
||||
|
||||
// Run
|
||||
clearData()
|
||||
.then(() => importData())
|
||||
.then(() => {
|
||||
console.log('Done!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Import failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,292 +0,0 @@
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
import ExcelJS from 'exceljs';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
import path from 'path';
|
||||
|
||||
// Dynamic imports to ensure env is loaded first
|
||||
const { db } = await import('../../config/database.js');
|
||||
const { kurzy, ucastnici, registracie } = await import('../schema.js');
|
||||
|
||||
const EXCEL_FILE = '/home/richardtekula/Downloads/Copy of AI školenie študenti.xlsx';
|
||||
|
||||
// Helper to parse dates from various formats
|
||||
const parseDate = (value) => {
|
||||
if (!value) return null;
|
||||
if (value instanceof Date) return value;
|
||||
if (typeof value === 'number') {
|
||||
// Excel serial date number
|
||||
const date = new Date((value - 25569) * 86400 * 1000);
|
||||
return date;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
const parsed = new Date(value);
|
||||
return isNaN(parsed.getTime()) ? null : parsed;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Helper to clean string values
|
||||
const cleanString = (value) => {
|
||||
if (value === null || value === undefined) return null;
|
||||
const str = String(value).trim();
|
||||
return str === '' ? null : str;
|
||||
};
|
||||
|
||||
// Helper to parse numeric value
|
||||
const parseNumber = (value) => {
|
||||
if (value === null || value === undefined) return null;
|
||||
const num = parseFloat(value);
|
||||
return isNaN(num) ? null : num;
|
||||
};
|
||||
|
||||
// Map stav from Excel to our enum values
|
||||
const mapStav = (value) => {
|
||||
if (!value) return 'registrovany';
|
||||
const v = String(value).toLowerCase().trim();
|
||||
if (v.includes('absolvoval')) return 'absolvoval';
|
||||
if (v.includes('potvrden')) return 'potvrdeny';
|
||||
if (v.includes('zrusen')) return 'zruseny';
|
||||
if (v.includes('potencial')) return 'potencialny';
|
||||
return 'registrovany';
|
||||
};
|
||||
|
||||
// Map forma kurzu
|
||||
const mapForma = (value) => {
|
||||
if (!value) return 'prezencne';
|
||||
const v = String(value).toLowerCase().trim();
|
||||
if (v.includes('online')) return 'online';
|
||||
if (v.includes('hybrid')) return 'hybridne';
|
||||
return 'prezencne';
|
||||
};
|
||||
|
||||
async function importAiKurzy() {
|
||||
console.log('Reading Excel file:', EXCEL_FILE);
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.readFile(EXCEL_FILE);
|
||||
|
||||
console.log('Sheets in workbook:', workbook.worksheets.map(ws => ws.name));
|
||||
|
||||
// Process each sheet
|
||||
for (const worksheet of workbook.worksheets) {
|
||||
console.log(`\n=== Processing sheet: ${worksheet.name} ===`);
|
||||
console.log(`Rows: ${worksheet.rowCount}, Columns: ${worksheet.columnCount}`);
|
||||
|
||||
// Get headers from first row
|
||||
const headerRow = worksheet.getRow(1);
|
||||
const headers = [];
|
||||
headerRow.eachCell((cell, colNum) => {
|
||||
headers[colNum] = cleanString(cell.value);
|
||||
});
|
||||
console.log('Headers:', headers.filter(Boolean));
|
||||
|
||||
// Collect data rows
|
||||
const dataRows = [];
|
||||
worksheet.eachRow((row, rowNum) => {
|
||||
if (rowNum === 1) return; // Skip header
|
||||
|
||||
const rowData = {};
|
||||
row.eachCell((cell, colNum) => {
|
||||
const header = headers[colNum];
|
||||
if (header) {
|
||||
rowData[header] = cell.value;
|
||||
}
|
||||
});
|
||||
|
||||
// Only add if row has some data
|
||||
if (Object.values(rowData).some(v => v !== null && v !== undefined && v !== '')) {
|
||||
dataRows.push(rowData);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Found ${dataRows.length} data rows`);
|
||||
|
||||
// Log first few rows to understand structure
|
||||
if (dataRows.length > 0) {
|
||||
console.log('Sample row:', JSON.stringify(dataRows[0], null, 2));
|
||||
}
|
||||
|
||||
// Try to import data based on headers
|
||||
await importSheetData(worksheet.name, headers, dataRows);
|
||||
}
|
||||
|
||||
console.log('\n=== Import completed ===');
|
||||
}
|
||||
|
||||
async function importSheetData(sheetName, headers, rows) {
|
||||
// Detect what kind of data this is based on headers
|
||||
const headerLower = headers.map(h => h?.toLowerCase() || '');
|
||||
|
||||
const hasKurzFields = headerLower.some(h => h.includes('kurz') || h.includes('datum') || h.includes('cena'));
|
||||
const hasUcastnikFields = headerLower.some(h => h.includes('meno') || h.includes('email') || h.includes('priezvisko'));
|
||||
|
||||
if (rows.length === 0) {
|
||||
console.log('No data to import');
|
||||
return;
|
||||
}
|
||||
|
||||
// Import participants and registrations
|
||||
if (hasUcastnikFields) {
|
||||
await importParticipantsAndRegistrations(sheetName, headers, rows);
|
||||
}
|
||||
}
|
||||
|
||||
async function importParticipantsAndRegistrations(sheetName, headers, rows) {
|
||||
console.log(`\nImporting participants from sheet: ${sheetName}`);
|
||||
|
||||
// First, ensure we have a course for this sheet
|
||||
const courseName = sheetName;
|
||||
let course = await db.select().from(kurzy).where(eq(kurzy.nazov, courseName)).limit(1);
|
||||
|
||||
if (course.length === 0) {
|
||||
// Create course from sheet name
|
||||
const [newCourse] = await db.insert(kurzy).values({
|
||||
nazov: courseName,
|
||||
typKurzu: extractCourseType(sheetName),
|
||||
cena: '0', // Will need to update manually
|
||||
datumOd: new Date(),
|
||||
datumDo: new Date(),
|
||||
aktivny: true,
|
||||
}).returning();
|
||||
course = [newCourse];
|
||||
console.log(`Created course: ${courseName} (ID: ${newCourse.id})`);
|
||||
} else {
|
||||
console.log(`Using existing course: ${courseName} (ID: ${course[0].id})`);
|
||||
}
|
||||
|
||||
const kurzId = course[0].id;
|
||||
|
||||
// Map headers to our fields
|
||||
const headerMap = {};
|
||||
headers.forEach((header, idx) => {
|
||||
if (!header) return;
|
||||
const h = header.toLowerCase();
|
||||
|
||||
if (h.includes('titul') || h === 'titul') headerMap.titul = idx;
|
||||
if (h.includes('meno') && !h.includes('priezvisko')) headerMap.meno = idx;
|
||||
if (h.includes('priezvisko') || h === 'surname' || h === 'priezvisko') headerMap.priezvisko = idx;
|
||||
if (h.includes('email') || h.includes('e-mail')) headerMap.email = idx;
|
||||
if (h.includes('telefon') || h.includes('phone') || h.includes('tel')) headerMap.telefon = idx;
|
||||
if (h.includes('firma') || h.includes('company') || h.includes('spolocnost')) headerMap.firma = idx;
|
||||
if (h.includes('mesto') || h.includes('city')) headerMap.mesto = idx;
|
||||
if (h.includes('ulica') || h.includes('street') || h.includes('adresa')) headerMap.ulica = idx;
|
||||
if (h.includes('psc') || h.includes('zip') || h.includes('postal')) headerMap.psc = idx;
|
||||
if (h.includes('stav') || h.includes('status')) headerMap.stav = idx;
|
||||
if (h.includes('forma') || h.includes('form')) headerMap.forma = idx;
|
||||
if (h.includes('faktur') && h.includes('cislo')) headerMap.fakturaCislo = idx;
|
||||
if (h.includes('faktur') && h.includes('vystaven')) headerMap.fakturaVystavena = idx;
|
||||
if (h.includes('zaplaten') || h.includes('paid')) headerMap.zaplatene = idx;
|
||||
if (h.includes('poznam') || h.includes('note')) headerMap.poznamka = idx;
|
||||
if (h.includes('pocet') || h.includes('count')) headerMap.pocetUcastnikov = idx;
|
||||
});
|
||||
|
||||
console.log('Field mapping:', headerMap);
|
||||
|
||||
let importedCount = 0;
|
||||
let skippedCount = 0;
|
||||
|
||||
for (const row of rows) {
|
||||
try {
|
||||
// Get email - required field
|
||||
const email = cleanString(row[headers[headerMap.email]] || Object.values(row).find(v => String(v).includes('@')));
|
||||
if (!email || !email.includes('@')) {
|
||||
skippedCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if participant exists
|
||||
let participant = await db.select().from(ucastnici).where(eq(ucastnici.email, email)).limit(1);
|
||||
|
||||
if (participant.length === 0) {
|
||||
// Try to find name fields
|
||||
let meno = cleanString(row[headers[headerMap.meno]]);
|
||||
let priezvisko = cleanString(row[headers[headerMap.priezvisko]]);
|
||||
|
||||
// If no separate fields, try to split full name
|
||||
if (!meno && !priezvisko) {
|
||||
// Look for a name-like field
|
||||
for (const [key, value] of Object.entries(row)) {
|
||||
const val = cleanString(value);
|
||||
if (val && !val.includes('@') && !val.includes('http') && val.length < 50) {
|
||||
const parts = val.split(/\s+/);
|
||||
if (parts.length >= 2) {
|
||||
meno = parts[0];
|
||||
priezvisko = parts.slice(1).join(' ');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create participant
|
||||
const [newParticipant] = await db.insert(ucastnici).values({
|
||||
titul: cleanString(row[headers[headerMap.titul]]),
|
||||
meno: meno || 'N/A',
|
||||
priezvisko: priezvisko || 'N/A',
|
||||
email: email,
|
||||
telefon: cleanString(row[headers[headerMap.telefon]]),
|
||||
firma: cleanString(row[headers[headerMap.firma]]),
|
||||
mesto: cleanString(row[headers[headerMap.mesto]]),
|
||||
ulica: cleanString(row[headers[headerMap.ulica]]),
|
||||
psc: cleanString(row[headers[headerMap.psc]]),
|
||||
}).returning();
|
||||
participant = [newParticipant];
|
||||
console.log(`Created participant: ${email}`);
|
||||
}
|
||||
|
||||
const ucastnikId = participant[0].id;
|
||||
|
||||
// Check if registration exists
|
||||
const existingReg = await db.select()
|
||||
.from(registracie)
|
||||
.where(and(eq(registracie.kurzId, kurzId), eq(registracie.ucastnikId, ucastnikId)))
|
||||
.limit(1);
|
||||
|
||||
if (existingReg.length === 0) {
|
||||
// Create registration
|
||||
await db.insert(registracie).values({
|
||||
kurzId: kurzId,
|
||||
ucastnikId: ucastnikId,
|
||||
formaKurzu: mapForma(row[headers[headerMap.forma]]),
|
||||
pocetUcastnikov: parseInt(row[headers[headerMap.pocetUcastnikov]]) || 1,
|
||||
fakturaCislo: cleanString(row[headers[headerMap.fakturaCislo]]),
|
||||
fakturaVystavena: Boolean(row[headers[headerMap.fakturaVystavena]]),
|
||||
zaplatene: Boolean(row[headers[headerMap.zaplatene]]),
|
||||
stav: mapStav(row[headers[headerMap.stav]]),
|
||||
poznamka: cleanString(row[headers[headerMap.poznamka]]),
|
||||
});
|
||||
importedCount++;
|
||||
} else {
|
||||
console.log(`Registration already exists for ${email} in ${sheetName}`);
|
||||
skippedCount++;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing row:`, error.message);
|
||||
skippedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Imported ${importedCount} registrations, skipped ${skippedCount}`);
|
||||
}
|
||||
|
||||
function extractCourseType(sheetName) {
|
||||
const name = sheetName.toLowerCase();
|
||||
if (name.includes('ai 1') || name.includes('ai1')) return 'AI 1';
|
||||
if (name.includes('ai 2') || name.includes('ai2')) return 'AI 2';
|
||||
if (name.includes('seo')) return 'SEO';
|
||||
if (name.includes('marketing')) return 'Marketing';
|
||||
return 'AI';
|
||||
}
|
||||
|
||||
// Run the import
|
||||
importAiKurzy()
|
||||
.then(() => {
|
||||
console.log('Import finished successfully');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Import failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user