Update Voucher , Tiket , Dashboard
membuat perubahan dan update
This commit is contained in:
+345
-55
@@ -1,4 +1,10 @@
|
||||
<!-- Main content -->
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
?>
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
@@ -11,15 +17,225 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="float-sm-right mb-0">
|
||||
<!--<a type="button" class="btn btn-danger btn-sm m-1" data-toggle="modal" data-target="#staticBackdrop">Tambah</a>-->
|
||||
<a type="button" class="btn btn-danger btn-sm m-1" data-toggle="modal" data-target="#staticBackdrop">Generate</a>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Modal Tambah -->
|
||||
<div class="modal fade" id="staticBackdrop" data-backdrop="static" data-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div class="modal-header bg-primary">
|
||||
<h5 class="modal-title" id="staticBackdropLabel">Generate Voucher</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Nama Server</label>
|
||||
<select class="form-control" name="ids" required>
|
||||
<option value="">Pilih</option>
|
||||
<?php
|
||||
$List = new Listdata();
|
||||
$List->set_list("data_server", $SqlDataWH);
|
||||
foreach ($List->get_list() as $key => $value): ?>
|
||||
<option value="<?php echo $value['id']; ?>"><?php echo $value['nama_server']; ?></option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Mikrotik</label>
|
||||
<select class="form-control" name="idm" required>
|
||||
<option value="">Pilih</option>
|
||||
<?php
|
||||
$List = new Listdata();
|
||||
$List->set_list("setting_mikrotik", $SqlDataWHId);
|
||||
foreach ($List->get_list() as $key => $value): ?>
|
||||
<option value="<?php echo $value['id']; ?>"><?php echo $value['nama']; ?></option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-8">
|
||||
<div class="form-group">
|
||||
<label>Paket</label>
|
||||
<select class="form-control" name="idp" required>
|
||||
<option value="">Pilih</option>
|
||||
<?php
|
||||
$List = new Listdata();
|
||||
$List->set_list("profile_paket", $SqlDataWHId . "AND jenis_profile = 'Hotspot' AND status = 1");
|
||||
foreach ($List->get_list() as $key => $value): ?>
|
||||
<option value="<?php echo $value['id']; ?>"><?php echo $value['nama']; ?></option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="form-group">
|
||||
<label>Jumlah</label>
|
||||
<div class="input-group mb-3">
|
||||
<input type="number" class="form-control" min="1" max="50" value="1" name="jumlah" id="jumlah" required>
|
||||
<span class="input-group-text" id="basic-addon2">Pcs</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<input type="submit" name="generate" class="btn btn-primary" value="Generate">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if (isset($_POST['generate'])) {
|
||||
try {
|
||||
// Mulai transaksi DB
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Ambil data paket
|
||||
$stmt = $pdo->prepare("SELECT radius_data,durasi,nama_profile,harga_paket FROM profile_paket WHERE id = :idp");
|
||||
$stmt->execute([':idp' => $_POST['idp']]);
|
||||
$paket = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// ====== KIRIM KE API MIKROTIK ======
|
||||
$stmt = $pdo->prepare("SELECT ip_address,username,password,port_api,radius_nas_data FROM setting_mikrotik WHERE id = :id");
|
||||
$stmt->execute([':id' => $_POST['idm']]);
|
||||
$mikrotik = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$dataMik = json_decode($mikrotik['radius_nas_data']);
|
||||
|
||||
if (!$paket) {
|
||||
throw new Exception("Paket tidak ditemukan.");
|
||||
}
|
||||
|
||||
$data = json_decode($paket['radius_data']);
|
||||
$kode = $data ? 'VR' : 'VM'; // VR = Radius, VM = MikroTik
|
||||
$jenis = $data ? 'sv-radius' : 'sv-mikrotik';
|
||||
$karakter = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890qwertyuiopasdfghjklzxcvbnm";
|
||||
$str = $paket['durasi'];
|
||||
$jumlah = intval($_POST['jumlah']);
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
// Validasi jumlah
|
||||
if ($jumlah < 1 || $jumlah > 200) {
|
||||
throw new Exception("Jumlah voucher harus antara 1-200.");
|
||||
}
|
||||
|
||||
// Generate voucher unik
|
||||
$voucherList = [];
|
||||
while (count($voucherList) < $jumlah) {
|
||||
$kodevoucher = $str . substr(str_shuffle($karakter), 0, 7) . $kode;
|
||||
|
||||
// Pastikan tidak duplikat di DB & array
|
||||
$cek = $pdo->prepare("SELECT COUNT(*) FROM ganerate_voucher WHERE voucher = :voucher");
|
||||
$cek->execute([':voucher' => $kodevoucher]);
|
||||
if ($cek->fetchColumn() == 0 && !in_array($kodevoucher, $voucherList)) {
|
||||
$voucherList[] = $kodevoucher;
|
||||
}
|
||||
}
|
||||
|
||||
// Kirim ke Radius atau MikroTik
|
||||
$successVoucher = [];
|
||||
$failVoucher = [];
|
||||
|
||||
if ($data) {
|
||||
// ====== KIRIM KE RADIUS ======
|
||||
$radius = new CrudRadiusServer();
|
||||
$apiResponse = $radius->request('add_user', 'POST', [
|
||||
'jenis' => 'Hotspot',
|
||||
'username' => $voucherList,
|
||||
'password' => $voucherList,
|
||||
'groupname' => $data->groupname,
|
||||
'nasgroupname' => $dataMik->data->{'nasgroupname'}
|
||||
]);
|
||||
|
||||
foreach ($apiResponse['results'] as $res) {
|
||||
if ($res['status'] === 'success') {
|
||||
$successVoucher[] = $res['username'];
|
||||
} else {
|
||||
$failVoucher[] = $res['username'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($successVoucher)) {
|
||||
throw new Exception("Tidak ada voucher yang berhasil dibuat di Radius.");
|
||||
}
|
||||
} else {
|
||||
|
||||
require('router_api/routeros_api.class.php');
|
||||
$API = new RouterosAPI();
|
||||
$API->debug = false;
|
||||
|
||||
if (!$API->connect2($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password'], $mikrotik['port_api'])) {
|
||||
throw new Exception("Gagal konek ke API MikroTik.");
|
||||
}
|
||||
|
||||
foreach ($voucherList as $vcr) {
|
||||
$result = $API->comm('/ip/hotspot/user/add', [
|
||||
"name" => $vcr,
|
||||
"password" => $vcr,
|
||||
"profile" => $paket['nama_profile'], // pastikan field profile ada di DB
|
||||
"server" => "all"
|
||||
]);
|
||||
|
||||
if (isset($result['!trap'])) {
|
||||
$failVoucher[] = $vcr;
|
||||
} else {
|
||||
$successVoucher[] = $vcr;
|
||||
}
|
||||
}
|
||||
|
||||
$API->disconnect();
|
||||
|
||||
if (empty($successVoucher)) {
|
||||
throw new Exception("Tidak ada voucher yang berhasil dibuat di MikroTik.");
|
||||
}
|
||||
}
|
||||
|
||||
// Insert ke DB hanya yang sukses
|
||||
$values = [];
|
||||
$params = [];
|
||||
foreach ($successVoucher as $voucher) {
|
||||
$values[] = "(?, ?, ?, ?, ?, ?, ?)";
|
||||
$params[] = $_POST['ids']; // id_data_server
|
||||
$params[] = $_POST['idm']; // id_setting_mikrotik
|
||||
$params[] = $_POST['idp']; // id_profile_paket
|
||||
$params[] = $voucher; // voucher
|
||||
$params[] = $paket['harga_paket']; // harga
|
||||
$params[] = $jenis; // jenis
|
||||
$params[] = $date; // create_time
|
||||
}
|
||||
|
||||
$sql = "INSERT INTO ganerate_voucher
|
||||
(id_data_server, id_setting_mikrotik, id_profile_paket, voucher, harga, jenis, create_time)
|
||||
VALUES " . implode(", ", $values);
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
// Commit transaksi
|
||||
$pdo->commit();
|
||||
|
||||
$totalSuccess = count($successVoucher);
|
||||
$totalError = count($failVoucher);
|
||||
|
||||
sweetAlert("$totalSuccess voucher berhasil dibuat. Gagal: $totalError", "success");
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
// sweetAlert("Gagal membuat voucher: " . $e->getMessage(), "error");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-7">
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-2">
|
||||
|
||||
@@ -68,67 +284,101 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<?php
|
||||
// Ambil semua data Mikrotik langsung
|
||||
$List = new Listdata();
|
||||
$List->set_list("setting_mikrotik", $SqlDataWHId);
|
||||
?>
|
||||
<h6 class="mt-2 mb-2">Mikrotik</h6>
|
||||
<select class="form-control" name="idmscript" id="idmscript">
|
||||
<?php foreach ($List->get_list() as $value):
|
||||
$radius_data = json_decode($value['radius_nas_data']);
|
||||
$dataUrl = encrypt_url(json_encode([
|
||||
'board' => $value['board_id'],
|
||||
'nasgroupname' => $radius_data->data->{'nasgroupname'}
|
||||
]));
|
||||
?>
|
||||
<option value="<?= htmlspecialchars($dataUrl) ?>">
|
||||
<?= htmlspecialchars($value['nama']) ?>
|
||||
</option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
|
||||
<h6 class="mt-2 mb-2">Login Page Script</h6>
|
||||
<div class="mb-3">
|
||||
<div class="text-right" style="margin-bottom: -33px; margin-right: 2px;">
|
||||
<a onclick="copyToClipboard('script-page')" class="btn btn-sm btn-light btn-icon" title="Copy">
|
||||
<i class="fa fa-copy"></i>
|
||||
</a>
|
||||
</div>
|
||||
<pre class="bg-light border rounded p-3 mb-2" id="script-page">
|
||||
Loading script...
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Buat script HTML dengan escape karakter agar aman
|
||||
function generateScript(dataUrl) {
|
||||
return `<div id="voucher-container"></div>;
|
||||
<script src="http://localhost/manjapro-project/voucherpay/cl-style.js?i=${dataUrl}"></script>`;
|
||||
}
|
||||
|
||||
// Update script ketika pilihan berubah
|
||||
function updateScript() {
|
||||
const selectedValue = document.getElementById('idmscript').value;
|
||||
const preElement = document.getElementById('script-page');
|
||||
preElement.textContent = generateScript(selectedValue);
|
||||
}
|
||||
|
||||
// Event: saat select berubah
|
||||
document.getElementById('idmscript').addEventListener('change', updateScript);
|
||||
|
||||
// Saat halaman pertama kali load
|
||||
window.addEventListener('DOMContentLoaded', updateScript);
|
||||
|
||||
// Tombol copy
|
||||
function copyToClipboard(preId) {
|
||||
const text = document.getElementById(preId).textContent
|
||||
.replace(/</g, "<").replace(/>/g, ">");
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
// console.log("Script berhasil disalin!");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-5">
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-2">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<center>
|
||||
<p>Akumulasi Voucher</p>
|
||||
<p>Voucher List</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-6">
|
||||
<!-- small box -->
|
||||
<div class="small-box bg-info" id="pendingBox">
|
||||
<div class="inner">
|
||||
<h4 id="jumtotalValue">0</h4>
|
||||
<p>Total Voucher</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-android-wifi"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-6">
|
||||
<!-- small box -->
|
||||
<div class="small-box bg-warning" id="pendingBox">
|
||||
<div class="inner">
|
||||
<h4 id="jumbelumValue">0</h4>
|
||||
<p>Belum Aktif</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-wifi"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-6">
|
||||
<!-- small box -->
|
||||
<div class="small-box bg-success" id="pendingBox">
|
||||
<div class="inner">
|
||||
<h4 id="jumsedangValue">0</h4>
|
||||
<p>Sedang Aktif</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-android-wifi"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-6">
|
||||
<!-- small box -->
|
||||
<div class="small-box bg-danger" id="pendingBox">
|
||||
<div class="inner">
|
||||
<h4 id="jumsudahValue">0</h4>
|
||||
<p>Sudah Kedaluarsa</p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="ion ion-wifi"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="voucherTable" class="table table-striped table-bordered" style="zoom: 90%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Waktu</th>
|
||||
<th>Voucher</th>
|
||||
<th>Harga</th>
|
||||
<th>Biaya</th>
|
||||
<th>Saldo</th>
|
||||
<th>Status</th>
|
||||
<th>Aktif</th>
|
||||
<th>Expired</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -227,3 +477,43 @@
|
||||
// Panggil fungsi setDefaultMonth saat halaman dimuat
|
||||
window.onload = fetchDataAgen();
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#voucherTable').DataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"responsive": true,
|
||||
"autoWidth": false,
|
||||
"ajax": {
|
||||
"url": "controller/voucher_auto.php",
|
||||
"type": "GET"
|
||||
},
|
||||
"pageLength": 25,
|
||||
"columns": [
|
||||
{ "data": 0 }, // create_time
|
||||
{ "data": 1 }, // voucher
|
||||
{ "data": 2 }, // harga
|
||||
{ "data": 3, "orderable": false }, // biaya (tidak bisa diurutkan)
|
||||
{ "data": 4, "orderable": false }, // saldo (tidak bisa diurutkan)
|
||||
{ "data": 5 }, // status_cek
|
||||
{ "data": 6 }, // active_time
|
||||
{ "data": 7 } // expaired_time
|
||||
],
|
||||
"order": [[0, "desc"]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.getElementById('jumlah').addEventListener('input', function () {
|
||||
let value = parseInt(this.value);
|
||||
|
||||
if (value > 50) {
|
||||
this.value = 50; // set max
|
||||
} else if (value < 1) {
|
||||
this.value = 1; // set min
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user