Aplikasi billing & manajemen ISP (fiber optic) — PWA pelanggan, portal teknisi & kolektor, admin panel lengkap, multi-vendor OLT, RADIUS, WhatsApp/Telegram, pembayaran QRIS. Kredit & lisensi (ISC): - Base kode & repo: alijayanet/billing-rtrw oleh Alijaya Net — terima kasih banyak atas base kode dan repo yang bermanfaat. - Add-on: GoWA, LibreSpeed/OpenSpeedTest, Uptime Kuma, notification-forwarder. - Dikembangkan menjadi OPEN-ISP oleh oxpoe — https://github.com/oxpoe/open-isp
68 lines
2.6 KiB
JavaScript
68 lines
2.6 KiB
JavaScript
/**
|
|
* customerIdService.js — ID Pelanggan PERMANEN (tidak bisa di-regenerate).
|
|
*
|
|
* Format: <PREFIX>-<angka> contoh: SKY-48213
|
|
* - Hanya ANGKA setelah tanda hubung (tanpa huruf).
|
|
* - Dibuat otomatis sekali saat pelanggan dibuat, lalu melekat permanen.
|
|
* - Unik (dicek ke DB, tanpa duplikat).
|
|
* - Prefix & jumlah digit diatur di Pengaturan (customer_id_prefix / customer_id_digits).
|
|
*/
|
|
const crypto = require('crypto');
|
|
const db = require('../config/database');
|
|
const { getSetting } = require('../config/settingsManager');
|
|
|
|
const DEFAULT_PREFIX = 'ISP';
|
|
const DEFAULT_DIGITS = 5;
|
|
|
|
function sanitizePrefix(p) {
|
|
return String(p || '').toUpperCase().replace(/[^A-Z0-9]/g, '').slice(0, 12);
|
|
}
|
|
function sanitizeDigits(d) {
|
|
const n = parseInt(d, 10);
|
|
if (!Number.isFinite(n)) return DEFAULT_DIGITS;
|
|
return Math.min(Math.max(n, 4), 10);
|
|
}
|
|
function randomDigits(n) {
|
|
let out = '';
|
|
for (let i = 0; i < n; i++) out += String(crypto.randomInt(0, 10));
|
|
return out;
|
|
}
|
|
function escapeRe(s) { return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
|
|
|
|
// Format baru yang berlaku: <PREFIX>-<angka> (minimal 4 digit).
|
|
// Sengaja TIDAK bergantung nilai prefix saat ini → mengubah prefix tidak
|
|
// akan membuat kode lama ikut ter-regenerate (permanen).
|
|
function isNewFormat(code) {
|
|
return /^[A-Z0-9]+-\d{4,10}$/.test(String(code || ''));
|
|
}
|
|
|
|
function generateCustomerCode() {
|
|
const prefix = sanitizePrefix(getSetting('customer_id_prefix', DEFAULT_PREFIX)) || DEFAULT_PREFIX;
|
|
const digits = sanitizeDigits(getSetting('customer_id_digits', DEFAULT_DIGITS));
|
|
const check = db.prepare('SELECT 1 FROM customers WHERE customer_code = ? LIMIT 1');
|
|
for (let i = 0; i < 60; i++) {
|
|
const code = prefix + '-' + randomDigits(digits);
|
|
if (!check.get(code)) return code;
|
|
}
|
|
// Ruang hampir penuh → tambah 1 digit agar tetap unik
|
|
return prefix + '-' + randomDigits(digits + 1);
|
|
}
|
|
|
|
// Isi yang kosong + migrasi sekali untuk format lama (bukan PREFIX-angka).
|
|
// Kode yang sudah sesuai format baru TIDAK akan diubah (permanen).
|
|
function backfillCustomerCodes() {
|
|
try {
|
|
const rows = db.prepare('SELECT id, customer_code FROM customers').all()
|
|
.filter((r) => !r.customer_code || !isNewFormat(r.customer_code));
|
|
if (!rows.length) return 0;
|
|
const upd = db.prepare('UPDATE customers SET customer_code = ? WHERE id = ?');
|
|
const run = db.transaction((list) => { for (const r of list) upd.run(generateCustomerCode(), r.id); });
|
|
run(rows);
|
|
return rows.length;
|
|
} catch (e) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
module.exports = { generateCustomerCode, backfillCustomerCodes, isNewFormat, sanitizePrefix, sanitizeDigits };
|