gl aggregate table (ETL), cronjob by NODEJS
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../config.php';
|
||||
require '../include_header.php';
|
||||
?>
|
||||
|
||||
<body>
|
||||
<?php require '../include_topbar.php'; ?>
|
||||
<?php require '../include_setting_sidebar.php'; ?>
|
||||
|
||||
<main id="content" class="content py-15">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center mb-6 gap-3">
|
||||
<div>
|
||||
<h1 class="fs-3 mb-1">ETL GL Summary Maintenance</h1>
|
||||
<p class="mb-0">Manages the <code>etl_gl_summary</code> table used by the accounting reports</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-5">
|
||||
|
||||
<!-- Automatic Maintenance -->
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card border-0 shadow-sm h-100" style="position:relative;">
|
||||
<div class="card-header bg-transparent border-bottom">
|
||||
<h6 class="mb-0"><i class="ti ti-clock me-2"></i>Automatic Maintenance</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted small mb-4">
|
||||
The system automatically checks and repairs the GL summary table nightly.
|
||||
Each company is assigned a fixed time slot to distribute load across the day.
|
||||
</p>
|
||||
<table class="table table-sm table-borderless mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-muted small" style="width:160px;">Scheduled slot</td>
|
||||
<td><strong id="stat_slot">—</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted small">Last ran</td>
|
||||
<td id="stat_last_ran">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted small">Last result</td>
|
||||
<td id="stat_last_result">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted small">Gaps found</td>
|
||||
<td id="stat_gaps_found">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted small">Periods rebuilt</td>
|
||||
<td id="stat_periods_rebuilt">—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-muted small">Next run</td>
|
||||
<td id="stat_next_run">—</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-loader-overlay" id="overlay_status">
|
||||
<div class="spinner-border spinner-border-sm text-primary"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manual Rebuild -->
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-transparent border-bottom">
|
||||
<h6 class="mb-0"><i class="ti ti-database me-2"></i>Manual Full Rebuild</h6>
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<p class="text-muted small mb-3">
|
||||
Wipes and rebuilds the entire GL summary table from raw journal entries.
|
||||
Use this after a direct database fix, data migration, or if dashboard figures look incorrect.
|
||||
</p>
|
||||
<div class="alert alert-warning d-flex gap-2 align-items-start py-2 px-3 small mb-4">
|
||||
<i class="ti ti-alert-triangle mt-1 flex-shrink-0"></i>
|
||||
<span>Rebuilds one month at a time. The dashboard stays usable during the rebuild — it falls back to raw data for any period not yet in the summary.</span>
|
||||
</div>
|
||||
<div class="mt-auto">
|
||||
<button class="btn btn-danger" id="btn_rebuild_full">
|
||||
<i class="ti ti-database-import me-1"></i>Rebuild Full ETL Table
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php require '../include_ending.php'; ?>
|
||||
|
||||
<script>
|
||||
function load_status() {
|
||||
$('#overlay_status').show();
|
||||
ajax_request({
|
||||
url: server_url + 'setting/api/engine/gl_maintenance.php',
|
||||
autoPrepare: true, checkRequired: 0, noLoading: true, queueLock: false, action: 'read',
|
||||
onSuccess: function(res) {
|
||||
var d = res.output;
|
||||
$('#stat_slot').text(pad2(d.slot_hour) + ':00 daily');
|
||||
$('#stat_last_ran').text(d.last_ran || '—');
|
||||
$('#stat_last_result').html(
|
||||
d.last_result === 'ok'
|
||||
? '<span class="badge bg-success-subtle text-success">OK</span>'
|
||||
: d.last_result
|
||||
? '<span class="badge bg-danger-subtle text-danger">' + escape_html(d.last_result) + '</span>'
|
||||
: '—'
|
||||
);
|
||||
$('#stat_gaps_found').text(d.last_result ? d.gaps_found : '—');
|
||||
$('#stat_periods_rebuilt').text(d.last_result ? d.periods_rebuilt : '—');
|
||||
$('#stat_next_run').text(d.next_run || '—');
|
||||
$('#overlay_status').hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pad2(n) { return String(n).padStart(2, '0'); }
|
||||
|
||||
$('#btn_rebuild_full').on('click', function() {
|
||||
bootbox.confirm({
|
||||
title: 'Rebuild Full ETL Table',
|
||||
message: 'This will rebuild the GL summary table one month at a time from raw journal entries. Continue?',
|
||||
buttons: {
|
||||
confirm: { label: 'Rebuild', className: 'btn-danger' },
|
||||
cancel: { label: 'Cancel', className: 'btn-secondary' }
|
||||
},
|
||||
callback: function(confirmed) {
|
||||
if (!confirmed) return;
|
||||
|
||||
var btn = $('#btn_rebuild_full').prop('disabled', true);
|
||||
|
||||
ajax_request({
|
||||
url: server_url + 'setting/api/engine/gl_maintenance.php',
|
||||
autoPrepare: true, checkRequired: 0, noLoading: true, queueLock: false, action: 'get_periods',
|
||||
onSuccess: function(res) {
|
||||
var periods = res.output || [];
|
||||
var total = periods.length;
|
||||
|
||||
if (total === 0) {
|
||||
btn.prop('disabled', false);
|
||||
bootbox.alert('No GL periods found.');
|
||||
return;
|
||||
}
|
||||
|
||||
BatchOverlay.show('Rebuilding GL Summary', total, { unit: 'periods', color: '#dc3545' });
|
||||
|
||||
function rebuild_next(i) {
|
||||
if (i >= total) {
|
||||
BatchOverlay.done(total + ' period(s) rebuilt successfully.', function() {
|
||||
btn.prop('disabled', false);
|
||||
});
|
||||
load_status();
|
||||
return;
|
||||
}
|
||||
|
||||
BatchOverlay.update(i, total, periods[i]);
|
||||
|
||||
ajax_request({
|
||||
url: server_url + 'setting/api/engine/gl_maintenance.php',
|
||||
autoPrepare: true, checkRequired: 0, noLoading: true, queueLock: false,
|
||||
action: 'rebuild_period', data: { period: periods[i] },
|
||||
onSuccess: function() { rebuild_next(i + 1); },
|
||||
onError: function() { rebuild_next(i + 1); }
|
||||
});
|
||||
}
|
||||
|
||||
rebuild_next(0);
|
||||
},
|
||||
onError: function() {
|
||||
BatchOverlay.hide();
|
||||
btn.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
load_status();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user