91 lines
2.8 KiB
JavaScript
91 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const { toEnglishDigits } = require('../../utils/jalaliDate');
|
|
|
|
const TITLE_PREFIX = /^(آقای|اقای|خانم|آقا|سرکار\s+خانم|سرکار)\s+/;
|
|
const HONORIFIC_MIDDLE = /\s+خ\s+/g;
|
|
|
|
const normalizePersonName = (value) => {
|
|
const text = String(value ?? '')
|
|
.replace(/ي/g, 'ی')
|
|
.replace(/ك/g, 'ک')
|
|
.replace(/[\u200c\u200d]/g, ' ')
|
|
.replace(/\s+/g, ' ')
|
|
.trim()
|
|
.replace(TITLE_PREFIX, '')
|
|
.replace(HONORIFIC_MIDDLE, ' ')
|
|
.replace(/^خ\s+/, '')
|
|
.trim();
|
|
return text;
|
|
};
|
|
|
|
const namesMatch = (left, right) => {
|
|
const a = normalizePersonName(left);
|
|
const b = normalizePersonName(right);
|
|
return Boolean(a) && a === b;
|
|
};
|
|
|
|
const normalizePhone = (raw) => {
|
|
if (raw == null || 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 normalizeNationalId = (raw) => {
|
|
if (raw == null || 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 mapAttendanceStatus = (raw) => {
|
|
const value = String(raw ?? '').trim();
|
|
if (!value) return null;
|
|
if (value === '*' || value === 'ح' || value === 'حاضر' || /^present$/i.test(value) || /^p$/i.test(value)) {
|
|
return 'present';
|
|
}
|
|
if (value === 'غ' || value === 'غایب' || /^absent$/i.test(value) || /^a$/i.test(value)) {
|
|
return 'absent';
|
|
}
|
|
if (value === 'ت' || value === 'تأخیر' || value === 'تاخیر' || /^late$/i.test(value)) {
|
|
return 'late';
|
|
}
|
|
if (value === 'م' || value === 'موجه' || /^excused$/i.test(value)) {
|
|
return 'excused';
|
|
}
|
|
return null;
|
|
};
|
|
|
|
const projectSessionDates = (existingIsoDates, totalCount) => {
|
|
const dates = [...existingIsoDates].filter(Boolean).sort();
|
|
if (!dates.length || dates.length >= totalCount) return dates.slice(0, totalCount);
|
|
|
|
const weekdaySet = new Set(dates.map((iso) => new Date(`${iso}T12:00:00.000Z`).getUTCDay()));
|
|
const last = new Date(`${dates[dates.length - 1]}T12:00:00.000Z`);
|
|
const projected = [...dates];
|
|
const cursor = new Date(last);
|
|
|
|
while (projected.length < totalCount) {
|
|
cursor.setUTCDate(cursor.getUTCDate() + 1);
|
|
if (weekdaySet.has(cursor.getUTCDay())) {
|
|
projected.push(cursor.toISOString().slice(0, 10));
|
|
}
|
|
}
|
|
return projected;
|
|
};
|
|
|
|
module.exports = {
|
|
normalizePersonName,
|
|
namesMatch,
|
|
normalizePhone,
|
|
normalizeNationalId,
|
|
mapAttendanceStatus,
|
|
projectSessionDates
|
|
};
|