import 'dotenv/config' import cron from "node-cron"; import dayjs from "dayjs"; import axios from "axios"; import prisma from "../prisma/PrismaClient"; import { formatISOWithoutTimezone } from './FormatDate'; const queue: (() => Promise)[] = []; let processing = false; const API_URL_NOTIFICATION = process.env.API_TOKEN_NOTIFICATION; const API_TOKEN_NOTIFICATTION = process.env.API_TOKEN_NOTIFICATTION; const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); const randomDelay = () => { const min = 60 * 1000; // 60 detik const max = 180 * 1000; // 180 detik return Math.floor(Math.random() * (max - min + 1)) + min; }; // Worker untuk memproses queue const processQueue = async () => { if (processing || queue.length === 0) return; processing = true; while (queue.length > 0) { console.log(`▶️ Mulai memproses antrean, sisa job: ${queue.length}`); const job = queue.shift(); if (job) { try { await job(); if (queue.length > 0) { const delayMs = randomDelay(); console.log(`⏳ Tunggu ${Math.round(delayMs / 1000)} detik sebelum job berikutnya...`); await delay(delayMs); } } catch (err: any) { console.error("❌ Job gagal:", err.message); } } } console.log("✅ Semua job selesai diproses."); processing = false; }; // Tambah job ke antrean const addToQueue = (fn: () => Promise) => { queue.push(fn); console.log(`➕ Job ditambahkan ke antrean. Total sekarang: ${queue.length}`); console.log("📦 Isi antrean saat ini:", queue.map((_, i) => `Job#${i + 1}`)); processQueue(); }; // Cron: jalan tiap hari cron.schedule("00 08 * * *", async () => { console.log("⏰ [CRON] Checking schedules for today..."); try { const today = dayjs().startOf("day").toDate(); const tomorrow = dayjs().add(1, "day").startOf("day").toDate(); // Ambil semua schedule untuk hari ini const schedules = await prisma.scheduleVisitation.findMany({ where: { deletedAt: null, date_visit: { gte: today, lt: tomorrow, }, }, include: { sales_visit: true, hospital: { include: { province: true, city: true, } } }, }); if (schedules.length === 0) { console.log("ℹ️ No schedules for today."); return; } console.log(`📌 Ditemukan ${schedules.length} schedule untuk hari ini:`); schedules.forEach((s, idx) => { console.log(` #${idx + 1} SalesID=${s.sales_id}, Phone=${s.sales_visit?.phone ?? "❌ kosong"}`); }); schedules.forEach((schedule, idx) => { const phone = schedule.sales_visit?.phone as string | undefined; if (!phone) { console.warn(`⚠️ Sales ${schedule.sales_id} tidak punya nomor telepon.`); return; } const fullname = schedule.sales_visit?.fullname || '-'; const hospitalName = schedule.hospital?.name || '-'; const hospitalAddress = schedule.hospital?.address || '-'; const hospitalContact = schedule.hospital?.contact || '-'; const hospitalEmail = schedule.hospital?.email || '-'; const hospitalLat = schedule.hospital?.latitude || '-'; const hospitalLong = schedule.hospital?.longitude || '-'; const hospitalGmaps = schedule.hospital?.gmaps_url || '-'; const hospitalProv = schedule.hospital?.province.name || '-'; const hospitalCity = schedule.hospital?.city.name || '-'; const scheduleCreate = schedule.createdAt || '-'; const message = ` Halo ${fullname}, [[[ maaf, ini sedang testing - gayuh ]]] Ini adalah pengingat jadwal kunjungan yang dibuat pada tanggal ${formatISOWithoutTimezone(scheduleCreate)}. Anda dijadwalkan untuk mengunjungi: Rumah Sakit: ${hospitalName} Alamat: ${hospitalAddress} Kota: ${hospitalCity}, Provinsi: ${hospitalProv} Kontak: ${hospitalContact}, Email: ${hospitalEmail} Lokasi Google Maps: ${hospitalGmaps} Koordinat: Latitude ${hospitalLat}, Longitude ${hospitalLong} Nomor telepon sales terkait: ${phone} Pastikan semua persiapan kunjungan sudah lengkap! Semangat bertugas! `.trim(); addToQueue(async () => { console.log( `[${dayjs().format("HH:mm:ss")}] 📩 (Job#${idx + 1}) Sending message to ${phone}...` ); await axios.post( API_URL_NOTIFICATION!, { to: phone, message }, { headers: { "x-api-token": API_TOKEN_NOTIFICATTION!, "Content-Type": "application/json", }, } ); console.log( `[${dayjs().format("HH:mm:ss")}] ✔️ (Job#${idx + 1}) Sent message to ${phone}` ); }); }); } catch (err: any) { console.error("❌ Cron job error:", err.message); } });