Skip to content

Instantly share code, notes, and snippets.

@bogordesaincom
Created January 1, 2026 06:47
Show Gist options
  • Select an option

  • Save bogordesaincom/ff317120f193dc5b8629f6e8678a97b5 to your computer and use it in GitHub Desktop.

Select an option

Save bogordesaincom/ff317120f193dc5b8629f6e8678a97b5 to your computer and use it in GitHub Desktop.
G
import database from '../database';
import dayjs from 'dayjs';
import nanoTime from 'nano-time';
export const isWeekend = (date: string): boolean => {
const day = dayjs(date).day();
return day === 0 || day === 6;
};
const CheckSchedule = async () => {
const trx = await database.transaction();
try {
/* ===============================
* 1. COMPANY
* =============================== */
const findCompany = await trx.table('companies').where('code', 'CIMB').first();
if (!findCompany) {
throw new Error('Company not found');
}
/* ===============================
* 2. DATE RANGE
* =============================== */
const monthName = '01';
const yearName = 2026;
const startDate = dayjs(`${yearName}-${monthName}-01`);
const daysInMonth = startDate.daysInMonth();
const dates: string[] = Array.from({ length: daysInMonth }, (_, i) =>
startDate.add(i, 'day').format('YYYY-MM-DD')
);
/* ===============================
* 3. EXISTING TASK JANUARY (1 QUERY)
* =============================== */
const existingTasks = await trx
.table('tasks')
.whereBetween('schedule_date', ['2026-01-01', '2026-01-31'])
.select('machine_id');
const existingMachineSet = new Set(existingTasks.map((t: any) => t.machine_id));
/* ===============================
* 4. GROUPINGS
* =============================== */
const checkGroupings = await trx
.table('group_item')
.leftJoin('locations', 'locations.id', 'group_item.location_id')
.leftJoin('frequencies', 'frequencies.id', 'group_item.frequency_id')
.leftJoin('atm_machines', 'atm_machines.location_id', 'locations.id')
.leftJoin('regionals', 'atm_machines.regional_id', 'regionals.id')
.leftJoin('companies', 'atm_machines.company_id', 'companies.id')
.leftJoin('templates', 'templates.company_id', 'companies.id')
.leftJoin('users', 'group_item.staff_id', 'users.id')
.where('atm_machines.company_id', findCompany.id)
.where('frequencies.value', 30)
.select(
'group_item.*',
'atm_machines.id as machine_id',
'atm_machines.company_id',
'atm_machines.regional_id',
'atm_machines.branch_id',
'atm_machines.supervisor_id',
'templates.id as template_id',
'regionals.timezone',
'users.name as staff_name'
);
/* ===============================
* 5. TEMPLATE CHECKLIST
* =============================== */
const templateData = await trx
.table('templates')
.where('company_id', findCompany.id)
.first();
if (!templateData) {
throw new Error('Template not found');
}
const templateChecklist = await trx
.table('template_checklist')
.where('template_id', templateData.id)
.select('checklist_id');
/* ===============================
* 6. MAIN PROCESS
* =============================== */
for (const item of checkGroupings) {
if (existingMachineSet.has(item.machine_id)) {
continue;
}
/* ---------- ACTIVITY ---------- */
const [activity] = await trx
.table('activities')
.insert({
group_id: item.group_id,
template_id: null,
name: `Activity ${item.staff_name} Bulan ${monthName}/${yearName}`,
month: monthName,
year: Number(yearName),
})
.returning('id');
const [activityItem] = await trx
.table('activity_item')
.insert({
activity_id: activity.id,
group_id: item.group_id,
company_id: item.company_id,
group_item_id: item.id,
machine_id: item.machine_id,
location_id: item.location_id,
staff_id: item.staff_id,
regional_id: item.regional_id,
branch_id: item.branch_id,
frequency_id: item.frequency_id,
template_id: item.template_id,
status: 'draft',
})
.returning('id');
/* ---------- TASKS BULK ---------- */
const baseNano = BigInt(nanoTime());
const tasksPayload = dates.map((schedule, index) => ({
company_id: item.company_id,
template_id: item.template_id,
group_id: item.group_id,
location_id: item.location_id,
activity_id: activity.id,
activity_item_id: activityItem.id,
staff_id: item.staff_id,
machine_id: item.machine_id,
frequency_id: item.frequency_id,
is_clean: false,
is_validated: false,
note: null,
id_task: `T-${baseNano + BigInt(index)}`,
schedule_date: schedule,
validator_id: item.supervisor_id,
type: 'morning',
nanotime: Number(baseNano + BigInt(index)),
status: 'assigned',
timezone: item.timezone,
is_weekend: isWeekend(schedule),
}));
const insertedTasks = await trx.table('tasks').insert(tasksPayload).returning('id');
/* ---------- TASK CHECKLIST BULK ---------- */
const checklistPayload = insertedTasks.flatMap((task: any) =>
templateChecklist.map((check: any) => ({
company_id: item.company_id,
checklist_id: check.checklist_id,
template_id: item.template_id,
staff_id: item.staff_id,
task_id: task.id,
activity_id: activity.id,
activity_item_id: activityItem.id,
is_check: false,
condition: true,
}))
);
await trx.table('task_checklist').insert(checklistPayload);
}
await trx.commit();
process.exit(0);
} catch (error) {
await trx.rollback();
console.error('❌ Error:', error);
process.exit(1);
}
};
CheckSchedule();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment