feat(assets): align assets toolbar layout with controls and enable multi-page select all

This commit is contained in:
kdeterme 2026-10-11 19:14:03 +02:00
parent f19d09ce5f
commit 9c9aa30df7
3 changed files with 442 additions and 132 deletions

View file

@ -638,6 +638,79 @@ function applyVisibleColumnsPreference(visibleColumns) {
}
});
isApplyingSavedColumnVisibility = false;
// Update checkboxes in dropdown
document.querySelectorAll('.col-toggle-check').forEach(cb => {
cb.checked = wanted.has(cb.dataset.column);
});
}
function renderColumnsDropdown() {
const container = document.getElementById('columns-list-container');
if (!container) return;
container.innerHTML = '';
const cols = [
{ field: 'code', label: gettext('Code'), defaultVisible: true },
{ field: 'name', label: gettext('Nom'), defaultVisible: true },
{ field: 'element_type', label: gettext('Type'), defaultVisible: true },
{ field: 'thematic_name', label: gettext('Thématique'), defaultVisible: true },
{ field: 'category', label: gettext('Catégorie d\'assets'), defaultVisible: false },
{ field: 'model', label: gettext('Modèle'), defaultVisible: false },
{ field: 'status', label: gettext('Statut'), defaultVisible: false },
{ field: 'validation_status', label: gettext('Statut de validation'), defaultVisible: true },
];
const visibleCols = new Set(getVisibleColumnsPreference());
cols.forEach(col => {
const isVisible = visibleCols.has(col.field);
const div = document.createElement('div');
div.className = 'form-check py-1';
div.innerHTML = `
<input class="form-check-input col-toggle-check" type="checkbox" id="col-toggle-${col.field}" data-column="${col.field}" ${isVisible ? 'checked' : ''}>
<label class="form-check-label user-select-none small text-dark" for="col-toggle-${col.field}">${col.label}</label>
`;
container.appendChild(div);
});
container.addEventListener('change', (e) => {
const cb = e.target.closest('.col-toggle-check');
if (!cb) return;
const colField = cb.dataset.column;
if (cb.checked) {
$('#unified-table').bootstrapTable('showColumn', colField);
} else {
$('#unified-table').bootstrapTable('hideColumn', colField);
}
schedulePreferencesSave();
});
document.getElementById('cols-select-all')?.addEventListener('click', (e) => {
e.preventDefault();
cols.forEach(col => {
$('#unified-table').bootstrapTable('showColumn', col.field);
});
container.querySelectorAll('.col-toggle-check').forEach(cb => { cb.checked = true; });
schedulePreferencesSave();
});
document.getElementById('cols-reset-default')?.addEventListener('click', (e) => {
e.preventDefault();
cols.forEach(col => {
if (col.defaultVisible) {
$('#unified-table').bootstrapTable('showColumn', col.field);
} else {
$('#unified-table').bootstrapTable('hideColumn', col.field);
}
});
container.querySelectorAll('.col-toggle-check').forEach(cb => {
const field = cb.dataset.column;
const def = cols.find(c => c.field === field);
cb.checked = !!def?.defaultVisible;
});
schedulePreferencesSave();
});
}
// ─── Preferences: save / restore ─────────────────────────────────────────────
@ -834,14 +907,27 @@ $(document).ready(function () {
search: false,
pagination: true,
pageSize: 100,
maintainMetaData: true,
clickToSelect: true,
ignoreClickToSelectOn: function (element) {
return $(element).closest('.zoom-btn, .unified-code-link').length > 0;
},
onCheck: function (row) { row.state = true; selectedIds.add(row.id); updateSelectionStatus(); },
onUncheck: function (row) { row.state = false; selectedIds.delete(row.id); updateSelectionStatus(); },
onCheckAll: function (rows) { rows.forEach(r => { r.state = true; selectedIds.add(r.id); }); updateSelectionStatus(); },
onUncheckAll: function (rows) { rows.forEach(r => { r.state = false; selectedIds.delete(r.id); }); updateSelectionStatus(); },
onCheck: function (row) {
row.state = true;
selectedIds.add(row.id);
updateSelectionStatus();
},
onUncheck: function (row) {
row.state = false;
selectedIds.delete(row.id);
updateSelectionStatus();
},
onCheckAll: function (rows) {
selectAllTableRows();
},
onUncheckAll: function (rows) {
deselectAllTableRows();
},
onClickRow: function (row) {
if (!row.lon || !row.lat) return;
const source = row.is_management_zone ? 'management_zones' : (row.is_location ? 'locations' : 'assets');
@ -851,6 +937,10 @@ $(document).ready(function () {
},
});
$('#unified-table').on('post-body.bs.table page-change.bs.table', function () {
syncSelectAllCheckbox();
});
$(window).on('resize', function () {
$('#unified-table').bootstrapTable('resetView', { height: calcHeight() });
});
@ -1289,28 +1379,21 @@ $(document).ready(function () {
// ─── Select all / deselect all ─────────────────────────────────────────
function selectAllTableRows() {
const allRows = $('#unified-table').bootstrapTable('getData') || [];
allRows.forEach(r => {
selectedIds.add(r.id);
r.state = true;
});
$('#unified-table').bootstrapTable('checkAll');
updateSelectionStatus();
}
$(document).on('click', 'input[name="btSelectAll"]', function () {
if (this.checked) {
selectAllTableRows();
} else {
deselectAllTableRows();
}
});
function deselectAllTableRows() {
const allRows = $('#unified-table').bootstrapTable('getData') || [];
allRows.forEach(r => {
r.state = false;
});
selectedIds.clear();
$('#unified-table').bootstrapTable('uncheckAll');
updateSelectionStatus();
}
document.getElementById('page-size-select')?.addEventListener('change', function () {
const newSize = parseInt(this.value, 10) || 100;
$('#unified-table').bootstrapTable('refreshOptions', { pageSize: newSize });
});
document.getElementById('unified-select-all').addEventListener('click', selectAllTableRows);
document.getElementById('unified-deselect-all').addEventListener('click', deselectAllTableRows);
document.getElementById('unified-select-all')?.addEventListener('click', selectAllTableRows);
document.getElementById('unified-deselect-all')?.addEventListener('click', deselectAllTableRows);
bindUnifiedAssetsExport();
bindUnifiedBulkActions();
@ -1349,6 +1432,7 @@ $(document).ready(function () {
// ─── Init ──────────────────────────────────────────────────────────────
applyInitialPreferences();
renderColumnsDropdown();
buildCategoryLookup();
renderCategoryFilters();
renderModelFilters();
@ -1645,7 +1729,7 @@ function getCsrfToken() {
}
function getSelectedAssetKeysForExport() {
const rows = $('#unified-table').bootstrapTable('getData') || [];
const rows = getAllTableRows();
const keys = [];
const seen = new Set();
@ -1740,7 +1824,7 @@ function bindUnifiedAssetsExport() {
}
function buildBulkSelectedAssetsPayload() {
const rows = $('#unified-table').bootstrapTable('getData') || [];
const rows = getAllTableRows();
const byId = new Map(rows.filter(r => !r.is_location).map(r => [String(r.id), r]));
const payload = [];
@ -2774,14 +2858,9 @@ function loadTableData(features) {
$('#unified-spinner').hide();
$('#unified-table').bootstrapTable('load', rows);
// Restore checked state
if (selectedIds.size) {
rows.forEach((row, idx) => {
if (selectedIds.has(row.id)) {
$('#unified-table').bootstrapTable('check', idx);
}
});
}
updateSelectionStatus();
const countBadge = document.getElementById('assets-counter-badge');
if (countBadge) countBadge.textContent = rows.length;
}
// ─── Map integration ──────────────────────────────────────────────────────────
@ -3093,6 +3172,9 @@ function showEmptyState() {
hideSpinner();
document.getElementById('unified-empty-state').style.display = '';
updateAssetsHint();
const countBadge = document.getElementById('assets-counter-badge');
if (countBadge) countBadge.textContent = '0';
syncSelectAllCheckbox();
}
function hideEmptyState() {
@ -3129,6 +3211,81 @@ function updateFilterBadge() {
badge.classList.toggle('d-none', n === 0);
}
function getAllTableRows() {
const $table = $('#unified-table');
if (!$table.length || typeof $table.bootstrapTable !== 'function') return [];
const options = $table.bootstrapTable('getOptions');
if (options && Array.isArray(options.data) && options.data.length > 0) {
return options.data;
}
return $table.bootstrapTable('getData', { useCurrentPage: false }) || [];
}
var isBulkSelectionInProgress = false;
function selectAllTableRows() {
if (isBulkSelectionInProgress) return;
isBulkSelectionInProgress = true;
try {
const allRows = getAllTableRows();
allRows.forEach(r => {
selectedIds.add(r.id);
r.state = true;
});
$('#unified-table tbody tr').addClass('selected');
$('#unified-table input[name="btSelectItem"]').prop('checked', true);
updateSelectionStatus();
} finally {
isBulkSelectionInProgress = false;
}
}
function deselectAllTableRows() {
if (isBulkSelectionInProgress) return;
isBulkSelectionInProgress = true;
try {
const allRows = getAllTableRows();
allRows.forEach(r => {
r.state = false;
selectedIds.delete(r.id);
});
$('#unified-table tbody tr').removeClass('selected');
$('#unified-table input[name="btSelectItem"]').prop('checked', false);
updateSelectionStatus();
} finally {
isBulkSelectionInProgress = false;
}
}
function syncSelectAllCheckbox() {
const allRows = getAllTableRows();
const selectAllCheckboxes = document.querySelectorAll('input[name="btSelectAll"]');
if (!selectAllCheckboxes.length) return;
if (allRows.length === 0) {
selectAllCheckboxes.forEach(cb => {
cb.checked = false;
cb.indeterminate = false;
});
return;
}
let selectedRowCount = 0;
allRows.forEach(r => {
if (selectedIds.has(r.id)) {
selectedRowCount++;
}
});
const isAllSelected = selectedRowCount === allRows.length;
const isSomeSelected = selectedRowCount > 0 && selectedRowCount < allRows.length;
selectAllCheckboxes.forEach(cb => {
cb.checked = isAllSelected;
cb.indeterminate = isSomeSelected;
});
}
function updateSelectionStatus() {
const el = document.getElementById('unified-selection-status');
if (el) el.textContent = `${selectedIds.size} ${gettext('sélectionné(s)')}`;
@ -3137,10 +3294,11 @@ function updateSelectionStatus() {
if (hiddenInput) hiddenInput.value = Array.from(selectedIds).join(',');
const hiddenLocationsInput = document.getElementById('preventive-selected-locations-ids');
if (hiddenLocationsInput) hiddenLocationsInput.value = Array.from(selectedIds).join(',');
syncSelectAllCheckbox();
}
function buildPreventiveSelectedAssetsPayload() {
const rows = $('#unified-table').bootstrapTable('getData') || [];
const rows = getAllTableRows();
const byId = new Map(rows.filter(r => !r.is_location).map(r => [String(r.id), r]));
const payload = [];

View file

@ -390,8 +390,8 @@
font-size: 0.72rem;
font-weight: 700;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
top: 2px !important;
right: -6px !important;
top: -5px !important;
right: -7px !important;
left: auto !important;
transform: none !important;
min-width: 1.25rem;
@ -479,7 +479,7 @@
font-weight: 600 !important;
text-transform: uppercase !important;
letter-spacing: 0.04em !important;
border-bottom: 1.5px solid #e2e8f0 !important;
border-bottom: 2px solid #cbd5e1 !important;
padding: 0.45rem 0.65rem !important;
vertical-align: middle !important;
white-space: nowrap !important;
@ -494,11 +494,11 @@
/* Rows & Cells */
.bootstrap-table.bootstrap5 #unified-table td {
padding: 0.32rem 0.65rem !important;
padding: 0.35rem 0.65rem !important;
vertical-align: middle !important;
font-size: 0.82rem !important;
color: #334155;
border-bottom: 1px solid #f1f5f9 !important;
border-bottom: 1px solid #e2e8f0 !important;
line-height: 1.3 !important;
}
@ -593,43 +593,157 @@
border-color: #cbd5e1;
}
/* Selection toolbar styling */
#unified-select-all,
#unified-deselect-all {
background-color: #ffffff;
border: 1px solid #e2e8f0;
color: #475569;
border-radius: 6px;
font-size: 0.78rem;
font-weight: 500;
padding: 0.28rem 0.65rem;
/* ─── Controls/Assets Tabs ─────────────────────────────────────────── */
.controls-tabs {
border-bottom: 2px solid #e2e8f0;
}
.controls-tabs .nav-link {
border: none;
border-bottom: 2px solid transparent;
color: #64748b;
font-weight: 600;
font-size: 0.95rem;
padding: 0.5rem 0.75rem;
margin-bottom: -2px;
background: transparent;
transition: all 0.15s ease;
}
#unified-select-all:hover,
#unified-deselect-all:hover {
background-color: #f1f5f9;
.controls-tabs .nav-link:hover {
color: #0f172a;
border-color: #cbd5e1;
border-bottom-color: #cbd5e1;
}
.controls-tabs .nav-link.active {
color: #0f172a;
border-bottom-color: #0f172a;
background: transparent;
}
.controls-tabs .tab-counter-badge {
background-color: #0f172a;
color: #ffffff;
font-size: 0.75rem;
font-weight: 700;
padding: 0.18rem 0.55rem;
border-radius: 9999px;
margin-left: 0.5rem;
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
border: 1px solid #0f172a;
}
/* ─── Assets Toolbar ───────────────────────────────────────────────── */
.assets-toolbar {
padding: 0.25rem 0;
}
.filter-trigger-btn,
#columns-dropdown-btn,
#action-dropdown-btn {
border: 1px solid #cbd5e1;
border-radius: 8px;
font-size: 0.82rem;
font-weight: 500;
padding: 0.32rem 0.75rem;
background-color: #ffffff;
color: #334155;
display: inline-flex;
align-items: center;
gap: 0.4rem;
transition: all 0.15s ease;
text-decoration: none;
}
.filter-trigger-btn:hover,
#columns-dropdown-btn:hover,
#action-dropdown-btn:hover {
background-color: #f8fafc;
border-color: #94a3b8;
color: #0f172a;
}
.btn-new-asset {
background-color: #0f172a;
color: #ffffff !important;
border: 1px solid #0f172a;
border-radius: 8px;
padding: 0.32rem 0.75rem;
font-size: 0.82rem;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.4rem;
transition: all 0.15s ease;
text-decoration: none;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
white-space: nowrap;
}
.btn-new-asset:hover:not(:disabled) {
background-color: #1e293b;
color: #ffffff !important;
border-color: #1e293b;
transform: translateY(-1px);
box-shadow: 0 4px 6px -1px rgba(15, 23, 42, 0.12);
}
.btn-new-asset:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.columns-dropdown-menu {
border-radius: 12px;
border: 1px solid #e2e8f0;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.12), 0 8px 10px -6px rgba(0, 0, 0, 0.08);
min-width: 250px;
z-index: 1060;
}
.columns-checkbox-list {
max-height: 280px;
overflow-y: auto;
}
.columns-checkbox-list .form-check {
margin-bottom: 0.2rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.columns-checkbox-list .form-check-input {
cursor: pointer;
margin-top: 0;
}
.columns-checkbox-list .form-check-label {
cursor: pointer;
font-size: 0.82rem;
}
.page-size-selector {
font-size: 0.82rem;
color: #64748b;
}
.page-size-select {
padding: 0.25rem 0.55rem;
font-size: 0.82rem;
border: 1px solid #cbd5e1;
border-radius: 7px;
background-color: #ffffff;
color: #334155;
cursor: pointer;
font-weight: 500;
}
.page-size-select:focus {
outline: none;
border-color: #2563eb;
}
#unified-selection-status {
font-size: 0.8rem;
color: #64748b;
font-weight: 500;
}
#unified-bulk-action-dropdown .dropdown-toggle {
background-color: #ffffff;
border: 1px solid #e2e8f0;
color: #475569;
border-radius: 6px;
font-size: 0.78rem;
font-weight: 500;
padding: 0.28rem 0.75rem;
}
#unified-bulk-action-dropdown .dropdown-toggle:hover {
background-color: #f1f5f9;
color: #0f172a;
border-color: #cbd5e1;
}
/* Pagination bar styling */
.bootstrap-table.bootstrap5 .fixed-table-pagination {
@ -1074,21 +1188,21 @@
{# ─── Table column ───────────────────────────────────────────────── #}
<div id="col-table" class="col-md-6 d-flex flex-column" style="max-height: calc(100vh - 130px);">
{# Tab nav with + and filter buttons #}
<ul class="nav nav-tabs flex-shrink-0" id="tablesTab" role="tablist">
<!-- Entête d'onglet -->
<ul class="nav nav-tabs controls-tabs flex-shrink-0 mb-2" id="tablesTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" type="button">
<button class="nav-link active" id="assets-table-tab" type="button">
<i class="bi bi-layers me-1"></i>{% translate "Assets" %}
<span class="tab-counter-badge" id="assets-counter-badge">0</span>
</button>
</li>
<div class="my-1 ms-2">
<button class="btn btn-light" type="button" id="btn-add-asset"
title="{% translate 'Ajouter un asset' %}">
<i class="bi bi-plus-circle"></i>
</button>
</div>
<div class="my-1 ms-1">
<button class="btn btn-light position-relative" type="button"
</ul>
<!-- Barre d'outils du tableau : Filtres, Colonnes, Action, Nouvel asset, Statut de sélection, Affichage par page -->
<div class="assets-toolbar d-flex justify-content-between align-items-center flex-wrap gap-2 mb-2">
<div class="d-flex align-items-center flex-wrap gap-2">
<!-- Bouton Filtres avec badge -->
<button class="btn btn-light position-relative filter-trigger-btn" type="button"
data-bs-toggle="modal" data-bs-target="#filterModal"
title="{% translate 'Filtres' %}">
<i class="bi bi-funnel"></i> {% translate "Filtres" %}
@ -1096,53 +1210,90 @@
<span id="filter-count">0</span>
</span>
</button>
<!-- Dropdown Sélecteur de Colonnes -->
<div class="dropdown d-inline-block">
<button type="button" class="btn btn-light dropdown-toggle" id="columns-dropdown-btn" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" title="{% translate 'Choisir les colonnes à afficher' %}">
<i class="bi bi-layout-three-columns me-1"></i>{% translate "Colonnes" %}
</button>
<div class="dropdown-menu shadow-sm py-2 px-3 columns-dropdown-menu" aria-labelledby="columns-dropdown-btn">
<div class="d-flex justify-content-between align-items-center mb-2 pb-1 border-bottom">
<span class="fw-semibold text-dark small">{% translate "Colonnes" %}</span>
<div class="d-flex gap-1">
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none text-primary small" id="cols-select-all">{% translate "Toutes" %}</button>
<span class="text-muted small">·</span>
<button type="button" class="btn btn-link btn-sm p-0 text-decoration-none text-muted small" id="cols-reset-default">{% translate "Défaut" %}</button>
</div>
</div>
<div id="columns-list-container" class="columns-checkbox-list">
<!-- Injecté dynamiquement par JavaScript -->
</div>
</div>
</div>
<!-- Dropdown Action (remplace Excel) -->
{% if not preventive_draft_id %}
<div class="dropdown d-inline-block" id="unified-bulk-action-dropdown">
<button class="btn btn-light dropdown-toggle" id="action-dropdown-btn" type="button" data-bs-toggle="dropdown" aria-expanded="false" title="{% translate 'Actions sur les assets sélectionnés' %}">
<i class="bi bi-gear me-1"></i>{% translate "Action" %}
</button>
<ul class="dropdown-menu shadow-sm py-2">
<li>
<a class="dropdown-item" href="#" id="unified-action-export"
data-bs-toggle="modal" data-bs-target="#unifiedExportModal">
<i class="bi bi-download me-2"></i>{% translate "Exporter" %}
</a>
</li>
{% if has_bulk_edit_status_permission %}
<li>
<a class="dropdown-item" href="#" id="unified-action-bulk-status"
data-bs-toggle="modal" data-bs-target="#bulkStatusModal">
<i class="bi bi-pencil-square me-2"></i>{% translate "Modifier le statut en masse" %}
</a>
</li>
{% endif %}
{% if has_bulk_edit_validation_status_permission %}
<li>
<a class="dropdown-item" href="#" id="unified-action-bulk-validation-status"
data-bs-toggle="modal" data-bs-target="#bulkValidationStatusModal">
<i class="bi bi-shield-check me-2"></i>{% translate "Modifier le statut de validation en masse" %}
</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}
<!-- Bouton Nouvel Asset -->
<button class="btn btn-new-asset" type="button" id="btn-add-asset" title="{% translate 'Ajouter un asset' %}">
<i class="bi bi-plus-lg me-1"></i>
<span>{% translate "Nouvel asset" %}</span>
</button>
<!-- Statut sélection -->
<span id="unified-selection-status" class="text-muted small ms-1 mb-0">0 {% translate "sélectionné(s)" %}</span>
{% if preventive_draft_id %}
<button type="submit" class="btn btn-success btn-sm ms-2" form="preventive-select-form">{% translate "Valider la sélection" %}</button>
{% endif %}
</div>
</ul>
<div class="d-flex align-items-center gap-2">
<div class="page-size-selector d-flex align-items-center gap-1">
<label for="page-size-select" class="small text-muted mb-0 d-none d-sm-inline">{% translate "Afficher par" %}</label>
<select id="page-size-select" class="form-select form-select-sm page-size-select">
<option value="25">25</option>
<option value="50">50</option>
<option value="100" selected>100</option>
<option value="200">200</option>
</select>
</div>
</div>
</div>
{# Tab content #}
<div class="tab-content d-flex flex-column" style="flex: 1; min-height: 0;">
<div class="tab-pane fade show active d-flex flex-column" style="flex: 1; min-height: 0; padding-top: 0.5rem;">
{# Selection toolbar #}
<div class="d-flex gap-2 flex-wrap align-items-center mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary" id="unified-select-all">{% translate "Tout sélectionner" %}</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="unified-deselect-all">{% translate "Tout désélectionner" %}</button>
{% if preventive_draft_id %}
<button type="submit" class="btn btn-success btn-sm" form="preventive-select-form">{% translate "Valider la sélection" %}</button>
{% endif %}
<div id="unified-selection-status" class="text-muted small mb-0">0 {% translate "sélectionné(s)" %}</div>
{% if not preventive_draft_id %}
<div class="dropdown ms-auto" id="unified-bulk-action-dropdown">
<button class="btn btn-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
{% translate "Action" %}
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item" href="#" id="unified-action-export"
data-bs-toggle="modal" data-bs-target="#unifiedExportModal">
<i class="bi bi-download me-2"></i>{% translate "Exporter" %}
</a>
</li>
{% if has_bulk_edit_status_permission %}
<li>
<a class="dropdown-item" href="#" id="unified-action-bulk-status"
data-bs-toggle="modal" data-bs-target="#bulkStatusModal">
<i class="bi bi-pencil-square me-2"></i>{% translate "Modifier le statut en masse" %}
</a>
</li>
{% endif %}
{% if has_bulk_edit_validation_status_permission %}
<li>
<a class="dropdown-item" href="#" id="unified-action-bulk-validation-status"
data-bs-toggle="modal" data-bs-target="#bulkValidationStatusModal">
<i class="bi bi-shield-check me-2"></i>{% translate "Modifier le statut de validation en masse" %}
</a>
</li>
{% endif %}
</ul>
</div>
{% endif %}
</div>
<div class="tab-pane fade show active d-flex flex-column" style="flex: 1; min-height: 0;">
{# Table area: spinner overlay + empty state + table #}
<div style="position: relative;">
@ -1165,8 +1316,9 @@
class="table table-hover table-sm"
data-pagination="true"
data-page-size="100"
data-maintain-meta-data="true"
data-click-to-select="true"
data-show-columns="true"
data-show-columns="false"
data-search="false">
</table>

View file

@ -67,7 +67,7 @@ class ImportFulcrumTreesCommandTest(TestCase):
"ges_conduite": "LI",
"cf_sit": 4.5,
"arb_anpla": "1995",
"maj_date": "2024-05-10T00:00:00.000Z"
"maj_date": "2026-05-10T00:00:00.000Z"
}
}
]
@ -96,8 +96,8 @@ class ImportFulcrumTreesCommandTest(TestCase):
"sit_id": "099.01",
"pos_id": "001",
"dia_comma": "BC-TEST-001",
"dia_date": "2024-05-10T00:00:00.000Z",
"in_deadline": "2025-05-10T00:00:00.000Z",
"dia_date": "2026-05-10T00:00:00.000Z",
"in_deadline": "2027-05-10T00:00:00.000Z",
"rec_delai": "Pla-1",
"rec_interv": "FO",
"in_fin_yn": "no",
@ -149,23 +149,23 @@ class ImportFulcrumTreesCommandTest(TestCase):
self.assertEqual(itv.priority, "3") # Pla-1 -> 3
self.assertEqual(itv.status, "to_be_planned")
self.assertIsNotNone(itv.expected_begin_time)
self.assertEqual(itv.expected_begin_time.date(), date(2024, 5, 10))
self.assertEqual(itv.expected_begin_time.date(), date(2026, 5, 10))
self.assertIsNotNone(itv.expected_end_time)
self.assertEqual(itv.expected_end_time.date(), date(2025, 5, 10))
self.assertEqual(itv.expected_end_time.date(), date(2027, 5, 10))
# Vérifications dates de maintenance sur l'arbre
self.assertEqual(tree.last_phytosanitary_date, date(2024, 5, 10))
self.assertEqual(tree.next_inspection_date, date(2025, 5, 10))
self.assertEqual(tree.last_phytosanitary_date, date(2026, 5, 10))
self.assertEqual(tree.next_inspection_date, date(2027, 5, 10))
self.assertEqual(tree.pruning_frequency_years, 1)
# Vérifications événements de planification (timeline)
self.assertEqual(itv.planned_events.count(), 2)
begin_event = itv.planned_events.filter(event_type='expected_begin').first()
self.assertIsNotNone(begin_event)
self.assertEqual(begin_event.event_time.date(), date(2024, 5, 10))
self.assertEqual(begin_event.event_time.date(), date(2026, 5, 10))
end_event = itv.planned_events.filter(event_type='expected_end').first()
self.assertIsNotNone(end_event)
self.assertEqual(end_event.event_time.date(), date(2025, 5, 10))
self.assertEqual(end_event.event_time.date(), date(2027, 5, 10))
# Vérification liaison InterventionAsset
links = InterventionAsset.objects.filter(intervention=itv)