Files
BE_IBL/application/controllers/tools/Qr_report_uploader.php
2026-05-24 18:25:23 +07:00

261 lines
8.0 KiB
PHP

<?php
class Qr_report_uploader extends MY_Controller
{
var $db_onedev;
var $db_log;
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database('onedev', true);
$this->db_log = $this->load->database('one_lab_log', true);
}
public function index()
{
echo "QR report uploader tool";
}
public function run($limit = 10)
{
$limit = (int)$limit;
if ($limit <= 0) {
$limit = 10;
}
$endpointUrl = $this->get_active_endpoint_url();
if ($endpointUrl === '') {
$this->reply_result([
'status' => 'ERR',
'message' => 'QR_ReportEndpointUrl aktif tidak ditemukan.',
]);
return;
}
$rows = $this->get_pending_rows($limit);
$summary = [
'endpoint_url' => $endpointUrl,
'limit' => $limit,
'total_pending' => count($rows),
'uploaded' => 0,
'failed' => 0,
'failed_permanent' => 0,
'skipped' => 0,
'details' => [],
];
foreach ($rows as $row) {
$result = $this->process_row($row, $endpointUrl);
$summary['details'][] = $result;
if ($result['status'] === 'uploaded') {
$summary['uploaded']++;
} elseif ($result['status'] === 'failed') {
$summary['failed']++;
} elseif ($result['status'] === 'failed_permanent') {
$summary['failed_permanent']++;
} else {
$summary['skipped']++;
}
}
$this->reply_result([
'status' => 'OK',
'data' => $summary,
]);
}
private function get_pending_rows($limit)
{
$sql = "SELECT QR_PrintOutID,
QR_PrintOutT_OrderHeaderID,
QR_PrintOutUUID,
QR_PrintOutVerifyURL,
QR_PrintOutReportURL,
QR_PrintOutUploadStatus,
QR_PrintOutRetryCount
FROM qr_printout
WHERE QR_PrintOutIsActive = 1
AND (QR_PrintOutUploadStatus = 'pending' OR QR_PrintOutUploadStatus = 'failed')
AND QR_PrintOutRetryCount < 3
AND QR_PrintOutReportURL IS NOT NULL
AND QR_PrintOutReportURL != ''
ORDER BY QR_PrintOutCreatedAt ASC
LIMIT ?";
$qry = $this->db_onedev->query($sql, [$limit]);
if (!$qry) {
$this->reply_result([
'status' => 'ERR',
'message' => 'Gagal mengambil daftar pending.',
'db_error' => $this->db_onedev->error(),
]);
exit;
}
return $qry->result_array();
}
private function get_active_endpoint_url()
{
$sql = "SELECT QR_ReportEndpointUrl
FROM qr_report_endpoint
WHERE QR_ReportEndpointIsActive = 'Y'
LIMIT 1";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
return '';
}
$row = $qry->row_array();
if (!$row || empty($row['QR_ReportEndpointUrl'])) {
return '';
}
return rtrim($row['QR_ReportEndpointUrl'], '/') . '/';
}
private function process_row($row, $endpointUrl)
{
$printoutID = (int)$row['QR_PrintOutID'];
$orderHeaderID = (int)$row['QR_PrintOutT_OrderHeaderID'];
$reportUrl = $row['QR_PrintOutReportURL'];
$pdfContent = $this->download_file($reportUrl);
if ($pdfContent === false) {
return $this->mark_failed($row, $orderHeaderID, '', 'DOWNLOAD_FAILED');
}
if (strpos($pdfContent, '%PDF') === false) {
return $this->mark_failed($row, $orderHeaderID, '', 'INVALID_PDF');
}
$payload = json_encode([
'qrcode' => $row['QR_PrintOutUUID'],
'url' => $row['QR_PrintOutReportURL'],
'type' => 'pdf',
'name' => $row['QR_PrintOutUUID'] . '.pdf',
'base64_file' => base64_encode($pdfContent),
], JSON_UNESCAPED_SLASHES);
$response = $this->post_json($endpointUrl . 'upload', $payload, "secure-token-libCBxciByZXBvcnQ=");
$decoded = json_decode($response, true);
if (is_array($decoded) && isset($decoded['status']) && $decoded['status'] === 'OK') {
$this->log_insert_qr($printoutID, $orderHeaderID, $payload, $response);
$this->db_onedev->query(
"UPDATE qr_printout
SET QR_PrintOutUploadStatus = 'uploaded',
QR_PrintOutUploadedAt = NOW()
WHERE QR_PrintOutID = ?",
[$printoutID]
);
return [
'printout_id' => $printoutID,
'order_header_id' => $orderHeaderID,
'status' => 'uploaded',
'message' => 'Upload berhasil',
];
}
return $this->mark_failed($row, $orderHeaderID, $payload, $response);
}
private function mark_failed($row, $orderHeaderID, $payload, $response)
{
$printoutID = (int)$row['QR_PrintOutID'];
$retry = (int)$row['QR_PrintOutRetryCount'] + 1;
$newStatus = $retry >= 3 ? 'failed_permanent' : 'failed';
if ($payload !== '' || $response !== '') {
$this->log_insert_qr($printoutID, $orderHeaderID, $payload, $response);
}
$this->db_onedev->query(
"UPDATE qr_printout
SET QR_PrintOutUploadStatus = ?,
QR_PrintOutRetryCount = ?,
QR_PrintOutLastRetryAt = NOW()
WHERE QR_PrintOutID = ?",
[$newStatus, $retry, $printoutID]
);
return [
'printout_id' => $printoutID,
'order_header_id' => $orderHeaderID,
'status' => $newStatus,
'message' => is_string($response) ? $response : 'Upload gagal',
];
}
private function log_insert_qr($printoutID, $orderHeaderID, $json, $response)
{
$sql = "INSERT INTO one_lab_log.log_qr_printout(
Log_QR_PrintOutQR_PrintOutID,
Log_QR_PrintOutT_OrderHeaderID,
Log_QR_PrintOutJSON,
Log_QR_PrintOutResponse,
Log_QR_PrintOutDateTime
) VALUES(?,?,?,?,NOW())";
$this->db_onedev->query($sql, [
$printoutID,
$orderHeaderID,
$json,
$response,
]);
}
private function post_json($url, $data, $token)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($data),
"Authorization: Bearer {$token}",
]);
$result = curl_exec($ch);
if (curl_error($ch) !== '') {
$error = curl_error($ch);
curl_close($ch);
return "ERROR API [{$url}] : {$error}";
}
curl_close($ch);
return $result;
}
private function download_file($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
if (curl_error($ch)) {
curl_close($ch);
return false;
}
curl_close($ch);
return $result;
}
private function reply_result($result)
{
if ($this->input->is_cli_request()) {
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL;
return;
}
echo json_encode($result);
}
}