feat(sms): send class start date, days, and course time
Expose schedule fields on class and invoice templates so SMS can include Jalali start date, weekdays, and hour range.
This commit is contained in:
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
const Class = require('./classModel');
|
const Class = require('./classModel');
|
||||||
const User = require('../users/userModel');
|
const User = require('../users/userModel');
|
||||||
|
const Session = require('../sessions/sessionModel');
|
||||||
const AppError = require('../../utils/AppError');
|
const AppError = require('../../utils/AppError');
|
||||||
const { calculateMeta, escapeRegex, getSearchTerm } = require('../../utils/pagination');
|
const { calculateMeta, escapeRegex, getSearchTerm } = require('../../utils/pagination');
|
||||||
const { sendClassRegisteredSms } = require('../../utils/senders/smsMessages');
|
const { sendClassRegisteredSms } = require('../../utils/senders/smsMessages');
|
||||||
|
const { buildClassScheduleContext } = require('../../utils/classSchedule');
|
||||||
const logger = require('../../utils/logger');
|
const logger = require('../../utils/logger');
|
||||||
|
|
||||||
const getAll = async (query) => {
|
const getAll = async (query) => {
|
||||||
@@ -77,12 +79,20 @@ const registerUsers = async (classId, userIds) => {
|
|||||||
await cls.save();
|
await cls.save();
|
||||||
|
|
||||||
const classLabel = cls.name || cls.course?.title || 'کلاس';
|
const classLabel = cls.name || cls.course?.title || 'کلاس';
|
||||||
|
const sessions = await Session.find({ class: classId })
|
||||||
|
.select('day startTime endTime')
|
||||||
|
.sort({ day: 1 })
|
||||||
|
.lean();
|
||||||
|
const schedule = buildClassScheduleContext(cls, sessions);
|
||||||
const users = await User.find({ _id: { $in: toAdd } }).select('phoneNumber').lean();
|
const users = await User.find({ _id: { $in: toAdd } }).select('phoneNumber').lean();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
users.map(async (user) => {
|
users.map(async (user) => {
|
||||||
if (!user.phoneNumber) return;
|
if (!user.phoneNumber) return;
|
||||||
try {
|
try {
|
||||||
await sendClassRegisteredSms(user.phoneNumber, classLabel, user._id);
|
await sendClassRegisteredSms(user.phoneNumber, classLabel, user._id, {
|
||||||
|
courseName: cls.course?.title || classLabel,
|
||||||
|
...schedule
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[registerUsers] SMS failed for ${user.phoneNumber}: ${err.message}`);
|
logger.error(`[registerUsers] SMS failed for ${user.phoneNumber}: ${err.message}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ const { calculateMeta, escapeRegex, getSearchTerm } = require('../../utils/pagin
|
|||||||
const User = require('../users/userModel');
|
const User = require('../users/userModel');
|
||||||
const Course = require('../courses/courseModel');
|
const Course = require('../courses/courseModel');
|
||||||
const Class = require('../classes/classModel');
|
const Class = require('../classes/classModel');
|
||||||
|
const Session = require('../sessions/sessionModel');
|
||||||
const { sendInvoiceCreatedSms } = require('../../utils/senders/smsMessages');
|
const { sendInvoiceCreatedSms } = require('../../utils/senders/smsMessages');
|
||||||
|
const { buildClassScheduleContext } = require('../../utils/classSchedule');
|
||||||
const logger = require('../../utils/logger');
|
const logger = require('../../utils/logger');
|
||||||
|
|
||||||
const getAllPayments = async (query) => {
|
const getAllPayments = async (query) => {
|
||||||
@@ -79,22 +81,34 @@ const createPayment = async (body, actorId = null) => {
|
|||||||
const user = await User.findById(payment.user).select('name phoneNumber').lean();
|
const user = await User.findById(payment.user).select('name phoneNumber').lean();
|
||||||
if (user?.phoneNumber) {
|
if (user?.phoneNumber) {
|
||||||
let courseName = '';
|
let courseName = '';
|
||||||
|
let schedule = { classStartDate: '', classDays: '', courseTime: '' };
|
||||||
if (payment.course) {
|
if (payment.course) {
|
||||||
const course = await Course.findById(payment.course).select('title').lean();
|
const course = await Course.findById(payment.course).select('title').lean();
|
||||||
if (course?.title) courseName = course.title;
|
if (course?.title) courseName = course.title;
|
||||||
} else if (payment.classes && payment.classes.length > 0) {
|
}
|
||||||
|
if (payment.classes && payment.classes.length > 0) {
|
||||||
const cls = await Class.findById(payment.classes[0]).populate('course', 'title').lean();
|
const cls = await Class.findById(payment.classes[0]).populate('course', 'title').lean();
|
||||||
|
if (!courseName) {
|
||||||
if (cls?.course?.title) {
|
if (cls?.course?.title) {
|
||||||
courseName = cls.course.title;
|
courseName = cls.course.title;
|
||||||
} else if (cls?.name) {
|
} else if (cls?.name) {
|
||||||
courseName = cls.name;
|
courseName = cls.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cls) {
|
||||||
|
const sessions = await Session.find({ class: cls._id })
|
||||||
|
.select('day startTime endTime')
|
||||||
|
.sort({ day: 1 })
|
||||||
|
.lean();
|
||||||
|
schedule = buildClassScheduleContext(cls, sessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await sendInvoiceCreatedSms(user.phoneNumber, {
|
await sendInvoiceCreatedSms(user.phoneNumber, {
|
||||||
fullName: user.name || '',
|
fullName: user.name || '',
|
||||||
amount: payment.amount,
|
amount: payment.amount,
|
||||||
course: courseName || '-'
|
course: courseName || '-',
|
||||||
|
...schedule
|
||||||
}, user._id);
|
}, user._id);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ const SMS_TEMPLATE_DEFS = [
|
|||||||
{ key: 'className', label: 'نام کلاس', defaultName: 'className' },
|
{ key: 'className', label: 'نام کلاس', defaultName: 'className' },
|
||||||
{ key: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
|
{ key: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
|
||||||
{ key: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
|
{ key: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
|
||||||
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
|
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
|
||||||
|
{ key: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
|
||||||
|
{ key: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
|
||||||
|
{ key: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -33,7 +36,10 @@ const SMS_TEMPLATE_DEFS = [
|
|||||||
{ key: 'time', label: 'ساعت', defaultName: 'time' },
|
{ key: 'time', label: 'ساعت', defaultName: 'time' },
|
||||||
{ key: 'place', label: 'مکان', defaultName: 'place' },
|
{ key: 'place', label: 'مکان', defaultName: 'place' },
|
||||||
{ key: 'fullName', label: 'نام کاربر', defaultName: 'fullName' },
|
{ key: 'fullName', label: 'نام کاربر', defaultName: 'fullName' },
|
||||||
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
|
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
|
||||||
|
{ key: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
|
||||||
|
{ key: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
|
||||||
|
{ key: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -44,7 +50,10 @@ const SMS_TEMPLATE_DEFS = [
|
|||||||
{ key: 'fullName', label: 'نام کارآموز', defaultName: 'FULLNAME' },
|
{ key: 'fullName', label: 'نام کارآموز', defaultName: 'FULLNAME' },
|
||||||
{ key: 'amount', label: 'مبلغ', defaultName: 'PAYMENT_PRICE' },
|
{ key: 'amount', label: 'مبلغ', defaultName: 'PAYMENT_PRICE' },
|
||||||
{ key: 'course', label: 'نام دوره', defaultName: 'COURSE' },
|
{ key: 'course', label: 'نام دوره', defaultName: 'COURSE' },
|
||||||
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'MOBILE' }
|
{ key: 'phoneNumber', label: 'شماره همراه', defaultName: 'MOBILE' },
|
||||||
|
{ key: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
|
||||||
|
{ key: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
|
||||||
|
{ key: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -58,4 +58,15 @@ describe('SMS template variables', () => {
|
|||||||
assert.deepEqual(merged.variables.map((item) => item.slot), ['amount', 'fullName', 'course']);
|
assert.deepEqual(merged.variables.map((item) => item.slot), ['amount', 'fullName', 'course']);
|
||||||
assert.deepEqual(merged.variables.map((item) => item.name), ['PAYMENT_PRICE', 'FULLNAME', 'COURSE']);
|
assert.deepEqual(merged.variables.map((item) => item.name), ['PAYMENT_PRICE', 'FULLNAME', 'COURSE']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('exposes class start date, class days, and course time slots', () => {
|
||||||
|
const expected = ['classStartDate', 'classDays', 'courseTime'];
|
||||||
|
for (const key of ['classRegistered', 'classReminder', 'invoiceCreated']) {
|
||||||
|
const def = SMS_TEMPLATE_DEFS.find((item) => item.key === key);
|
||||||
|
const slots = (def?.slots || []).map((slot) => slot.key);
|
||||||
|
for (const slot of expected) {
|
||||||
|
assert.ok(slots.includes(slot), `${key} is missing slot ${slot}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const cron = require('node-cron');
|
|||||||
const Session = require('../components/sessions/sessionModel');
|
const Session = require('../components/sessions/sessionModel');
|
||||||
const User = require('../components/users/userModel');
|
const User = require('../components/users/userModel');
|
||||||
const { sendClassReminderSms } = require('../utils/senders/smsMessages');
|
const { sendClassReminderSms } = require('../utils/senders/smsMessages');
|
||||||
|
const { buildClassScheduleContext } = require('../utils/classSchedule');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
const parseStartDateTime = (session) => {
|
const parseStartDateTime = (session) => {
|
||||||
@@ -36,7 +37,7 @@ const runClassReminderJob = async () => {
|
|||||||
reminderSentAt: null,
|
reminderSentAt: null,
|
||||||
day: { $gte: dayFrom, $lte: dayTo },
|
day: { $gte: dayFrom, $lte: dayTo },
|
||||||
})
|
})
|
||||||
.populate({ path: 'class', select: 'name students' })
|
.populate({ path: 'class', select: 'name students startDate' })
|
||||||
.populate({ path: 'course', select: 'title' })
|
.populate({ path: 'course', select: 'title' })
|
||||||
.lean();
|
.lean();
|
||||||
|
|
||||||
@@ -54,6 +55,10 @@ const runClassReminderJob = async () => {
|
|||||||
const classLabel = classDoc?.name || session.course?.title || 'کلاس';
|
const classLabel = classDoc?.name || session.course?.title || 'کلاس';
|
||||||
const timeLabel = session.startTime;
|
const timeLabel = session.startTime;
|
||||||
const placeLabel = session.place || '-';
|
const placeLabel = session.place || '-';
|
||||||
|
const classSessions = classDoc?._id
|
||||||
|
? await Session.find({ class: classDoc._id }).select('day startTime endTime').sort({ day: 1 }).lean()
|
||||||
|
: [];
|
||||||
|
const schedule = buildClassScheduleContext(classDoc, classSessions, session);
|
||||||
|
|
||||||
const users = await User.find({ _id: { $in: studentIds } }).select('phoneNumber').lean();
|
const users = await User.find({ _id: { $in: studentIds } }).select('phoneNumber').lean();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
@@ -65,7 +70,11 @@ const runClassReminderJob = async () => {
|
|||||||
classLabel,
|
classLabel,
|
||||||
timeLabel,
|
timeLabel,
|
||||||
placeLabel,
|
placeLabel,
|
||||||
user._id
|
user._id,
|
||||||
|
{
|
||||||
|
courseName: session.course?.title || classLabel,
|
||||||
|
...schedule
|
||||||
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[ClassReminderJob] SMS failed for ${user.phoneNumber}: ${err.message}`);
|
logger.error(`[ClassReminderJob] SMS failed for ${user.phoneNumber}: ${err.message}`);
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
"dev": "nodemon app.js",
|
"dev": "nodemon app.js",
|
||||||
"seed": "node seed.js",
|
"seed": "node seed.js",
|
||||||
"test": "node --test components/settings/smsTemplates.test.js"
|
"test": "node --test components/settings/smsTemplates.test.js utils/classSchedule.test.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"express",
|
"express",
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const PERSIAN_WEEKDAYS = ['یکشنبه', 'دوشنبه', 'سهشنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'];
|
||||||
|
const IRAN_WEEK_ORDER = [6, 0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
const toDate = (value) => {
|
||||||
|
if (!value) return null;
|
||||||
|
const date = value instanceof Date ? value : new Date(value);
|
||||||
|
return Number.isNaN(date.getTime()) ? null : date;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatClockPart = (time) => {
|
||||||
|
const raw = String(time || '').trim();
|
||||||
|
if (!raw) return '';
|
||||||
|
const [hoursRaw, minutesRaw] = raw.split(':');
|
||||||
|
const hours = String(parseInt(hoursRaw, 10));
|
||||||
|
if (hours === 'NaN') return '';
|
||||||
|
if (!minutesRaw || minutesRaw === '00') return hours;
|
||||||
|
return `${hours}:${minutesRaw}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatCourseTime = (startTime, endTime) => {
|
||||||
|
const start = formatClockPart(startTime);
|
||||||
|
const end = formatClockPart(endTime);
|
||||||
|
if (!start) return '';
|
||||||
|
if (!end) return start;
|
||||||
|
return `از ${start} تا ${end}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const weekdayIndex = (value) => {
|
||||||
|
const date = toDate(value);
|
||||||
|
return date ? date.getDay() : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const joinFaList = (items) => {
|
||||||
|
if (!items.length) return '';
|
||||||
|
if (items.length === 1) return items[0];
|
||||||
|
if (items.length === 2) return `${items[0]} و ${items[1]}`;
|
||||||
|
return `${items.slice(0, -1).join('، ')} و ${items[items.length - 1]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatClassDays = (sessions = []) => {
|
||||||
|
const indexes = [];
|
||||||
|
const seen = new Set();
|
||||||
|
for (const session of sessions) {
|
||||||
|
const dayIndex = weekdayIndex(session?.day);
|
||||||
|
if (dayIndex == null || seen.has(dayIndex)) continue;
|
||||||
|
seen.add(dayIndex);
|
||||||
|
indexes.push(dayIndex);
|
||||||
|
}
|
||||||
|
indexes.sort((a, b) => IRAN_WEEK_ORDER.indexOf(a) - IRAN_WEEK_ORDER.indexOf(b));
|
||||||
|
return joinFaList(indexes.map((index) => PERSIAN_WEEKDAYS[index]).filter(Boolean));
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatClassStartDate = (value) => {
|
||||||
|
const date = toDate(value);
|
||||||
|
if (!date) return '';
|
||||||
|
try {
|
||||||
|
return date.toLocaleDateString('fa-IR');
|
||||||
|
} catch {
|
||||||
|
return date.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildClassScheduleContext = (classDoc, sessions = [], currentSession = null) => {
|
||||||
|
const sortedSessions = [...sessions].sort((a, b) => {
|
||||||
|
const left = toDate(a?.day)?.getTime() || 0;
|
||||||
|
const right = toDate(b?.day)?.getTime() || 0;
|
||||||
|
return left - right;
|
||||||
|
});
|
||||||
|
const sessionForTime = currentSession || sortedSessions[0] || null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
classStartDate: formatClassStartDate(classDoc?.startDate || sortedSessions[0]?.day),
|
||||||
|
classDays: formatClassDays(sortedSessions),
|
||||||
|
courseTime: formatCourseTime(sessionForTime?.startTime, sessionForTime?.endTime)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
formatCourseTime,
|
||||||
|
formatClassDays,
|
||||||
|
formatClassStartDate,
|
||||||
|
buildClassScheduleContext
|
||||||
|
};
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { describe, it } = require('node:test');
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const {
|
||||||
|
formatCourseTime,
|
||||||
|
formatClassDays,
|
||||||
|
formatClassStartDate,
|
||||||
|
buildClassScheduleContext
|
||||||
|
} = require('./classSchedule');
|
||||||
|
|
||||||
|
describe('class schedule SMS helpers', () => {
|
||||||
|
it('formats course time as an hour range', () => {
|
||||||
|
assert.equal(formatCourseTime('19:00', '21:00'), 'از 19 تا 21');
|
||||||
|
assert.equal(formatCourseTime('19:30', '21:00'), 'از 19:30 تا 21');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('joins class weekdays in Persian week order', () => {
|
||||||
|
const atNoon = (year, month, day) => new Date(year, month - 1, day, 12, 0, 0);
|
||||||
|
const monday = atNoon(2026, 8, 17);
|
||||||
|
const saturday = atNoon(2026, 8, 15);
|
||||||
|
const wednesday = atNoon(2026, 8, 19);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
formatClassDays([
|
||||||
|
{ day: monday },
|
||||||
|
{ day: saturday },
|
||||||
|
{ day: wednesday },
|
||||||
|
{ day: saturday }
|
||||||
|
]),
|
||||||
|
'شنبه، دوشنبه و چهارشنبه'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('builds start date, days, and course time from class and sessions', () => {
|
||||||
|
const atNoon = (year, month, day) => new Date(year, month - 1, day, 12, 0, 0);
|
||||||
|
const context = buildClassScheduleContext(
|
||||||
|
{ startDate: atNoon(2026, 8, 15) },
|
||||||
|
[
|
||||||
|
{ day: atNoon(2026, 8, 15), startTime: '19:00', endTime: '21:00' },
|
||||||
|
{ day: atNoon(2026, 8, 17), startTime: '19:00', endTime: '21:00' }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(context.classStartDate);
|
||||||
|
assert.equal(context.classDays, 'شنبه و دوشنبه');
|
||||||
|
assert.equal(context.courseTime, 'از 19 تا 21');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses the current session for course time when provided', () => {
|
||||||
|
const context = buildClassScheduleContext(
|
||||||
|
{ startDate: new Date('2026-08-15T00:00:00Z') },
|
||||||
|
[{ day: new Date('2026-08-15T00:00:00Z'), startTime: '19:00', endTime: '21:00' }],
|
||||||
|
{ startTime: '10:00', endTime: '12:00' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(context.courseTime, 'از 10 تا 12');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -58,6 +58,9 @@ const sendClassRegisteredSms = async (receiver, className, userId = null, extraC
|
|||||||
fullName: fullName || 'کارآموز',
|
fullName: fullName || 'کارآموز',
|
||||||
phoneNumber: receiver,
|
phoneNumber: receiver,
|
||||||
mobile: receiver,
|
mobile: receiver,
|
||||||
|
classStartDate: extraContext.classStartDate || '',
|
||||||
|
classDays: extraContext.classDays || '',
|
||||||
|
courseTime: extraContext.courseTime || '',
|
||||||
...extraContext
|
...extraContext
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
@@ -85,6 +88,9 @@ const sendClassReminderSms = async (receiver, className, time, place = '', userI
|
|||||||
fullName: fullName || 'کارآموز',
|
fullName: fullName || 'کارآموز',
|
||||||
phoneNumber: receiver,
|
phoneNumber: receiver,
|
||||||
mobile: receiver,
|
mobile: receiver,
|
||||||
|
classStartDate: extraContext.classStartDate || '',
|
||||||
|
classDays: extraContext.classDays || '',
|
||||||
|
courseTime: extraContext.courseTime || extraContext.time || time || '',
|
||||||
...extraContext
|
...extraContext
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
@@ -97,11 +103,17 @@ const sendInvoiceCreatedSms = async (receiver, payload, userId = null) => {
|
|||||||
let fullName = '';
|
let fullName = '';
|
||||||
let amount = '';
|
let amount = '';
|
||||||
let course = '';
|
let course = '';
|
||||||
|
let classStartDate = '';
|
||||||
|
let classDays = '';
|
||||||
|
let courseTime = '';
|
||||||
|
|
||||||
if (typeof payload === 'object' && payload !== null) {
|
if (typeof payload === 'object' && payload !== null) {
|
||||||
fullName = payload.fullName || '';
|
fullName = payload.fullName || '';
|
||||||
amount = payload.amount != null ? String(payload.amount) : '';
|
amount = payload.amount != null ? String(payload.amount) : '';
|
||||||
course = payload.course || '';
|
course = payload.course || '';
|
||||||
|
classStartDate = payload.classStartDate || '';
|
||||||
|
classDays = payload.classDays || '';
|
||||||
|
courseTime = payload.courseTime || '';
|
||||||
} else {
|
} else {
|
||||||
amount = String(payload || '');
|
amount = String(payload || '');
|
||||||
}
|
}
|
||||||
@@ -121,7 +133,10 @@ const sendInvoiceCreatedSms = async (receiver, payload, userId = null) => {
|
|||||||
amount: amountLabel,
|
amount: amountLabel,
|
||||||
course: courseLabel,
|
course: courseLabel,
|
||||||
phoneNumber: receiver,
|
phoneNumber: receiver,
|
||||||
mobile: receiver
|
mobile: receiver,
|
||||||
|
classStartDate,
|
||||||
|
classDays,
|
||||||
|
courseTime
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user