Add spreadsheet-style home page, migrate full 2026 ledger
- New /lignes route (set as site front page): full line-by-line table of every ligne comptable, Vue app with filters (compte/client/type/année) and month/year grouping, columns matching the original spreadsheet (one per compte). Rows with répartition ≠ montant HT are visibly flagged (red row + écart column), not hidden or auto-corrected. - /dashboard now only holds the aggregate solde-par-compte/par-client view - Migrated all 199 real 2026 transaction lines + 9 opening balances (from REPORT CLOTURE 2025) via a drush import script, preserving raw source data (known répartition mismatches included) -- validated with a new state-flag bypass of the presave check, used only for historical import - Added "Autre" as an allowed field_type_ligne value for edge-case rows - Client taxonomy grew from 15 seeded terms to the full unified list Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
{#
|
||||
Dashboard shell: Drupal renders the page (nav, auth, permissions).
|
||||
dashboard.js (Vue 3) fetches JSON:API and renders a spreadsheet-like table
|
||||
of every ligne comptable, with filters and month/year grouping, client-side.
|
||||
"Ajouter une ligne" opens the real Drupal node form in a modal
|
||||
(core/drupal.dialog.ajax) -- no form logic duplicated in JS.
|
||||
#}
|
||||
{% verbatim %}
|
||||
<div id="figli-home-app">
|
||||
<div class="figli-toolbar">
|
||||
<a href="/node/add/ligne_comptable" class="button button--primary" @click.prevent="openAddForm">+ Ajouter une ligne</a>
|
||||
|
||||
<label>Compte
|
||||
<select v-model="filterCompte">
|
||||
<option value="">Tous</option>
|
||||
<option v-for="c in allComptes" :key="c" :value="c">{{ c }}</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Client
|
||||
<select v-model="filterClient">
|
||||
<option value="">Tous</option>
|
||||
<option v-for="c in allClients" :key="c" :value="c">{{ c }}</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Type
|
||||
<select v-model="filterType">
|
||||
<option value="">Tous</option>
|
||||
<option v-for="t in allTypes" :key="t.value" :value="t.value">{{ t.label }}</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Année
|
||||
<select v-model="filterYear">
|
||||
<option value="">Toutes</option>
|
||||
<option v-for="y in allYears" :key="y" :value="y">{{ y }}</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Regrouper par
|
||||
<select v-model="groupBy">
|
||||
<option value="none">Aucun</option>
|
||||
<option value="month">Mois</option>
|
||||
<option value="year">Année</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label class="figli-checkbox">
|
||||
<input type="checkbox" v-model="onlyErrors" /> Écarts uniquement
|
||||
</label>
|
||||
|
||||
<span class="figli-count" v-if="!loading">{{ filteredRows.length }} / {{ rows.length }} lignes{{ errorCount ? ' — ' + errorCount + ' avec écart' : '' }}</span>
|
||||
</div>
|
||||
|
||||
<p v-if="loading">Chargement des données…</p>
|
||||
<p v-else-if="error" class="figli-error">Erreur de chargement : {{ error }}</p>
|
||||
<div v-else class="figli-table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Client</th>
|
||||
<th>Type</th>
|
||||
<th>Libellé / Détail</th>
|
||||
<th class="amount">Montant HT</th>
|
||||
<th class="amount">Montant TTC</th>
|
||||
<th v-for="c in allComptes" :key="c" class="amount compte-col">{{ c }}</th>
|
||||
<th class="amount">Écart</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="item in groupedRows" :key="item.key">
|
||||
<tr v-if="item.isGroup" class="figli-group-row">
|
||||
<td :colspan="6 + allComptes.length + 1">{{ item.label }} <span class="figli-note">({{ item.count }} lignes)</span></td>
|
||||
</tr>
|
||||
<tr v-else :class="{'figli-error-row': item.hasError}">
|
||||
<td>{{ item.date }}</td>
|
||||
<td>{{ item.client || '—' }}</td>
|
||||
<td><span class="figli-badge" :class="'type-' + item.type">{{ typeLabel(item.type) }}</span></td>
|
||||
<td class="figli-libelle">{{ item.libelle }}</td>
|
||||
<td class="amount">{{ formatEur(item.montant_ht) }}</td>
|
||||
<td class="amount">{{ formatEur(item.montant_ttc) }}</td>
|
||||
<td v-for="c in allComptes" :key="c" class="amount compte-col">{{ item.parCompte[c] !== undefined ? formatEur(item.parCompte[c]) : '' }}</td>
|
||||
<td class="amount" :class="{'figli-ecart': item.hasError}">{{ item.hasError ? formatEur(item.ecart) : '' }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endverbatim %}
|
||||
Reference in New Issue
Block a user