Files
open-isp/services/customerIdService.js
oxpoe eaf05f2811 OPEN-ISP v0.5 (pickle-lime) — rilis open-source perdana
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
2026-10-09 05:51:21 +07:00

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 };