148 lines
4.6 KiB
JavaScript
148 lines
4.6 KiB
JavaScript
// /scripts/convert-professors.js
|
||
'use strict';
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { execSync } = require('child_process');
|
||
|
||
const ODS_FILE = path.resolve(__dirname, '../../raw-data/Untitled spreadsheet.ods');
|
||
const OUTPUT_FILE = path.resolve(__dirname, '../../raw-data/professors-import.json');
|
||
|
||
const pythonExtractScript = `
|
||
import zipfile, xml.etree.ElementTree as ET, json, sys
|
||
|
||
ods_path = sys.argv[1]
|
||
with zipfile.ZipFile(ods_path) as z:
|
||
content = z.read('content.xml')
|
||
tree = ET.fromstring(content)
|
||
for table in tree.iter('{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table'):
|
||
rows = []
|
||
for row in table.iter('{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-row'):
|
||
row_vals = []
|
||
for cell in row.iter('{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-cell'):
|
||
texts = [t.text for t in cell.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p') if t.text]
|
||
repeat = int(cell.attrib.get('{urn:oasis:names:tc:opendocument:xmlns:table:1.0}number-columns-repeated', 1))
|
||
val = ' '.join(texts).strip() if texts else ''
|
||
if repeat > 1 and not val:
|
||
pass
|
||
else:
|
||
for _ in range(min(repeat, 20)):
|
||
row_vals.append(val)
|
||
if any(row_vals):
|
||
rows.append(row_vals)
|
||
print(json.dumps(rows, ensure_ascii=False))
|
||
break
|
||
`;
|
||
|
||
const extractOdsRows = (filePath) => {
|
||
const output = execSync(`python3 -c "${pythonExtractScript.replace(/"/g, '\\"')}" "${filePath}"`, {
|
||
encoding: 'utf-8',
|
||
maxBuffer: 10 * 1024 * 1024
|
||
});
|
||
return JSON.parse(output);
|
||
};
|
||
|
||
const toEnglishDigits = (str = '') =>
|
||
String(str)
|
||
.replace(/[۰-۹]/g, (d) => '0123456789'['۰۱۲۳۴۵۶۷۸۹'.indexOf(d)])
|
||
.replace(/[٠-٩]/g, (d) => '0123456789'['٠١٢٣٤٥٦٧٨٩'.indexOf(d)]);
|
||
|
||
const cleanPhone = (raw) => {
|
||
if (!raw) return '';
|
||
let digits = toEnglishDigits(raw).replace(/\D/g, '');
|
||
if (digits.startsWith('98') && digits.length >= 12) digits = `0${digits.slice(2)}`;
|
||
if (digits.length === 10 && digits.startsWith('9')) digits = `0${digits}`;
|
||
if (digits.length === 11 && digits.startsWith('9')) digits = `0${digits.slice(0, 10)}`;
|
||
if (digits.length > 11 && digits.startsWith('09')) digits = digits.slice(0, 11);
|
||
return digits;
|
||
};
|
||
|
||
const cleanNationalId = (raw) => {
|
||
if (!raw) return '';
|
||
let digits = toEnglishDigits(raw).replace(/\D/g, '');
|
||
if (digits && digits.length < 10 && /^\d+$/.test(digits)) {
|
||
digits = digits.padStart(10, '0');
|
||
}
|
||
return digits;
|
||
};
|
||
|
||
const cleanCard = (raw) => {
|
||
if (!raw) return '';
|
||
return toEnglishDigits(raw).replace(/\D/g, '');
|
||
};
|
||
|
||
const cleanShaba = (raw) => {
|
||
if (!raw) return '';
|
||
let val = toEnglishDigits(raw).replace(/[^0-9A-Za-z]/g, '');
|
||
return val;
|
||
};
|
||
|
||
const main = () => {
|
||
if (!fs.existsSync(ODS_FILE)) {
|
||
console.error(`ODS file not found: ${ODS_FILE}`);
|
||
process.exit(1);
|
||
}
|
||
|
||
const rows = extractOdsRows(ODS_FILE);
|
||
if (!rows || rows.length < 2) {
|
||
console.error('No rows found in ODS file');
|
||
process.exit(1);
|
||
}
|
||
|
||
const header = rows[0];
|
||
console.log('Detected headers:', header);
|
||
|
||
const professors = [];
|
||
|
||
for (let i = 1; i < rows.length; i += 1) {
|
||
const r = rows[i];
|
||
// 0: ردیف, 1: نام, 2: نام خانوادگی, 3: کد ملی, 4: شماره تماس, 5: درصد, 6: شماره کارت, 7: شمار شبا
|
||
const rawName = r[1] || '';
|
||
const rawSurname = r[2] || '';
|
||
const rawNid = r[3] || '';
|
||
const rawPhone = r[4] || '';
|
||
const rawCard = r[6] || '';
|
||
const rawShaba = r[7] || '';
|
||
|
||
// Strip honorifics like 'سرکار'
|
||
const name = rawName.replace(/^(آقای|اقای|خانم|آقا|سرکار\s+خانم|سرکار)\s+/, '').trim();
|
||
const surname = rawSurname.trim();
|
||
|
||
const nationalIdCode = cleanNationalId(rawNid);
|
||
const phoneNumber = cleanPhone(rawPhone);
|
||
const cardNumber = cleanCard(rawCard);
|
||
const shabaNumber = cleanShaba(rawShaba);
|
||
|
||
professors.push({
|
||
name,
|
||
surname,
|
||
nationalIdCode,
|
||
phoneNumber,
|
||
cardNumber,
|
||
shabaNumber
|
||
});
|
||
}
|
||
|
||
const payload = {
|
||
version: 1,
|
||
generatedAt: new Date().toISOString(),
|
||
source: 'Untitled spreadsheet.ods',
|
||
summary: {
|
||
professors: professors.length
|
||
},
|
||
professors
|
||
};
|
||
|
||
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(payload, null, 2), 'utf-8');
|
||
console.log(`Successfully wrote ${professors.length} professors to ${OUTPUT_FILE}`);
|
||
};
|
||
|
||
if (require.main === module) {
|
||
main();
|
||
}
|
||
|
||
module.exports = {
|
||
extractOdsRows,
|
||
main
|
||
};
|