import fs from 'node:fs' import path from 'node:path' import { prisma } from '../src/lib/prisma' type CsvRow = { ID?: string DescriptionOfID?: string Vat?: string Type?: string } function parseCsvLine(line: string): string[] { const result: string[] = [] let current = '' let inQuotes = false for (let index = 0; index < line.length; index++) { const char = line[index] if (char === '"') { if (inQuotes && line[index + 1] === '"') { current += '"' index++ } else { inQuotes = !inQuotes } continue } if (char === ',' && !inQuotes) { result.push(current) current = '' continue } current += char } result.push(current) return result.map(value => value.trim()) } function parseCsv(content: string): CsvRow[] { const lines = content .split(/\r?\n/) .map(line => line.trim()) .filter(Boolean) if (!lines.length) return [] const headers = parseCsvLine(lines[0]) return lines.slice(1).map(line => { const cols = parseCsvLine(line) const row: Record = {} for (let index = 0; index < headers.length; index++) { row[headers[index]] = cols[index] || '' } return row }) } function toBooleanFlags(typeValue: string) { const normalized = typeValue || '' const isPublic = normalized.includes('شناسه عمومی') const isImported = normalized.includes('وارداتی') const isDomestic = !isImported return { isPublic, isDomestic } } function parseVat(vatValue: string) { const parsed = Number(vatValue || '0') if (!Number.isFinite(parsed)) return 0 return parsed } async function main() { const defaultPath = '/Users/ahasani/Desktop/product_good_2026-05-01T11-35-57_part_1_28812448-0dd9-411c-99e1-334c28d781fe.csv' const csvPath = process.argv[2] || defaultPath const absolutePath = path.resolve(csvPath) if (!fs.existsSync(absolutePath)) { throw new Error(`CSV file not found: ${absolutePath}`) } const raw = fs.readFileSync(absolutePath, 'utf8').replace(/^\uFEFF/, '') const rows = parseCsv(raw) let upserted = 0 let skipped = 0 const guild = await prisma.guild.findFirst({}) for (const row of rows) { const code = (row.ID || '').trim() const name = (row.DescriptionOfID || '').trim() const vat = parseVat((row.Vat || '').trim()) const type = (row.Type || '').trim() const { isPublic, isDomestic } = toBooleanFlags(type) if (!code || !name) { skipped++ continue } await prisma.stockKeepingUnits.upsert({ where: { code }, create: { code, name, VAT: vat, guild: { connect: { id: guild?.id, }, }, is_public: isPublic, is_domestic: isDomestic, }, update: { name, VAT: vat, guild: { connect: { id: guild?.id, }, }, is_public: isPublic, is_domestic: isDomestic, }, }) upserted++ } console.log( JSON.stringify( { csvPath: absolutePath, totalRows: rows.length, upserted, skipped, }, null, 2, ), ) } main() .catch(error => { console.error(error) process.exit(1) }) .finally(async () => { await prisma.$disconnect() })