Plugin Directory

Changeset 3803495


Ignore:
Timestamp:
11/15/2026 03:31:43 PM (5 hours ago)
Author:
tulipwork
Message:

Update to version 2.7.1 from GitHub

Location:
ultimate-business-dashboard
Files:
20 edited
1 copied

Legend:

Unmodified
Added
Removed
  • ultimate-business-dashboard/tags/2.7.1/assets/css/admin.css

    r3803022 r3803495  
    841841.card-empty { margin: 0; color: var(--ubd-grey); font-style: italic; }
    842842.card-actions { align-items: center; gap: 6px; flex-wrap: wrap; }
    843 .card-actions .button .dashicons { font-size: 16px; width: 16px; height: 16px; vertical-align: middle; margin: -3px 2px 0 0; }
    844843.ultibuda-icon-button.button { padding: 0 6px; color: var(--ubd-grey); }
    845844.ultibuda-icon-button.button:hover,
    846845.ultibuda-icon-button.button:focus { color: var(--ubd-blue); }
    847 .ultibuda-icon-button .dashicons { margin-right: 0 !important; }
    848846.ultibuda-inline-form { display: inline; margin: 0; }
    849847
    … …  
    896894.ultibuda-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
    897895.ultibuda-break-even { margin: 12px 0 0; color: var(--ubd-grey); }
    898 .print-report-btn .dashicons { vertical-align: middle; margin-top: -3px; }
    899896@media (max-width: 1100px) {
    900897    .ultibuda-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    … …  
    10231020.ultibuda-code-input { width: 100px; }
    10241021.ultibuda-categories-table select { max-width: 100%; }
     1022
     1023/* 2.7.1 : icônes centrées dans les boutons, quelle que soit la taille du texte */
     1024.card-actions .button,
     1025.print-report-btn.button {
     1026    display: inline-flex;
     1027    align-items: center;
     1028    justify-content: center;
     1029    gap: 4px;
     1030}
     1031.card-actions .button .dashicons,
     1032.print-report-btn .dashicons {
     1033    font-size: 16px;
     1034    width: 16px;
     1035    height: 16px;
     1036    line-height: 1;
     1037    margin: 0;
     1038    vertical-align: baseline;
     1039}
     1040
     1041/* 2.7.1 : page Factures, catégorie lisible et type compact */
     1042.ultibuda-invoices-table .column-supplier { width: 24%; }
     1043.ultibuda-invoices-table .column-category { width: 28%; }
     1044.ultibuda-invoices-table .column-category select { width: 100%; min-width: 200px; max-width: none; }
     1045.ultibuda-invoices-table .ultibuda-select-small { width: auto; max-width: 140px; min-width: 0; }
     1046.ultibuda-invoices-table .column-input { width: 96px; }
     1047.ultibuda-invoices-table .column-input input { max-width: 96px; }
     1048
     1049/* 2.7.1 : doublons probables en colonnes alignées */
     1050.ultibuda-dup-line { display: grid; grid-template-columns: 150px 100px 100px minmax(0, 1fr) auto; align-items: center; gap: 4px 12px; padding: 3px 0; }
     1051.ultibuda-dup-line .num { text-align: right; font-variant-numeric: tabular-nums; }
     1052.ultibuda-dup-line > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
     1053@media (max-width: 782px) { .ultibuda-dup-line { grid-template-columns: minmax(0, 1fr) auto; } .ultibuda-dup-line > span:nth-child(4) { display: none; } }
  • ultimate-business-dashboard/tags/2.7.1/assets/js/admin.js

    r3803022 r3803495  
    334334                            { type: 'bar', label: d.revenueLabel, data: d.revenue, backgroundColor: 'rgba(34, 113, 177, 0.75)', borderRadius: 3, order: 3 },
    335335                            { type: 'line', label: d.revenuePrevLabel, data: d.revenuePrev, borderColor: '#8c8f94', borderDash: [6, 4], pointRadius: 0, borderWidth: 2, order: 2 },
    336                             { type: 'line', label: d.ebeLabel, data: d.ebe, borderColor: '#00a32a', backgroundColor: '#00a32a', tension: 0.25, borderWidth: 2, order: 1 },
    337                             { type: 'line', label: d.resultLabel, data: d.result, borderColor: '#d63638', backgroundColor: '#d63638', tension: 0.25, borderWidth: 2, order: 0 }
     336                            { type: 'line', label: d.ebeLabel, data: d.ebe, borderColor: '#00a32a', backgroundColor: '#00a32a', tension: 0.25, borderWidth: 4, pointRadius: 4, order: 0 },
     337                            { type: 'line', label: d.resultLabel, data: d.result, borderColor: '#d63638', backgroundColor: '#d63638', tension: 0.25, borderWidth: 2, borderDash: [5, 4], pointRadius: 3, pointStyle: 'rectRot', order: 1 }
    338338                        ]
    339339                    },
  • ultimate-business-dashboard/tags/2.7.1/includes/format.php

    r3802991 r3803495  
    4545    return [
    4646        'symbol' => $symbol !== '' ? $symbol : $default['symbol'],
    47         'position' => in_array($position, ['before', 'after'], true) ? $position : $default['position'],
     47        // Position automatique : celle de la langue de l'utilisateur, comme le format des nombres
     48        // (« 100 € » en français, « €100 » en anglais), quelle que soit la langue du site.
     49        'position' => in_array($position, ['before', 'after'], true) ? $position : ultibuda_locale_currency_position(get_user_locale()),
    4850    ];
     51}
     52
     53/**
     54 * Place habituelle du symbole monétaire dans une langue.
     55 *
     56 * @param string $locale Langue (ex. fr_FR, en_US).
     57 * @return string before|after
     58 */
     59function ultibuda_locale_currency_position($locale) {
     60    foreach (['en', 'nl', 'ja', 'zh', 'ko', 'he', 'pt_BR', 'es_MX', 'es_AR', 'es_CO', 'es_CL', 'th', 'ms', 'id'] as $prefix) {
     61        if (strpos((string) $locale, $prefix) === 0) {
     62            return 'before';
     63        }
     64    }
     65    return 'after';
    4966}
    5067
    … …  
    123140        return '<span class="variation neutral" title="' . esc_attr__('No comparison available', 'ultimate-business-dashboard') . '">–</span>';
    124141    }
     142    if (is_numeric($var) && abs((float) $var) >= 1000) {
     143        // Base de comparaison presque nulle : le pourcentage n'a pas de sens
     144        return '<span class="variation neutral" title="' . esc_attr__('Variation too large to be meaningful (very small comparison base)', 'ultimate-business-dashboard') . '">' . esc_html__('n/m', 'ultimate-business-dashboard') . '</span>';
     145    }
    125146    if ($var === 'NM') {
    126147        return '<span class="variation neutral" title="' . esc_attr__('Variation not meaningful (transition from loss to profit or vice versa)', 'ultimate-business-dashboard') . '">' . esc_html__('n/m', 'ultimate-business-dashboard') . '</span>';
  • ultimate-business-dashboard/tags/2.7.1/includes/invoice-store.php

    r3803022 r3803495  
    640640
    641641/**
     642 * Date d'ajout de la facture la plus récente (toutes sources), en horodatage, ou 0.
     643 *
     644 * @return int
     645 */
     646function ultibuda_last_invoice_added_time() {
     647    if (!ultibuda_invoices_store_ready()) {
     648        return 0;
     649    }
     650    global $wpdb;
     651    $table = ultibuda_invoices_table();
     652    $last = $wpdb->get_var("SELECT MAX(created_at) FROM $table"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     653    return $last ? (int) strtotime($last . ' UTC') : 0;
     654}
     655
     656/**
    642657 * Nombre de factures par catégorie.
    643658 *
  • ultimate-business-dashboard/tags/2.7.1/includes/quality.php

    r3802991 r3803495  
    4040 * Alertes ignorées.
    4141 *
    42  * @return array{duplicates: string[], suppliers: string[], amounts: string[]}
     42 * @return array{duplicates: string[], suppliers: string[], amounts: string[], shared_numbers: string[]}
    4343 */
    4444function ultibuda_quality_ignored() {
    4545    $ignored = get_option('ultibuda_quality_ignored', []);
    4646    $ignored = is_array($ignored) ? $ignored : [];
    47     foreach (['duplicates', 'suppliers', 'amounts'] as $key) {
     47    foreach (['duplicates', 'suppliers', 'amounts', 'shared_numbers'] as $key) {
    4848        $ignored[$key] = isset($ignored[$key]) && is_array($ignored[$key]) ? $ignored[$key] : [];
    4949    }
    … …  
    5454 * Ignore une alerte.
    5555 *
    56  * @param string $type duplicates|suppliers|amounts.
     56 * @param string $type duplicates|suppliers|amounts|shared_numbers.
    5757 * @param string $key  Clé de l'alerte.
    5858 */
    … …  
    9494
    9595    foreach ($by_supplier as $supplier_invoices) {
    96         // Même numéro de facture chez le même fournisseur
     96        // Même numéro de facture et même montant chez le même fournisseur (un même numéro avec des
     97        // montants différents désigne en général deux documents distincts, ex. relevés Deliveroo)
    9798        $by_number = [];
    9899        foreach ($supplier_invoices as $invoice) {
    99100            $number = strtolower(trim((string) ($invoice['invoice_number'] ?? '')));
    100101            if ($number !== '' && $number !== 'n/a') {
    101                 $by_number[$number][] = $invoice;
     102                $by_number[$number . '|' . number_format((float) ($invoice['total_amount'] ?? 0), 2, '.', '')][] = $invoice;
    102103            }
    103104        }
    … …  
    139140
    140141/**
     142 * Numéros de facture partagés par plusieurs documents de montants différents, regroupés par fournisseur.
     143 *
     144 * Ce n'est pas un doublon (acomptes, avoirs, relevés), mais un relevé de paiement importé à côté
     145 * de la facture qu'il règle compterait deux fois en charge : on le signale à part, une ligne par fournisseur.
     146 *
     147 * @param array[] $invoices Factures.
     148 * @return array[] Liste de ['key' => string, 'supplier' => string, 'numbers' => int, 'invoices' => int, 'example' => string].
     149 */
     150function ultibuda_quality_shared_numbers($invoices) {
     151    $ignored = ultibuda_quality_ignored()['shared_numbers'];
     152    $groups = [];
     153    foreach ($invoices as $invoice) {
     154        $supplier = ultibuda_normalize_supplier($invoice['supplier'] ?? '');
     155        $number = strtolower(trim((string) ($invoice['invoice_number'] ?? '')));
     156        if ($supplier === '' || $supplier === 'unknown' || $number === '' || $number === 'n/a' || in_array($supplier, $ignored, true)) {
     157            continue;
     158        }
     159        $groups[$supplier]['name'] = $groups[$supplier]['name'] ?? (string) $invoice['supplier'];
     160        $groups[$supplier]['numbers'][$number]['label'] = (string) $invoice['invoice_number'];
     161        $groups[$supplier]['numbers'][$number]['amounts'][number_format((float) ($invoice['total_amount'] ?? 0), 2, '.', '')] = true;
     162        $groups[$supplier]['numbers'][$number]['count'] = ($groups[$supplier]['numbers'][$number]['count'] ?? 0) + 1;
     163    }
     164    $result = [];
     165    foreach ($groups as $supplier => $group) {
     166        $shared = array_filter($group['numbers'], function ($entry) {
     167            return count($entry['amounts']) > 1;
     168        });
     169        if (!$shared) {
     170            continue;
     171        }
     172        $first = reset($shared);
     173        $result[] = [
     174            'key' => $supplier,
     175            'supplier' => $group['name'],
     176            'numbers' => count($shared),
     177            'invoices' => array_sum(array_column($shared, 'count')),
     178            'example' => $first['label'],
     179        ];
     180    }
     181    usort($result, function ($a, $b) {
     182        return $b['numbers'] - $a['numbers'];
     183    });
     184    return $result;
     185}
     186
     187/**
    141188 * Factures non catégorisées (ou rattachées à une catégorie supprimée).
    142189 *
    … …  
    288335function ultibuda_quality_issue_count($invoices) {
    289336    return count(ultibuda_quality_duplicates($invoices))
     337        + count(ultibuda_quality_shared_numbers($invoices))
    290338        + ultibuda_quality_uncategorized_count($invoices)
    291339        + count(ultibuda_quality_supplier_groups($invoices))
    … …  
    367415                $message = __('Invoice deleted.', 'ultimate-business-dashboard');
    368416            }
    369         } elseif (in_array($action, ['ignore_duplicate', 'ignore_suppliers', 'ignore_amount'], true) && $key !== '') {
    370             $types = ['ignore_duplicate' => 'duplicates', 'ignore_suppliers' => 'suppliers', 'ignore_amount' => 'amounts'];
     417        } elseif (in_array($action, ['ignore_duplicate', 'ignore_suppliers', 'ignore_amount', 'ignore_shared_number'], true) && $key !== '') {
     418            $types = ['ignore_duplicate' => 'duplicates', 'ignore_suppliers' => 'suppliers', 'ignore_amount' => 'amounts', 'ignore_shared_number' => 'shared_numbers'];
    371419            ultibuda_quality_ignore($types[$action], $key);
    372420            $message = __('Alert ignored.', 'ultimate-business-dashboard');
    … …  
    384432    $invoices = ultibuda_get_invoices();
    385433    $duplicates = ultibuda_quality_duplicates($invoices);
     434    $shared_numbers = ultibuda_quality_shared_numbers($invoices);
    386435    $uncategorized = ultibuda_quality_uncategorized_count($invoices);
    387436    $supplier_groups = ultibuda_quality_supplier_groups($invoices);
    … …  
    422471                <?php
    423472                /* translators: %d: number of days */
    424                 echo esc_html(sprintf(__('Same supplier with the same invoice number, or with the same total amount less than %d days apart.', 'ultimate-business-dashboard'), ULTIBUDA_DUPLICATE_DAYS));
     473                echo esc_html(sprintf(__('Same supplier with the same invoice number and amount, or with the same total amount less than %d days apart.', 'ultimate-business-dashboard'), ULTIBUDA_DUPLICATE_DAYS));
    425474                ?>
    426475            </p>
    … …  
    438487                            <td><?php echo esc_html($pair['invoices'][0]['supplier']); ?></td>
    439488                            <td>
    440                                 <?php foreach ($pair['invoices'] as $invoice) : ?>
    441                                     <div>
    442                                         <?php echo wp_kses_post(ultibuda_quality_document_link($invoice)); ?>
    443                                         — <?php echo esc_html($invoice['date']); ?>
    444                                         — <?php echo esc_html($money($invoice['total_amount'])); ?>
    445                                         <?php if (!empty($invoice['invoice_number']) && $invoice['invoice_number'] !== 'N/A') : ?>
    446                                             — <?php echo esc_html($invoice['invoice_number']); ?>
    447                                         <?php endif; ?>
    448                                         <?php $action_button('delete_invoice', $invoice['id'], __('Delete this one', 'ultimate-business-dashboard'), __('Delete this invoice? This cannot be undone.', 'ultimate-business-dashboard')); ?>
     489                                <?php foreach ($pair['invoices'] as $invoice) :
     490                                    $time = strtotime((string) $invoice['date']);
     491                                    ?>
     492                                    <div class="ultibuda-dup-line">
     493                                        <span><?php echo wp_kses_post(ultibuda_quality_document_link($invoice)); ?></span>
     494                                        <span><?php echo esc_html($time ? date_i18n('j M Y', $time) : $invoice['date']); ?></span>
     495                                        <span class="num"><?php echo esc_html($money($invoice['total_amount'])); ?></span>
     496                                        <span class="ultibuda-muted"><?php echo esc_html((!empty($invoice['invoice_number']) && $invoice['invoice_number'] !== 'N/A') ? $invoice['invoice_number'] : '–'); ?></span>
     497                                        <span><?php $action_button('delete_invoice', $invoice['id'], __('Delete this one', 'ultimate-business-dashboard'), __('Delete this invoice? This cannot be undone.', 'ultimate-business-dashboard')); ?></span>
    449498                                    </div>
    450499                                <?php endforeach; ?>
    451500                            </td>
    452                             <td><?php echo $pair['reason'] === 'number' ? esc_html__('Same invoice number', 'ultimate-business-dashboard') : esc_html__('Same amount, close dates', 'ultimate-business-dashboard'); ?></td>
     501                            <td><?php echo $pair['reason'] === 'number' ? esc_html__('Same invoice number and amount', 'ultimate-business-dashboard') : esc_html__('Same amount, close dates', 'ultimate-business-dashboard'); ?></td>
    453502                            <td><?php $action_button('ignore_duplicate', $pair['key'], __('Not a duplicate', 'ultimate-business-dashboard')); ?></td>
    454503                        </tr>
    … …  
    465514                </p>
    466515            <?php endif; ?>
     516        <?php endif; ?>
     517
     518        <?php if ($shared_numbers) : ?>
     519            <h2>
     520                <?php
     521                /* translators: %d: number of suppliers */
     522                echo esc_html(sprintf(__('Same number, different amounts (%d)', 'ultimate-business-dashboard'), count($shared_numbers)));
     523                ?>
     524            </h2>
     525            <p class="description"><?php esc_html_e('Several documents of these suppliers share the same number with different amounts. It is often normal (instalments, credit notes), but a payment statement imported next to the invoice it settles is counted twice as an expense: open an example and check that each document is a real invoice.', 'ultimate-business-dashboard'); ?></p>
     526            <div class="ultibuda-quality-table-wrap">
     527                <table class="widefat striped">
     528                    <thead><tr>
     529                        <th><?php esc_html_e('Supplier', 'ultimate-business-dashboard'); ?></th>
     530                        <th><?php esc_html_e('Numbers concerned', 'ultimate-business-dashboard'); ?></th>
     531                        <th><?php esc_html_e('Example', 'ultimate-business-dashboard'); ?></th>
     532                        <th><?php esc_html_e('Actions', 'ultimate-business-dashboard'); ?></th>
     533                    </tr></thead>
     534                    <tbody>
     535                    <?php foreach ($shared_numbers as $entry) : ?>
     536                        <tr>
     537                            <td><?php echo esc_html($entry['supplier']); ?></td>
     538                            <td>
     539                                <?php
     540                                /* translators: 1: number of invoice numbers, 2: number of invoices */
     541                                echo esc_html(sprintf(_n('%1$s number (%2$s invoices)', '%1$s numbers (%2$s invoices)', $entry['numbers'], 'ultimate-business-dashboard'), ultibuda_number($entry['numbers'], 0), ultibuda_number($entry['invoices'], 0)));
     542                                ?>
     543                            </td>
     544                            <td><a href="<?php echo esc_url(add_query_arg(['page' => 'ultibuda-invoices', 's' => $entry['example']], admin_url('admin.php'))); ?>"><?php echo esc_html($entry['example']); ?></a></td>
     545                            <td>
     546                                <a class="button button-small" href="<?php echo esc_url(add_query_arg(['page' => 'ultibuda-invoices', 's' => $entry['supplier']], admin_url('admin.php'))); ?>"><?php esc_html_e('See the invoices', 'ultimate-business-dashboard'); ?></a>
     547                                <?php $action_button('ignore_shared_number', $entry['key'], __('This is normal', 'ultimate-business-dashboard')); ?>
     548                            </td>
     549                        </tr>
     550                    <?php endforeach; ?>
     551                    </tbody>
     552                </table>
     553            </div>
    467554        <?php endif; ?>
    468555
  • ultimate-business-dashboard/tags/2.7.1/languages/ultimate-business-dashboard-fr_FR.po

    r3803022 r3803495  
    44"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ultimate-business-"
    55"dashboard\n"
    6 "POT-Creation-Date: 2026-11-15T09:59:02+00:00\n"
     6"POT-Creation-Date: 2026-11-15T15:30:11+00:00\n"
    77"PO-Revision-Date: 2025-11-22 17:17+0100\n"
    88"Last-Translator: \n"
    … …  
    7777#: includes/categories.php:17 includes/dashboard.php:263 includes/data.php:16
    7878#: includes/imports.php:451 includes/imports.php:535 includes/invoices.php:133
    79 #: includes/quality.php:358 includes/quickbooks.php:25
     79#: includes/quality.php:406 includes/quickbooks.php:25
    8080#: includes/quickbooks.php:511 includes/reports.php:17 includes/settings.php:44
    8181#: includes/user-management.php:17 includes/zapier.php:17
    … …  
    159159"Categories are created from your imports (Dext, CSV, QuickBooks). For each "
    160160"one, choose how it is counted in your results."
    161 msgstr "Les catégories sont créées à partir de vos imports (Dext, CSV, QuickBooks). Pour chacune, choisissez comment elle compte dans vos résultats."
     161msgstr ""
     162"Les catégories sont créées à partir de vos imports (Dext, CSV, QuickBooks). "
     163"Pour chacune, choisissez comment elle compte dans vos résultats."
    162164
    163165#: includes/categories.php:209
    … …  
    175177"of goods sold, adjusted by inventory), occupancy costs (rent, energy…), "
    176178"other operating expenses, or exceptional expenses (excluded from the EBE)."
    177 msgstr "la ligne du compte de résultat où apparaissent les factures : achats de marchandises (coût des marchandises vendues, corrigé du stock), coûts d’occupation (loyer, énergie…), autres charges d’exploitation, ou charges exceptionnelles (hors EBE)."
     179msgstr ""
     180"la ligne du compte de résultat où apparaissent les factures : achats de "
     181"marchandises (coût des marchandises vendues, corrigé du stock), coûts "
     182"d’occupation (loyer, énergie…), autres charges d’exploitation, ou charges "
     183"exceptionnelles (hors EBE)."
    178184
    179185#: includes/categories.php:212 includes/categories.php:247
    … …  
    187193"fixed or variable cost, used for the contribution margin and the break-even "
    188194"point. Purchases of goods are always variable."
    189 msgstr "coût fixe ou variable, utilisé pour la marge sur coûts variables et le point mort. Les achats de marchandises sont toujours variables."
     195msgstr ""
     196"coût fixe ou variable, utilisé pour la marge sur coûts variables et le point "
     197"mort. Les achats de marchandises sont toujours variables."
    190198
    191199#: includes/categories.php:213 includes/categories.php:245
    … …  
    207215"The Uncategorized category is the default for unassigned invoices and cannot "
    208216"be deleted."
    209 msgstr "La catégorie Non classé reçoit les factures sans catégorie et ne peut pas être supprimée."
     217msgstr ""
     218"La catégorie Non classé reçoit les factures sans catégorie et ne peut pas "
     219"être supprimée."
    210220
    211221#: includes/categories.php:223 includes/categories.php:294
    … …  
    257267
    258268#: includes/categories.php:244 includes/invoices.php:436
    259 #: includes/quality.php:431 ultimate-business-dashboard.php:138
     269#: includes/quality.php:480 ultimate-business-dashboard.php:138
    260270msgid "Invoices"
    261271msgstr "Factures"
    … …  
    699709"Monthly amounts that do not come from invoices, excluding VAT. They feed the "
    700710"Dashboard and the Ratios & Reports."
    701 msgstr "Montants mensuels qui ne viennent pas des factures, hors TVA. Ils alimentent le tableau de bord et les Ratios et Rapports."
     711msgstr ""
     712"Montants mensuels qui ne viennent pas des factures, hors TVA. Ils alimentent "
     713"le tableau de bord et les Ratios et Rapports."
    702714
    703715#: includes/data.php:136
    … …  
    823835
    824836#. translators: %s: number. Percentage format; French uses a non-breaking space before the % sign.
    825 #: includes/format.php:93
     837#: includes/format.php:110
    826838msgctxt "percentage"
    827839msgid "%s%%"
    828840msgstr "%s %%"
    829841
    830 #: includes/format.php:123
     842#: includes/format.php:140
    831843msgid "No comparison available"
    832844msgstr "Pas de comparaison possible"
    833845
    834 #: includes/format.php:126 ultimate-business-dashboard.php:352
     846#: includes/format.php:144
     847msgid "Variation too large to be meaningful (very small comparison base)"
     848msgstr ""
     849"Variation trop forte pour être significative (base de comparaison très "
     850"faible)"
     851
     852#: includes/format.php:144 includes/format.php:147
     853msgid "n/m"
     854msgstr "n.s."
     855
     856#: includes/format.php:147 ultimate-business-dashboard.php:352
    835857msgid "Variation not meaningful (transition from loss to profit or vice versa)"
    836858msgstr ""
    837859"Variation non significative (transition d’une perte à un bénéfice ou vice "
    838860"versa)"
    839 
    840 #: includes/format.php:126
    841 msgid "n/m"
    842 msgstr "n.s."
    843861
    844862#: includes/import-header.php:12 ultimate-business-dashboard.php:142
    … …  
    850868msgstr "Vue d’ensemble"
    851869
    852 #: includes/import-tabs.php:13 ultimate-business-dashboard.php:532
     870#: includes/import-tabs.php:13 ultimate-business-dashboard.php:537
    853871msgid "Dext & Zapier"
    854872msgstr "Dext & Zapier"
    855873
    856 #: includes/import-tabs.php:14 ultimate-business-dashboard.php:533
     874#: includes/import-tabs.php:14 ultimate-business-dashboard.php:538
    857875msgid "Dext CSV"
    858876msgstr "CSV Dext"
    859877
    860 #: includes/import-tabs.php:15 ultimate-business-dashboard.php:534
     878#: includes/import-tabs.php:15 ultimate-business-dashboard.php:539
    861879msgid "Other CSV"
    862880msgstr "Autre CSV"
    863881
    864 #: includes/import-tabs.php:16 ultimate-business-dashboard.php:535
     882#: includes/import-tabs.php:16 ultimate-business-dashboard.php:540
    865883msgid "QuickBooks"
    866884msgstr "QuickBooks"
    … …  
    10231041
    10241042#: includes/imports.php:488 includes/imports.php:567 includes/invoices.php:484
    1025 #: includes/invoices.php:513 includes/quality.php:430 includes/quality.php:542
     1043#: includes/invoices.php:513 includes/quality.php:479 includes/quality.php:529
     1044#: includes/quality.php:629
    10261045msgid "Supplier"
    10271046msgstr "Fournisseur"
    … …  
    10511070
    10521071#: includes/imports.php:490 includes/imports.php:569 includes/invoices.php:486
    1053 #: includes/invoices.php:537 includes/quality.php:544
     1072#: includes/invoices.php:537 includes/quality.php:631
    10541073msgid "Net Amount"
    10551074msgstr "Montant net"
    … …  
    14311450msgstr "Sélectionner"
    14321451
    1433 #: includes/invoices.php:507 includes/quality.php:349
     1452#: includes/invoices.php:507 includes/quality.php:397
    14341453msgid "Open the invoice document"
    14351454msgstr "Ouvrir le document de la facture"
    … …  
    14641483msgstr[1] "Amortie · %d mois"
    14651484
    1466 #: includes/quality.php:367
     1485#: includes/quality.php:415
    14671486msgid "Invoice deleted."
    14681487msgstr "Facture supprimée."
    14691488
    1470 #: includes/quality.php:372
     1489#: includes/quality.php:420
    14711490msgid "Alert ignored."
    14721491msgstr "Alerte ignorée."
    14731492
    14741493#. translators: 1: number of invoices, 2: supplier name
    1475 #: includes/quality.php:379
     1494#: includes/quality.php:427
    14761495msgid "%1$d invoice now uses the supplier name \"%2$s\"."
    14771496msgid_plural "%1$d invoices now use the supplier name \"%2$s\"."
    … …  
    14791498msgstr[1] "%1$d factures portent désormais le nom de fournisseur « %2$s »."
    14801499
    1481 #: includes/quality.php:406 ultimate-business-dashboard.php:139
     1500#: includes/quality.php:455 ultimate-business-dashboard.php:139
    14821501msgid "Checks"
    14831502msgstr "Contrôles"
    14841503
    1485 #: includes/quality.php:407
     1504#: includes/quality.php:456
    14861505msgid ""
    14871506"Points to check before relying on your figures. Each alert can be ignored if "
    … …  
    14921511
    14931512#. translators: %d: number of alerts
    1494 #: includes/quality.php:415
     1513#: includes/quality.php:464
    14951514msgid "Possible duplicates (%d)"
    14961515msgstr "Doublons probables (%d)"
    14971516
    1498 #: includes/quality.php:419
     1517#: includes/quality.php:468
    14991518msgid "No possible duplicate."
    15001519msgstr "Aucun doublon probable."
    15011520
    15021521#. translators: %d: number of days
    1503 #: includes/quality.php:424
    1504 msgid ""
    1505 "Same supplier with the same invoice number, or with the same total amount "
    1506 "less than %d days apart."
    1507 msgstr ""
    1508 "Même fournisseur avec le même numéro de facture, ou avec le même montant TTC "
    1509 "à moins de %d jours d’écart."
    1510 
    1511 #: includes/quality.php:432
     1522#: includes/quality.php:473
     1523msgid ""
     1524"Same supplier with the same invoice number and amount, or with the same "
     1525"total amount less than %d days apart."
     1526msgstr ""
     1527"Même fournisseur avec le même numéro de facture et le même montant, ou avec "
     1528"le même montant TTC à moins de %d jours d’écart."
     1529
     1530#: includes/quality.php:481
    15121531msgid "Reason"
    15131532msgstr "Motif"
    15141533
    1515 #: includes/quality.php:433 includes/quality.php:498 includes/quality.php:546
    1516 #: includes/user-management.php:213
     1534#: includes/quality.php:482 includes/quality.php:532 includes/quality.php:585
     1535#: includes/quality.php:633 includes/user-management.php:213
    15171536msgid "Actions"
    15181537msgstr "Actions"
    15191538
    1520 #: includes/quality.php:448
     1539#: includes/quality.php:497
    15211540msgid "Delete this one"
    15221541msgstr "Supprimer celle-ci"
    15231542
    1524 #: includes/quality.php:448
     1543#: includes/quality.php:497
    15251544msgid "Delete this invoice? This cannot be undone."
    15261545msgstr "Supprimer cette facture ? Cette action est irréversible."
    15271546
    1528 #: includes/quality.php:452
    1529 msgid "Same invoice number"
    1530 msgstr "Même numéro de facture"
    1531 
    1532 #: includes/quality.php:452
     1547#: includes/quality.php:501
     1548msgid "Same invoice number and amount"
     1549msgstr "Même numéro et même montant"
     1550
     1551#: includes/quality.php:501
    15331552msgid "Same amount, close dates"
    15341553msgstr "Même montant, dates proches"
    15351554
    1536 #: includes/quality.php:453
     1555#: includes/quality.php:502
    15371556msgid "Not a duplicate"
    15381557msgstr "Pas un doublon"
    15391558
    15401559#. translators: %d: number of rows shown
    1541 #: includes/quality.php:463
     1560#: includes/quality.php:512
    15421561msgid "Only the first %d are shown."
    15431562msgstr "Seuls les %d premiers sont affichés."
    15441563
     1564#. translators: %d: number of suppliers
     1565#: includes/quality.php:522
     1566msgid "Same number, different amounts (%d)"
     1567msgstr "Même numéro, montants différents (%d)"
     1568
     1569#: includes/quality.php:525
     1570msgid ""
     1571"Several documents of these suppliers share the same number with different "
     1572"amounts. It is often normal (instalments, credit notes), but a payment "
     1573"statement imported next to the invoice it settles is counted twice as an "
     1574"expense: open an example and check that each document is a real invoice."
     1575msgstr ""
     1576"Chez ces fournisseurs, plusieurs documents portent le même numéro avec des "
     1577"montants différents. C’est souvent normal (acomptes, avoirs), mais un relevé "
     1578"de paiement importé à côté de la facture qu’il règle compte deux fois en "
     1579"charge : ouvrez un exemple et vérifiez que chaque document est bien une "
     1580"facture."
     1581
     1582#: includes/quality.php:530
     1583msgid "Numbers concerned"
     1584msgstr "Numéros concernés"
     1585
     1586#: includes/quality.php:531
     1587msgid "Example"
     1588msgstr "Exemple"
     1589
     1590#. translators: 1: number of invoice numbers, 2: number of invoices
     1591#: includes/quality.php:541
     1592msgid "%1$s number (%2$s invoices)"
     1593msgid_plural "%1$s numbers (%2$s invoices)"
     1594msgstr[0] "%1$s numéro (%2$s factures)"
     1595msgstr[1] "%1$s numéros (%2$s factures)"
     1596
     1597#: includes/quality.php:546
     1598msgid "See the invoices"
     1599msgstr "Voir les factures"
     1600
     1601#: includes/quality.php:547
     1602msgid "This is normal"
     1603msgstr "C’est normal"
     1604
    15451605#. translators: %d: number of invoices
    1546 #: includes/quality.php:472
     1606#: includes/quality.php:559
    15471607msgid "Uncategorized invoices (%d)"
    15481608msgstr "Factures non catégorisées (%d)"
    15491609
    1550 #: includes/quality.php:476
     1610#: includes/quality.php:563
    15511611msgid "All invoices have a category."
    15521612msgstr "Toutes les factures ont une catégorie."
    15531613
    1554 #: includes/quality.php:479
     1614#: includes/quality.php:566
    15551615msgid ""
    15561616"These invoices are counted in \"Other Invoices\" and as unclassified costs."
    … …  
    15581618"Ces factures sont comptées dans « Autres factures » et en coûts non classés."
    15591619
    1560 #: includes/quality.php:480
     1620#: includes/quality.php:567
    15611621msgid "Show them"
    15621622msgstr "Les afficher"
    15631623
    15641624#. translators: %d: number of groups
    1565 #: includes/quality.php:487
     1625#: includes/quality.php:574
    15661626msgid "Suppliers written in several ways (%d)"
    15671627msgstr "Fournisseurs écrits de plusieurs façons (%d)"
    15681628
    1569 #: includes/quality.php:491
     1629#: includes/quality.php:578
    15701630msgid "No similar supplier names."
    15711631msgstr "Aucun nom de fournisseur similaire."
    15721632
    1573 #: includes/quality.php:493
     1633#: includes/quality.php:580
    15741634msgid "Choose the name to keep: all the invoices of the group will use it."
    15751635msgstr ""
    15761636"Choisissez le nom à garder : toutes les factures du groupe le prendront."
    15771637
    1578 #: includes/quality.php:497
     1638#: includes/quality.php:584
    15791639msgid "Names found (invoices)"
    15801640msgstr "Noms trouvés (factures)"
    15811641
    1582 #: includes/quality.php:519
     1642#: includes/quality.php:606
    15831643msgid "Use this name"
    15841644msgstr "Garder ce nom"
    15851645
    1586 #: includes/quality.php:520
     1646#: includes/quality.php:607
    15871647msgid "Different suppliers"
    15881648msgstr "Fournisseurs différents"
    15891649
    15901650#. translators: %d: number of invoices
    1591 #: includes/quality.php:532
     1651#: includes/quality.php:619
    15921652msgid "Unusual amounts (%d)"
    15931653msgstr "Montants inhabituels (%d)"
    15941654
    1595 #: includes/quality.php:536
     1655#: includes/quality.php:623
    15961656msgid "No unusual amount over the last 12 months."
    15971657msgstr "Aucun montant inhabituel sur les 12 derniers mois."
    15981658
    1599 #: includes/quality.php:538
     1659#: includes/quality.php:625
    16001660msgid ""
    16011661"Invoices of the last 12 months more than 3 times the usual amount (median) "
    … …  
    16051665"(médiane) du fournisseur."
    16061666
    1607 #: includes/quality.php:543
     1667#: includes/quality.php:630
    16081668msgid "Invoice"
    16091669msgstr "Facture"
    16101670
    1611 #: includes/quality.php:545
     1671#: includes/quality.php:632
    16121672msgid "Usual amount"
    16131673msgstr "Montant habituel"
    16141674
    1615 #: includes/quality.php:555
     1675#: includes/quality.php:642
    16161676msgid "Checked"
    16171677msgstr "Vérifié"
    16181678
    16191679#. translators: 1: number of points, 2: opening link, 3: closing link
    1620 #: includes/quality.php:585
     1680#: includes/quality.php:672
    16211681msgid ""
    16221682"%1$d point to check in your data (duplicates, categories, suppliers, "
    … …  
    19772037"The largest expense items of the period, including the costs entered in the "
    19782038"Data page."
    1979 msgstr "Les principaux postes de dépenses de la période, y compris les charges saisies dans la page Données."
     2039msgstr ""
     2040"Les principaux postes de dépenses de la période, y compris les charges "
     2041"saisies dans la page Données."
    19802042
    19812043#: includes/reports.php:277 ultimate-business-dashboard.php:360
    … …  
    19912053"Costs entered in the Data page, amortizations and provisions are fixed; the "
    19922054"cost of goods sold is variable. Invoices follow the type of their category."
    1993 msgstr "Les charges saisies dans la page Données, les amortissements et les provisions sont fixes ; le coût des marchandises vendues est variable. Les factures suivent le type de leur catégorie."
     2055msgstr ""
     2056"Les charges saisies dans la page Données, les amortissements et les "
     2057"provisions sont fixes ; le coût des marchandises vendues est variable. Les "
     2058"factures suivent le type de leur catégorie."
    19942059
    19952060#. translators: 1: break-even revenue, 2: percentage of the actual revenue
    19962061#: includes/reports.php:309
    19972062msgid "Break-even point: %1$s of revenue (%2$s of the actual revenue)."
    1998 msgstr "Point mort : %1$s de chiffre d’affaires (%2$s du chiffre d’affaires réel)."
     2063msgstr ""
     2064"Point mort : %1$s de chiffre d’affaires (%2$s du chiffre d’affaires réel)."
    19992065
    20002066#: includes/reports.php:314
    … …  
    26332699msgstr "Non connecté"
    26342700
    2635 #: ultimate-business-dashboard.php:532
     2701#: ultimate-business-dashboard.php:534
     2702msgctxt "import status"
     2703msgid "Configured"
     2704msgstr "Configuré"
     2705
     2706#: ultimate-business-dashboard.php:537
    26362707msgid ""
    26372708"Automatic import: each invoice processed in Dext is sent here by Zapier."
    2638 msgstr "Import automatique : chaque facture traitée dans Dext est envoyée ici par Zapier."
    2639 
    2640 #: ultimate-business-dashboard.php:532
     2709msgstr ""
     2710"Import automatique : chaque facture traitée dans Dext est envoyée ici par "
     2711"Zapier."
     2712
     2713#: ultimate-business-dashboard.php:537 ultimate-business-dashboard.php:540
     2714msgid "Manage"
     2715msgstr "Gérer"
     2716
     2717#: ultimate-business-dashboard.php:537
    26412718msgid "Set up"
    26422719msgstr "Configurer"
    26432720
    2644 #: ultimate-business-dashboard.php:533
     2721#: ultimate-business-dashboard.php:538
    26452722msgid "Import a CSV export from Dext (\"Dext Prepare Default\" format)."
    26462723msgstr "Importer un export CSV de Dext (format « Dext Prepare Default »)."
    26472724
    2648 #: ultimate-business-dashboard.php:533 ultimate-business-dashboard.php:534
     2725#: ultimate-business-dashboard.php:538 ultimate-business-dashboard.php:539
    26492726msgid "Import a file"
    26502727msgstr "Importer un fichier"
    26512728
    2652 #: ultimate-business-dashboard.php:534
     2729#: ultimate-business-dashboard.php:539
    26532730msgid "Import invoices from any other tool with a simple CSV file."
    26542731msgstr "Importer les factures de tout autre outil avec un simple fichier CSV."
    26552732
    2656 #: ultimate-business-dashboard.php:535
     2733#: ultimate-business-dashboard.php:540
    26572734msgid "Connect QuickBooks Online to import supplier bills every hour."
    2658 msgstr "Connecter QuickBooks Online pour importer les factures fournisseurs toutes les heures."
    2659 
    2660 #: ultimate-business-dashboard.php:535
    2661 msgid "Manage"
    2662 msgstr "Gérer"
    2663 
    2664 #: ultimate-business-dashboard.php:535
     2735msgstr ""
     2736"Connecter QuickBooks Online pour importer les factures fournisseurs toutes "
     2737"les heures."
     2738
     2739#: ultimate-business-dashboard.php:540
    26652740msgid "Connect"
    26662741msgstr "Connecter"
    26672742
    2668 #: ultimate-business-dashboard.php:540
     2743#: ultimate-business-dashboard.php:545
    26692744msgid ""
    26702745"Choose how your supplier invoices reach the dashboard. Duplicates are "
    26712746"ignored automatically, whatever the method."
    2672 msgstr "Choisissez comment vos factures fournisseurs arrivent dans le tableau de bord. Les doublons sont ignorés automatiquement, quelle que soit la méthode."
     2747msgstr ""
     2748"Choisissez comment vos factures fournisseurs arrivent dans le tableau de "
     2749"bord. Les doublons sont ignorés automatiquement, quelle que soit la méthode."
     2750
     2751#. translators: 1: date and time, 2: total number of invoices
     2752#: ultimate-business-dashboard.php:551
     2753msgid "Last invoice added on %1$s · %2$s invoices in total"
     2754msgstr "Dernière facture ajoutée le %1$s · %2$s factures au total"
    26732755
    26742756#~ msgid ""
  • ultimate-business-dashboard/tags/2.7.1/languages/ultimate-business-dashboard.pot

    r3803022 r3803495  
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: Ultimate Business Dashboard 2.6\n"
     5"Project-Id-Version: Ultimate Business Dashboard 2.7.1\n"
    66"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ultimate-business-dashboard\n"
    77"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    … …  
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"Content-Transfer-Encoding: 8bit\n"
    12 "POT-Creation-Date: 2026-11-15T09:59:02+00:00\n"
     12"POT-Creation-Date: 2026-11-15T15:30:11+00:00\n"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.11.0\n"
    … …  
    8585#: includes/imports.php:535
    8686#: includes/invoices.php:133
    87 #: includes/quality.php:358
     87#: includes/quality.php:406
    8888#: includes/quickbooks.php:25
    8989#: includes/quickbooks.php:511
    … …  
    237237#: includes/categories.php:244
    238238#: includes/invoices.php:436
    239 #: includes/quality.php:431
     239#: includes/quality.php:480
    240240#: ultimate-business-dashboard.php:138
    241241msgid "Invoices"
    … …  
    839839
    840840#. translators: %s: number. Percentage format; French uses a non-breaking space before the % sign.
    841 #: includes/format.php:93
     841#: includes/format.php:110
    842842msgctxt "percentage"
    843843msgid "%s%%"
    844844msgstr ""
    845845
    846 #: includes/format.php:123
     846#: includes/format.php:140
    847847msgid "No comparison available"
    848848msgstr ""
    849849
    850 #: includes/format.php:126
     850#: includes/format.php:144
     851msgid "Variation too large to be meaningful (very small comparison base)"
     852msgstr ""
     853
     854#: includes/format.php:144
     855#: includes/format.php:147
     856msgid "n/m"
     857msgstr ""
     858
     859#: includes/format.php:147
    851860#: ultimate-business-dashboard.php:352
    852861msgid "Variation not meaningful (transition from loss to profit or vice versa)"
    853 msgstr ""
    854 
    855 #: includes/format.php:126
    856 msgid "n/m"
    857862msgstr ""
    858863
    … …  
    867872
    868873#: includes/import-tabs.php:13
    869 #: ultimate-business-dashboard.php:532
     874#: ultimate-business-dashboard.php:537
    870875msgid "Dext & Zapier"
    871876msgstr ""
    872877
    873878#: includes/import-tabs.php:14
    874 #: ultimate-business-dashboard.php:533
     879#: ultimate-business-dashboard.php:538
    875880msgid "Dext CSV"
    876881msgstr ""
    877882
    878883#: includes/import-tabs.php:15
    879 #: ultimate-business-dashboard.php:534
     884#: ultimate-business-dashboard.php:539
    880885msgid "Other CSV"
    881886msgstr ""
    882887
    883888#: includes/import-tabs.php:16
    884 #: ultimate-business-dashboard.php:535
     889#: ultimate-business-dashboard.php:540
    885890msgid "QuickBooks"
    886891msgstr ""
    … …  
    10361041#: includes/invoices.php:484
    10371042#: includes/invoices.php:513
    1038 #: includes/quality.php:430
    1039 #: includes/quality.php:542
     1043#: includes/quality.php:479
     1044#: includes/quality.php:529
     1045#: includes/quality.php:629
    10401046msgid "Supplier"
    10411047msgstr ""
    … …  
    10721078#: includes/invoices.php:486
    10731079#: includes/invoices.php:537
    1074 #: includes/quality.php:544
     1080#: includes/quality.php:631
    10751081msgid "Net Amount"
    10761082msgstr ""
    … …  
    14111417
    14121418#: includes/invoices.php:507
    1413 #: includes/quality.php:349
     1419#: includes/quality.php:397
    14141420msgid "Open the invoice document"
    14151421msgstr ""
    … …  
    14461452msgstr[1] ""
    14471453
    1448 #: includes/quality.php:367
     1454#: includes/quality.php:415
    14491455msgid "Invoice deleted."
    14501456msgstr ""
    14511457
    1452 #: includes/quality.php:372
     1458#: includes/quality.php:420
    14531459msgid "Alert ignored."
    14541460msgstr ""
    14551461
    14561462#. translators: 1: number of invoices, 2: supplier name
    1457 #: includes/quality.php:379
     1463#: includes/quality.php:427
    14581464msgid "%1$d invoice now uses the supplier name \"%2$s\"."
    14591465msgid_plural "%1$d invoices now use the supplier name \"%2$s\"."
    … …  
    14611467msgstr[1] ""
    14621468
    1463 #: includes/quality.php:406
     1469#: includes/quality.php:455
    14641470#: ultimate-business-dashboard.php:139
    14651471msgid "Checks"
    14661472msgstr ""
    14671473
    1468 #: includes/quality.php:407
     1474#: includes/quality.php:456
    14691475msgid "Points to check before relying on your figures. Each alert can be ignored if it is not a problem."
    14701476msgstr ""
    14711477
    14721478#. translators: %d: number of alerts
    1473 #: includes/quality.php:415
     1479#: includes/quality.php:464
    14741480msgid "Possible duplicates (%d)"
    14751481msgstr ""
    14761482
    1477 #: includes/quality.php:419
     1483#: includes/quality.php:468
    14781484msgid "No possible duplicate."
    14791485msgstr ""
    14801486
    14811487#. translators: %d: number of days
    1482 #: includes/quality.php:424
    1483 msgid "Same supplier with the same invoice number, or with the same total amount less than %d days apart."
    1484 msgstr ""
    1485 
    1486 #: includes/quality.php:432
     1488#: includes/quality.php:473
     1489msgid "Same supplier with the same invoice number and amount, or with the same total amount less than %d days apart."
     1490msgstr ""
     1491
     1492#: includes/quality.php:481
    14871493msgid "Reason"
    14881494msgstr ""
    14891495
    1490 #: includes/quality.php:433
    1491 #: includes/quality.php:498
    1492 #: includes/quality.php:546
     1496#: includes/quality.php:482
     1497#: includes/quality.php:532
     1498#: includes/quality.php:585
     1499#: includes/quality.php:633
    14931500#: includes/user-management.php:213
    14941501msgid "Actions"
    14951502msgstr ""
    14961503
    1497 #: includes/quality.php:448
     1504#: includes/quality.php:497
    14981505msgid "Delete this one"
    14991506msgstr ""
    15001507
    1501 #: includes/quality.php:448
     1508#: includes/quality.php:497
    15021509msgid "Delete this invoice? This cannot be undone."
    15031510msgstr ""
    15041511
    1505 #: includes/quality.php:452
    1506 msgid "Same invoice number"
    1507 msgstr ""
    1508 
    1509 #: includes/quality.php:452
     1512#: includes/quality.php:501
     1513msgid "Same invoice number and amount"
     1514msgstr ""
     1515
     1516#: includes/quality.php:501
    15101517msgid "Same amount, close dates"
    15111518msgstr ""
    15121519
    1513 #: includes/quality.php:453
     1520#: includes/quality.php:502
    15141521msgid "Not a duplicate"
    15151522msgstr ""
    15161523
    15171524#. translators: %d: number of rows shown
    1518 #: includes/quality.php:463
     1525#: includes/quality.php:512
    15191526msgid "Only the first %d are shown."
    15201527msgstr ""
    15211528
     1529#. translators: %d: number of suppliers
     1530#: includes/quality.php:522
     1531msgid "Same number, different amounts (%d)"
     1532msgstr ""
     1533
     1534#: includes/quality.php:525
     1535msgid "Several documents of these suppliers share the same number with different amounts. It is often normal (instalments, credit notes), but a payment statement imported next to the invoice it settles is counted twice as an expense: open an example and check that each document is a real invoice."
     1536msgstr ""
     1537
     1538#: includes/quality.php:530
     1539msgid "Numbers concerned"
     1540msgstr ""
     1541
     1542#: includes/quality.php:531
     1543msgid "Example"
     1544msgstr ""
     1545
     1546#. translators: 1: number of invoice numbers, 2: number of invoices
     1547#: includes/quality.php:541
     1548msgid "%1$s number (%2$s invoices)"
     1549msgid_plural "%1$s numbers (%2$s invoices)"
     1550msgstr[0] ""
     1551msgstr[1] ""
     1552
     1553#: includes/quality.php:546
     1554msgid "See the invoices"
     1555msgstr ""
     1556
     1557#: includes/quality.php:547
     1558msgid "This is normal"
     1559msgstr ""
     1560
    15221561#. translators: %d: number of invoices
    1523 #: includes/quality.php:472
     1562#: includes/quality.php:559
    15241563msgid "Uncategorized invoices (%d)"
    15251564msgstr ""
    15261565
    1527 #: includes/quality.php:476
     1566#: includes/quality.php:563
    15281567msgid "All invoices have a category."
    15291568msgstr ""
    15301569
    1531 #: includes/quality.php:479
     1570#: includes/quality.php:566
    15321571msgid "These invoices are counted in \"Other Invoices\" and as unclassified costs."
    15331572msgstr ""
    15341573
    1535 #: includes/quality.php:480
     1574#: includes/quality.php:567
    15361575msgid "Show them"
    15371576msgstr ""
    15381577
    15391578#. translators: %d: number of groups
    1540 #: includes/quality.php:487
     1579#: includes/quality.php:574
    15411580msgid "Suppliers written in several ways (%d)"
    15421581msgstr ""
    15431582
    1544 #: includes/quality.php:491
     1583#: includes/quality.php:578
    15451584msgid "No similar supplier names."
    15461585msgstr ""
    15471586
    1548 #: includes/quality.php:493
     1587#: includes/quality.php:580
    15491588msgid "Choose the name to keep: all the invoices of the group will use it."
    15501589msgstr ""
    15511590
    1552 #: includes/quality.php:497
     1591#: includes/quality.php:584
    15531592msgid "Names found (invoices)"
    15541593msgstr ""
    15551594
    1556 #: includes/quality.php:519
     1595#: includes/quality.php:606
    15571596msgid "Use this name"
    15581597msgstr ""
    15591598
    1560 #: includes/quality.php:520
     1599#: includes/quality.php:607
    15611600msgid "Different suppliers"
    15621601msgstr ""
    15631602
    15641603#. translators: %d: number of invoices
    1565 #: includes/quality.php:532
     1604#: includes/quality.php:619
    15661605msgid "Unusual amounts (%d)"
    15671606msgstr ""
    15681607
    1569 #: includes/quality.php:536
     1608#: includes/quality.php:623
    15701609msgid "No unusual amount over the last 12 months."
    15711610msgstr ""
    15721611
    1573 #: includes/quality.php:538
     1612#: includes/quality.php:625
    15741613msgid "Invoices of the last 12 months more than 3 times the usual amount (median) of the supplier."
    15751614msgstr ""
    15761615
    1577 #: includes/quality.php:543
     1616#: includes/quality.php:630
    15781617msgid "Invoice"
    15791618msgstr ""
    15801619
    1581 #: includes/quality.php:545
     1620#: includes/quality.php:632
    15821621msgid "Usual amount"
    15831622msgstr ""
    15841623
    1585 #: includes/quality.php:555
     1624#: includes/quality.php:642
    15861625msgid "Checked"
    15871626msgstr ""
    15881627
    15891628#. translators: 1: number of points, 2: opening link, 3: closing link
    1590 #: includes/quality.php:585
     1629#: includes/quality.php:672
    15911630msgid "%1$d point to check in your data (duplicates, categories, suppliers, amounts). %2$sSee the checks%3$s"
    15921631msgid_plural "%1$d points to check in your data (duplicates, categories, suppliers, amounts). %2$sSee the checks%3$s"
    … …  
    24202459msgstr ""
    24212460
    2422 #: ultimate-business-dashboard.php:532
     2461#: ultimate-business-dashboard.php:534
     2462msgctxt "import status"
     2463msgid "Configured"
     2464msgstr ""
     2465
     2466#: ultimate-business-dashboard.php:537
    24232467msgid "Automatic import: each invoice processed in Dext is sent here by Zapier."
    24242468msgstr ""
    24252469
    2426 #: ultimate-business-dashboard.php:532
     2470#: ultimate-business-dashboard.php:537
     2471#: ultimate-business-dashboard.php:540
     2472msgid "Manage"
     2473msgstr ""
     2474
     2475#: ultimate-business-dashboard.php:537
    24272476msgid "Set up"
    24282477msgstr ""
    24292478
    2430 #: ultimate-business-dashboard.php:533
     2479#: ultimate-business-dashboard.php:538
    24312480msgid "Import a CSV export from Dext (\"Dext Prepare Default\" format)."
    24322481msgstr ""
    24332482
    2434 #: ultimate-business-dashboard.php:533
    2435 #: ultimate-business-dashboard.php:534
     2483#: ultimate-business-dashboard.php:538
     2484#: ultimate-business-dashboard.php:539
    24362485msgid "Import a file"
    24372486msgstr ""
    24382487
    2439 #: ultimate-business-dashboard.php:534
     2488#: ultimate-business-dashboard.php:539
    24402489msgid "Import invoices from any other tool with a simple CSV file."
    24412490msgstr ""
    24422491
    2443 #: ultimate-business-dashboard.php:535
     2492#: ultimate-business-dashboard.php:540
    24442493msgid "Connect QuickBooks Online to import supplier bills every hour."
    24452494msgstr ""
    24462495
    2447 #: ultimate-business-dashboard.php:535
    2448 msgid "Manage"
    2449 msgstr ""
    2450 
    2451 #: ultimate-business-dashboard.php:535
     2496#: ultimate-business-dashboard.php:540
    24522497msgid "Connect"
    24532498msgstr ""
    24542499
    2455 #: ultimate-business-dashboard.php:540
     2500#: ultimate-business-dashboard.php:545
    24562501msgid "Choose how your supplier invoices reach the dashboard. Duplicates are ignored automatically, whatever the method."
    24572502msgstr ""
     2503
     2504#. translators: 1: date and time, 2: total number of invoices
     2505#: ultimate-business-dashboard.php:551
     2506msgid "Last invoice added on %1$s · %2$s invoices in total"
     2507msgstr ""
  • ultimate-business-dashboard/tags/2.7.1/readme.txt

    r3803022 r3803495  
    55Requires at least: 5.5
    66Tested up to: 7.1
    7 Stable tag: 2.7
     7Stable tag: 2.7.1
    88Requires PHP: 7.4
    99License: GPLv2 or later
    … …  
    9696
    9797== Changelog ==
     98= 2.7.1 - 15 November 2026 =
     99* Fixed: The EBITDA line of the dashboard chart was hidden behind the net result line when both were close
     100* Fixed: The currency symbol follows the user's language when its position is automatic (100 € in French, €100 in English), whatever the site language
     101* Fixed: Variations above 1,000 % (very small comparison base) are shown as "n/m"
     102* Improved: Checks: invoices with the same number but different amounts are no longer listed one pair at a time among duplicates, but in a separate "Same number, different amounts" section, one line per supplier (a payment statement imported next to its invoice would be counted twice)
     103* Improved: Icons and text centered in the buttons, wider category column on the Invoices page, aligned duplicate lines on the Checks page
     104* Improved: Imports page shows Dext & Zapier as configured and the date of the last invoice added
     105
    98106= 2.7 - 15 November 2026 =
    99107* Improved: Ratios & Reports redesigned: key figures as tiles compared with the same period of the previous year, ratios with the previous year, expense breakdown as sorted bars (top 8 + others) instead of a pie chart, fixed vs variable costs as a single bar with amounts and the break-even point, cleaner print / PDF
    … …  
    232240
    233241== Upgrade Notice ==
     242= 2.7.1 =
     243Visual fixes (chart, buttons, invoices, checks) and clearer duplicate checks.
     244
    234245= 2.7 =
    235246Redesigned Reports, Invoices (with mobile cards), Data (spreadsheet), Imports, Settings and Categories pages.
  • ultimate-business-dashboard/tags/2.7.1/ultimate-business-dashboard.php

    r3803022 r3803495  
    44 * Plugin URI: https://tulipemedia.com/en/ultimate-business-dashboard/
    55 * Description: Turn your WordPress dashboard into a Financial Powerhouse.
    6  * Version: 2.7
     6 * Version: 2.7.1
    77 * Author: Ziyad Bachalany
    88 * Author URI: https://tulipemedia.com
    … …  
    1717
    1818// Define plugin constants
    19 define('ULTIBUDA_VERSION', '2.7');
     19define('ULTIBUDA_VERSION', '2.7.1');
    2020define('ULTIBUDA_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2121define('ULTIBUDA_PLUGIN_URL', plugin_dir_url(__FILE__));
    … …  
    529529        $qb_status = ['', __('Not connected', 'ultimate-business-dashboard')];
    530530    }
     531    // Zapier : envois antérieurs à la 2.7 absents du journal ; la clé API indique qu'il est configuré
     532    $zapier_status = $last('zapier');
     533    if ($zapier_status[0] === '' && get_option('ultibuda_webhook_api_key', '')) {
     534        $zapier_status = ['ok', _x('Configured', 'import status', 'ultimate-business-dashboard')];
     535    }
    531536    $cards = [
    532         ['ultibuda-setup-zapier', 'dashicons-update', __('Dext & Zapier', 'ultimate-business-dashboard'), __('Automatic import: each invoice processed in Dext is sent here by Zapier.', 'ultimate-business-dashboard'), $last('zapier'), __('Set up', 'ultimate-business-dashboard')],
     537        ['ultibuda-setup-zapier', 'dashicons-update', __('Dext & Zapier', 'ultimate-business-dashboard'), __('Automatic import: each invoice processed in Dext is sent here by Zapier.', 'ultimate-business-dashboard'), $zapier_status, $zapier_status[0] ? __('Manage', 'ultimate-business-dashboard') : __('Set up', 'ultimate-business-dashboard')],
    533538        ['ultibuda-dext-import', 'dashicons-media-spreadsheet', __('Dext CSV', 'ultimate-business-dashboard'), __('Import a CSV export from Dext ("Dext Prepare Default" format).', 'ultimate-business-dashboard'), $last('dext_csv'), __('Import a file', 'ultimate-business-dashboard')],
    534539        ['ultibuda-other-import', 'dashicons-media-text', __('Other CSV', 'ultimate-business-dashboard'), __('Import invoices from any other tool with a simple CSV file.', 'ultimate-business-dashboard'), $last('other_csv'), __('Import a file', 'ultimate-business-dashboard')],
    … …  
    539544    ?>
    540545        <p class="description"><?php esc_html_e('Choose how your supplier invoices reach the dashboard. Duplicates are ignored automatically, whatever the method.', 'ultimate-business-dashboard'); ?></p>
     546        <?php $last_added = ultibuda_last_invoice_added_time(); ?>
     547        <?php if ($last_added) : ?>
     548            <p>
     549                <?php
     550                /* translators: 1: date and time, 2: total number of invoices */
     551                echo esc_html(sprintf(__('Last invoice added on %1$s · %2$s invoices in total', 'ultimate-business-dashboard'), wp_date(get_option('date_format') . ' ' . get_option('time_format'), $last_added), number_format_i18n(ultibuda_count_invoices())));
     552                ?>
     553            </p>
     554        <?php endif; ?>
    541555        <div class="ultibuda-import-cards">
    542556            <?php foreach ($cards as $card) : ?>
  • ultimate-business-dashboard/trunk/assets/css/admin.css

    r3803022 r3803495  
    841841.card-empty { margin: 0; color: var(--ubd-grey); font-style: italic; }
    842842.card-actions { align-items: center; gap: 6px; flex-wrap: wrap; }
    843 .card-actions .button .dashicons { font-size: 16px; width: 16px; height: 16px; vertical-align: middle; margin: -3px 2px 0 0; }
    844843.ultibuda-icon-button.button { padding: 0 6px; color: var(--ubd-grey); }
    845844.ultibuda-icon-button.button:hover,
    846845.ultibuda-icon-button.button:focus { color: var(--ubd-blue); }
    847 .ultibuda-icon-button .dashicons { margin-right: 0 !important; }
    848846.ultibuda-inline-form { display: inline; margin: 0; }
    849847
    … …  
    896894.ultibuda-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
    897895.ultibuda-break-even { margin: 12px 0 0; color: var(--ubd-grey); }
    898 .print-report-btn .dashicons { vertical-align: middle; margin-top: -3px; }
    899896@media (max-width: 1100px) {
    900897    .ultibuda-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    … …  
    10231020.ultibuda-code-input { width: 100px; }
    10241021.ultibuda-categories-table select { max-width: 100%; }
     1022
     1023/* 2.7.1 : icônes centrées dans les boutons, quelle que soit la taille du texte */
     1024.card-actions .button,
     1025.print-report-btn.button {
     1026    display: inline-flex;
     1027    align-items: center;
     1028    justify-content: center;
     1029    gap: 4px;
     1030}
     1031.card-actions .button .dashicons,
     1032.print-report-btn .dashicons {
     1033    font-size: 16px;
     1034    width: 16px;
     1035    height: 16px;
     1036    line-height: 1;
     1037    margin: 0;
     1038    vertical-align: baseline;
     1039}
     1040
     1041/* 2.7.1 : page Factures, catégorie lisible et type compact */
     1042.ultibuda-invoices-table .column-supplier { width: 24%; }
     1043.ultibuda-invoices-table .column-category { width: 28%; }
     1044.ultibuda-invoices-table .column-category select { width: 100%; min-width: 200px; max-width: none; }
     1045.ultibuda-invoices-table .ultibuda-select-small { width: auto; max-width: 140px; min-width: 0; }
     1046.ultibuda-invoices-table .column-input { width: 96px; }
     1047.ultibuda-invoices-table .column-input input { max-width: 96px; }
     1048
     1049/* 2.7.1 : doublons probables en colonnes alignées */
     1050.ultibuda-dup-line { display: grid; grid-template-columns: 150px 100px 100px minmax(0, 1fr) auto; align-items: center; gap: 4px 12px; padding: 3px 0; }
     1051.ultibuda-dup-line .num { text-align: right; font-variant-numeric: tabular-nums; }
     1052.ultibuda-dup-line > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
     1053@media (max-width: 782px) { .ultibuda-dup-line { grid-template-columns: minmax(0, 1fr) auto; } .ultibuda-dup-line > span:nth-child(4) { display: none; } }
  • ultimate-business-dashboard/trunk/assets/js/admin.js

    r3803022 r3803495  
    334334                            { type: 'bar', label: d.revenueLabel, data: d.revenue, backgroundColor: 'rgba(34, 113, 177, 0.75)', borderRadius: 3, order: 3 },
    335335                            { type: 'line', label: d.revenuePrevLabel, data: d.revenuePrev, borderColor: '#8c8f94', borderDash: [6, 4], pointRadius: 0, borderWidth: 2, order: 2 },
    336                             { type: 'line', label: d.ebeLabel, data: d.ebe, borderColor: '#00a32a', backgroundColor: '#00a32a', tension: 0.25, borderWidth: 2, order: 1 },
    337                             { type: 'line', label: d.resultLabel, data: d.result, borderColor: '#d63638', backgroundColor: '#d63638', tension: 0.25, borderWidth: 2, order: 0 }
     336                            { type: 'line', label: d.ebeLabel, data: d.ebe, borderColor: '#00a32a', backgroundColor: '#00a32a', tension: 0.25, borderWidth: 4, pointRadius: 4, order: 0 },
     337                            { type: 'line', label: d.resultLabel, data: d.result, borderColor: '#d63638', backgroundColor: '#d63638', tension: 0.25, borderWidth: 2, borderDash: [5, 4], pointRadius: 3, pointStyle: 'rectRot', order: 1 }
    338338                        ]
    339339                    },
  • ultimate-business-dashboard/trunk/includes/format.php

    r3802991 r3803495  
    4545    return [
    4646        'symbol' => $symbol !== '' ? $symbol : $default['symbol'],
    47         'position' => in_array($position, ['before', 'after'], true) ? $position : $default['position'],
     47        // Position automatique : celle de la langue de l'utilisateur, comme le format des nombres
     48        // (« 100 € » en français, « €100 » en anglais), quelle que soit la langue du site.
     49        'position' => in_array($position, ['before', 'after'], true) ? $position : ultibuda_locale_currency_position(get_user_locale()),
    4850    ];
     51}
     52
     53/**
     54 * Place habituelle du symbole monétaire dans une langue.
     55 *
     56 * @param string $locale Langue (ex. fr_FR, en_US).
     57 * @return string before|after
     58 */
     59function ultibuda_locale_currency_position($locale) {
     60    foreach (['en', 'nl', 'ja', 'zh', 'ko', 'he', 'pt_BR', 'es_MX', 'es_AR', 'es_CO', 'es_CL', 'th', 'ms', 'id'] as $prefix) {
     61        if (strpos((string) $locale, $prefix) === 0) {
     62            return 'before';
     63        }
     64    }
     65    return 'after';
    4966}
    5067
    … …  
    123140        return '<span class="variation neutral" title="' . esc_attr__('No comparison available', 'ultimate-business-dashboard') . '">–</span>';
    124141    }
     142    if (is_numeric($var) && abs((float) $var) >= 1000) {
     143        // Base de comparaison presque nulle : le pourcentage n'a pas de sens
     144        return '<span class="variation neutral" title="' . esc_attr__('Variation too large to be meaningful (very small comparison base)', 'ultimate-business-dashboard') . '">' . esc_html__('n/m', 'ultimate-business-dashboard') . '</span>';
     145    }
    125146    if ($var === 'NM') {
    126147        return '<span class="variation neutral" title="' . esc_attr__('Variation not meaningful (transition from loss to profit or vice versa)', 'ultimate-business-dashboard') . '">' . esc_html__('n/m', 'ultimate-business-dashboard') . '</span>';
  • ultimate-business-dashboard/trunk/includes/invoice-store.php

    r3803022 r3803495  
    640640
    641641/**
     642 * Date d'ajout de la facture la plus récente (toutes sources), en horodatage, ou 0.
     643 *
     644 * @return int
     645 */
     646function ultibuda_last_invoice_added_time() {
     647    if (!ultibuda_invoices_store_ready()) {
     648        return 0;
     649    }
     650    global $wpdb;
     651    $table = ultibuda_invoices_table();
     652    $last = $wpdb->get_var("SELECT MAX(created_at) FROM $table"); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     653    return $last ? (int) strtotime($last . ' UTC') : 0;
     654}
     655
     656/**
    642657 * Nombre de factures par catégorie.
    643658 *
  • ultimate-business-dashboard/trunk/includes/quality.php

    r3802991 r3803495  
    4040 * Alertes ignorées.
    4141 *
    42  * @return array{duplicates: string[], suppliers: string[], amounts: string[]}
     42 * @return array{duplicates: string[], suppliers: string[], amounts: string[], shared_numbers: string[]}
    4343 */
    4444function ultibuda_quality_ignored() {
    4545    $ignored = get_option('ultibuda_quality_ignored', []);
    4646    $ignored = is_array($ignored) ? $ignored : [];
    47     foreach (['duplicates', 'suppliers', 'amounts'] as $key) {
     47    foreach (['duplicates', 'suppliers', 'amounts', 'shared_numbers'] as $key) {
    4848        $ignored[$key] = isset($ignored[$key]) && is_array($ignored[$key]) ? $ignored[$key] : [];
    4949    }
    … …  
    5454 * Ignore une alerte.
    5555 *
    56  * @param string $type duplicates|suppliers|amounts.
     56 * @param string $type duplicates|suppliers|amounts|shared_numbers.
    5757 * @param string $key  Clé de l'alerte.
    5858 */
    … …  
    9494
    9595    foreach ($by_supplier as $supplier_invoices) {
    96         // Même numéro de facture chez le même fournisseur
     96        // Même numéro de facture et même montant chez le même fournisseur (un même numéro avec des
     97        // montants différents désigne en général deux documents distincts, ex. relevés Deliveroo)
    9798        $by_number = [];
    9899        foreach ($supplier_invoices as $invoice) {
    99100            $number = strtolower(trim((string) ($invoice['invoice_number'] ?? '')));
    100101            if ($number !== '' && $number !== 'n/a') {
    101                 $by_number[$number][] = $invoice;
     102                $by_number[$number . '|' . number_format((float) ($invoice['total_amount'] ?? 0), 2, '.', '')][] = $invoice;
    102103            }
    103104        }
    … …  
    139140
    140141/**
     142 * Numéros de facture partagés par plusieurs documents de montants différents, regroupés par fournisseur.
     143 *
     144 * Ce n'est pas un doublon (acomptes, avoirs, relevés), mais un relevé de paiement importé à côté
     145 * de la facture qu'il règle compterait deux fois en charge : on le signale à part, une ligne par fournisseur.
     146 *
     147 * @param array[] $invoices Factures.
     148 * @return array[] Liste de ['key' => string, 'supplier' => string, 'numbers' => int, 'invoices' => int, 'example' => string].
     149 */
     150function ultibuda_quality_shared_numbers($invoices) {
     151    $ignored = ultibuda_quality_ignored()['shared_numbers'];
     152    $groups = [];
     153    foreach ($invoices as $invoice) {
     154        $supplier = ultibuda_normalize_supplier($invoice['supplier'] ?? '');
     155        $number = strtolower(trim((string) ($invoice['invoice_number'] ?? '')));
     156        if ($supplier === '' || $supplier === 'unknown' || $number === '' || $number === 'n/a' || in_array($supplier, $ignored, true)) {
     157            continue;
     158        }
     159        $groups[$supplier]['name'] = $groups[$supplier]['name'] ?? (string) $invoice['supplier'];
     160        $groups[$supplier]['numbers'][$number]['label'] = (string) $invoice['invoice_number'];
     161        $groups[$supplier]['numbers'][$number]['amounts'][number_format((float) ($invoice['total_amount'] ?? 0), 2, '.', '')] = true;
     162        $groups[$supplier]['numbers'][$number]['count'] = ($groups[$supplier]['numbers'][$number]['count'] ?? 0) + 1;
     163    }
     164    $result = [];
     165    foreach ($groups as $supplier => $group) {
     166        $shared = array_filter($group['numbers'], function ($entry) {
     167            return count($entry['amounts']) > 1;
     168        });
     169        if (!$shared) {
     170            continue;
     171        }
     172        $first = reset($shared);
     173        $result[] = [
     174            'key' => $supplier,
     175            'supplier' => $group['name'],
     176            'numbers' => count($shared),
     177            'invoices' => array_sum(array_column($shared, 'count')),
     178            'example' => $first['label'],
     179        ];
     180    }
     181    usort($result, function ($a, $b) {
     182        return $b['numbers'] - $a['numbers'];
     183    });
     184    return $result;
     185}
     186
     187/**
    141188 * Factures non catégorisées (ou rattachées à une catégorie supprimée).
    142189 *
    … …  
    288335function ultibuda_quality_issue_count($invoices) {
    289336    return count(ultibuda_quality_duplicates($invoices))
     337        + count(ultibuda_quality_shared_numbers($invoices))
    290338        + ultibuda_quality_uncategorized_count($invoices)
    291339        + count(ultibuda_quality_supplier_groups($invoices))
    … …  
    367415                $message = __('Invoice deleted.', 'ultimate-business-dashboard');
    368416            }
    369         } elseif (in_array($action, ['ignore_duplicate', 'ignore_suppliers', 'ignore_amount'], true) && $key !== '') {
    370             $types = ['ignore_duplicate' => 'duplicates', 'ignore_suppliers' => 'suppliers', 'ignore_amount' => 'amounts'];
     417        } elseif (in_array($action, ['ignore_duplicate', 'ignore_suppliers', 'ignore_amount', 'ignore_shared_number'], true) && $key !== '') {
     418            $types = ['ignore_duplicate' => 'duplicates', 'ignore_suppliers' => 'suppliers', 'ignore_amount' => 'amounts', 'ignore_shared_number' => 'shared_numbers'];
    371419            ultibuda_quality_ignore($types[$action], $key);
    372420            $message = __('Alert ignored.', 'ultimate-business-dashboard');
    … …  
    384432    $invoices = ultibuda_get_invoices();
    385433    $duplicates = ultibuda_quality_duplicates($invoices);
     434    $shared_numbers = ultibuda_quality_shared_numbers($invoices);
    386435    $uncategorized = ultibuda_quality_uncategorized_count($invoices);
    387436    $supplier_groups = ultibuda_quality_supplier_groups($invoices);
    … …  
    422471                <?php
    423472                /* translators: %d: number of days */
    424                 echo esc_html(sprintf(__('Same supplier with the same invoice number, or with the same total amount less than %d days apart.', 'ultimate-business-dashboard'), ULTIBUDA_DUPLICATE_DAYS));
     473                echo esc_html(sprintf(__('Same supplier with the same invoice number and amount, or with the same total amount less than %d days apart.', 'ultimate-business-dashboard'), ULTIBUDA_DUPLICATE_DAYS));
    425474                ?>
    426475            </p>
    … …  
    438487                            <td><?php echo esc_html($pair['invoices'][0]['supplier']); ?></td>
    439488                            <td>
    440                                 <?php foreach ($pair['invoices'] as $invoice) : ?>
    441                                     <div>
    442                                         <?php echo wp_kses_post(ultibuda_quality_document_link($invoice)); ?>
    443                                         — <?php echo esc_html($invoice['date']); ?>
    444                                         — <?php echo esc_html($money($invoice['total_amount'])); ?>
    445                                         <?php if (!empty($invoice['invoice_number']) && $invoice['invoice_number'] !== 'N/A') : ?>
    446                                             — <?php echo esc_html($invoice['invoice_number']); ?>
    447                                         <?php endif; ?>
    448                                         <?php $action_button('delete_invoice', $invoice['id'], __('Delete this one', 'ultimate-business-dashboard'), __('Delete this invoice? This cannot be undone.', 'ultimate-business-dashboard')); ?>
     489                                <?php foreach ($pair['invoices'] as $invoice) :
     490                                    $time = strtotime((string) $invoice['date']);
     491                                    ?>
     492                                    <div class="ultibuda-dup-line">
     493                                        <span><?php echo wp_kses_post(ultibuda_quality_document_link($invoice)); ?></span>
     494                                        <span><?php echo esc_html($time ? date_i18n('j M Y', $time) : $invoice['date']); ?></span>
     495                                        <span class="num"><?php echo esc_html($money($invoice['total_amount'])); ?></span>
     496                                        <span class="ultibuda-muted"><?php echo esc_html((!empty($invoice['invoice_number']) && $invoice['invoice_number'] !== 'N/A') ? $invoice['invoice_number'] : '–'); ?></span>
     497                                        <span><?php $action_button('delete_invoice', $invoice['id'], __('Delete this one', 'ultimate-business-dashboard'), __('Delete this invoice? This cannot be undone.', 'ultimate-business-dashboard')); ?></span>
    449498                                    </div>
    450499                                <?php endforeach; ?>
    451500                            </td>
    452                             <td><?php echo $pair['reason'] === 'number' ? esc_html__('Same invoice number', 'ultimate-business-dashboard') : esc_html__('Same amount, close dates', 'ultimate-business-dashboard'); ?></td>
     501                            <td><?php echo $pair['reason'] === 'number' ? esc_html__('Same invoice number and amount', 'ultimate-business-dashboard') : esc_html__('Same amount, close dates', 'ultimate-business-dashboard'); ?></td>
    453502                            <td><?php $action_button('ignore_duplicate', $pair['key'], __('Not a duplicate', 'ultimate-business-dashboard')); ?></td>
    454503                        </tr>
    … …  
    465514                </p>
    466515            <?php endif; ?>
     516        <?php endif; ?>
     517
     518        <?php if ($shared_numbers) : ?>
     519            <h2>
     520                <?php
     521                /* translators: %d: number of suppliers */
     522                echo esc_html(sprintf(__('Same number, different amounts (%d)', 'ultimate-business-dashboard'), count($shared_numbers)));
     523                ?>
     524            </h2>
     525            <p class="description"><?php esc_html_e('Several documents of these suppliers share the same number with different amounts. It is often normal (instalments, credit notes), but a payment statement imported next to the invoice it settles is counted twice as an expense: open an example and check that each document is a real invoice.', 'ultimate-business-dashboard'); ?></p>
     526            <div class="ultibuda-quality-table-wrap">
     527                <table class="widefat striped">
     528                    <thead><tr>
     529                        <th><?php esc_html_e('Supplier', 'ultimate-business-dashboard'); ?></th>
     530                        <th><?php esc_html_e('Numbers concerned', 'ultimate-business-dashboard'); ?></th>
     531                        <th><?php esc_html_e('Example', 'ultimate-business-dashboard'); ?></th>
     532                        <th><?php esc_html_e('Actions', 'ultimate-business-dashboard'); ?></th>
     533                    </tr></thead>
     534                    <tbody>
     535                    <?php foreach ($shared_numbers as $entry) : ?>
     536                        <tr>
     537                            <td><?php echo esc_html($entry['supplier']); ?></td>
     538                            <td>
     539                                <?php
     540                                /* translators: 1: number of invoice numbers, 2: number of invoices */
     541                                echo esc_html(sprintf(_n('%1$s number (%2$s invoices)', '%1$s numbers (%2$s invoices)', $entry['numbers'], 'ultimate-business-dashboard'), ultibuda_number($entry['numbers'], 0), ultibuda_number($entry['invoices'], 0)));
     542                                ?>
     543                            </td>
     544                            <td><a href="<?php echo esc_url(add_query_arg(['page' => 'ultibuda-invoices', 's' => $entry['example']], admin_url('admin.php'))); ?>"><?php echo esc_html($entry['example']); ?></a></td>
     545                            <td>
     546                                <a class="button button-small" href="<?php echo esc_url(add_query_arg(['page' => 'ultibuda-invoices', 's' => $entry['supplier']], admin_url('admin.php'))); ?>"><?php esc_html_e('See the invoices', 'ultimate-business-dashboard'); ?></a>
     547                                <?php $action_button('ignore_shared_number', $entry['key'], __('This is normal', 'ultimate-business-dashboard')); ?>
     548                            </td>
     549                        </tr>
     550                    <?php endforeach; ?>
     551                    </tbody>
     552                </table>
     553            </div>
    467554        <?php endif; ?>
    468555
  • ultimate-business-dashboard/trunk/languages/ultimate-business-dashboard-fr_FR.po

    r3803022 r3803495  
    44"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ultimate-business-"
    55"dashboard\n"
    6 "POT-Creation-Date: 2026-11-15T09:59:02+00:00\n"
     6"POT-Creation-Date: 2026-11-15T15:30:11+00:00\n"
    77"PO-Revision-Date: 2025-11-22 17:17+0100\n"
    88"Last-Translator: \n"
    … …  
    7777#: includes/categories.php:17 includes/dashboard.php:263 includes/data.php:16
    7878#: includes/imports.php:451 includes/imports.php:535 includes/invoices.php:133
    79 #: includes/quality.php:358 includes/quickbooks.php:25
     79#: includes/quality.php:406 includes/quickbooks.php:25
    8080#: includes/quickbooks.php:511 includes/reports.php:17 includes/settings.php:44
    8181#: includes/user-management.php:17 includes/zapier.php:17
    … …  
    159159"Categories are created from your imports (Dext, CSV, QuickBooks). For each "
    160160"one, choose how it is counted in your results."
    161 msgstr "Les catégories sont créées à partir de vos imports (Dext, CSV, QuickBooks). Pour chacune, choisissez comment elle compte dans vos résultats."
     161msgstr ""
     162"Les catégories sont créées à partir de vos imports (Dext, CSV, QuickBooks). "
     163"Pour chacune, choisissez comment elle compte dans vos résultats."
    162164
    163165#: includes/categories.php:209
    … …  
    175177"of goods sold, adjusted by inventory), occupancy costs (rent, energy…), "
    176178"other operating expenses, or exceptional expenses (excluded from the EBE)."
    177 msgstr "la ligne du compte de résultat où apparaissent les factures : achats de marchandises (coût des marchandises vendues, corrigé du stock), coûts d’occupation (loyer, énergie…), autres charges d’exploitation, ou charges exceptionnelles (hors EBE)."
     179msgstr ""
     180"la ligne du compte de résultat où apparaissent les factures : achats de "
     181"marchandises (coût des marchandises vendues, corrigé du stock), coûts "
     182"d’occupation (loyer, énergie…), autres charges d’exploitation, ou charges "
     183"exceptionnelles (hors EBE)."
    178184
    179185#: includes/categories.php:212 includes/categories.php:247
    … …  
    187193"fixed or variable cost, used for the contribution margin and the break-even "
    188194"point. Purchases of goods are always variable."
    189 msgstr "coût fixe ou variable, utilisé pour la marge sur coûts variables et le point mort. Les achats de marchandises sont toujours variables."
     195msgstr ""
     196"coût fixe ou variable, utilisé pour la marge sur coûts variables et le point "
     197"mort. Les achats de marchandises sont toujours variables."
    190198
    191199#: includes/categories.php:213 includes/categories.php:245
    … …  
    207215"The Uncategorized category is the default for unassigned invoices and cannot "
    208216"be deleted."
    209 msgstr "La catégorie Non classé reçoit les factures sans catégorie et ne peut pas être supprimée."
     217msgstr ""
     218"La catégorie Non classé reçoit les factures sans catégorie et ne peut pas "
     219"être supprimée."
    210220
    211221#: includes/categories.php:223 includes/categories.php:294
    … …  
    257267
    258268#: includes/categories.php:244 includes/invoices.php:436
    259 #: includes/quality.php:431 ultimate-business-dashboard.php:138
     269#: includes/quality.php:480 ultimate-business-dashboard.php:138
    260270msgid "Invoices"
    261271msgstr "Factures"
    … …  
    699709"Monthly amounts that do not come from invoices, excluding VAT. They feed the "
    700710"Dashboard and the Ratios & Reports."
    701 msgstr "Montants mensuels qui ne viennent pas des factures, hors TVA. Ils alimentent le tableau de bord et les Ratios et Rapports."
     711msgstr ""
     712"Montants mensuels qui ne viennent pas des factures, hors TVA. Ils alimentent "
     713"le tableau de bord et les Ratios et Rapports."
    702714
    703715#: includes/data.php:136
    … …  
    823835
    824836#. translators: %s: number. Percentage format; French uses a non-breaking space before the % sign.
    825 #: includes/format.php:93
     837#: includes/format.php:110
    826838msgctxt "percentage"
    827839msgid "%s%%"
    828840msgstr "%s %%"
    829841
    830 #: includes/format.php:123
     842#: includes/format.php:140
    831843msgid "No comparison available"
    832844msgstr "Pas de comparaison possible"
    833845
    834 #: includes/format.php:126 ultimate-business-dashboard.php:352
     846#: includes/format.php:144
     847msgid "Variation too large to be meaningful (very small comparison base)"
     848msgstr ""
     849"Variation trop forte pour être significative (base de comparaison très "
     850"faible)"
     851
     852#: includes/format.php:144 includes/format.php:147
     853msgid "n/m"
     854msgstr "n.s."
     855
     856#: includes/format.php:147 ultimate-business-dashboard.php:352
    835857msgid "Variation not meaningful (transition from loss to profit or vice versa)"
    836858msgstr ""
    837859"Variation non significative (transition d’une perte à un bénéfice ou vice "
    838860"versa)"
    839 
    840 #: includes/format.php:126
    841 msgid "n/m"
    842 msgstr "n.s."
    843861
    844862#: includes/import-header.php:12 ultimate-business-dashboard.php:142
    … …  
    850868msgstr "Vue d’ensemble"
    851869
    852 #: includes/import-tabs.php:13 ultimate-business-dashboard.php:532
     870#: includes/import-tabs.php:13 ultimate-business-dashboard.php:537
    853871msgid "Dext & Zapier"
    854872msgstr "Dext & Zapier"
    855873
    856 #: includes/import-tabs.php:14 ultimate-business-dashboard.php:533
     874#: includes/import-tabs.php:14 ultimate-business-dashboard.php:538
    857875msgid "Dext CSV"
    858876msgstr "CSV Dext"
    859877
    860 #: includes/import-tabs.php:15 ultimate-business-dashboard.php:534
     878#: includes/import-tabs.php:15 ultimate-business-dashboard.php:539
    861879msgid "Other CSV"
    862880msgstr "Autre CSV"
    863881
    864 #: includes/import-tabs.php:16 ultimate-business-dashboard.php:535
     882#: includes/import-tabs.php:16 ultimate-business-dashboard.php:540
    865883msgid "QuickBooks"
    866884msgstr "QuickBooks"
    … …  
    10231041
    10241042#: includes/imports.php:488 includes/imports.php:567 includes/invoices.php:484
    1025 #: includes/invoices.php:513 includes/quality.php:430 includes/quality.php:542
     1043#: includes/invoices.php:513 includes/quality.php:479 includes/quality.php:529
     1044#: includes/quality.php:629
    10261045msgid "Supplier"
    10271046msgstr "Fournisseur"
    … …  
    10511070
    10521071#: includes/imports.php:490 includes/imports.php:569 includes/invoices.php:486
    1053 #: includes/invoices.php:537 includes/quality.php:544
     1072#: includes/invoices.php:537 includes/quality.php:631
    10541073msgid "Net Amount"
    10551074msgstr "Montant net"
    … …  
    14311450msgstr "Sélectionner"
    14321451
    1433 #: includes/invoices.php:507 includes/quality.php:349
     1452#: includes/invoices.php:507 includes/quality.php:397
    14341453msgid "Open the invoice document"
    14351454msgstr "Ouvrir le document de la facture"
    … …  
    14641483msgstr[1] "Amortie · %d mois"
    14651484
    1466 #: includes/quality.php:367
     1485#: includes/quality.php:415
    14671486msgid "Invoice deleted."
    14681487msgstr "Facture supprimée."
    14691488
    1470 #: includes/quality.php:372
     1489#: includes/quality.php:420
    14711490msgid "Alert ignored."
    14721491msgstr "Alerte ignorée."
    14731492
    14741493#. translators: 1: number of invoices, 2: supplier name
    1475 #: includes/quality.php:379
     1494#: includes/quality.php:427
    14761495msgid "%1$d invoice now uses the supplier name \"%2$s\"."
    14771496msgid_plural "%1$d invoices now use the supplier name \"%2$s\"."
    … …  
    14791498msgstr[1] "%1$d factures portent désormais le nom de fournisseur « %2$s »."
    14801499
    1481 #: includes/quality.php:406 ultimate-business-dashboard.php:139
     1500#: includes/quality.php:455 ultimate-business-dashboard.php:139
    14821501msgid "Checks"
    14831502msgstr "Contrôles"
    14841503
    1485 #: includes/quality.php:407
     1504#: includes/quality.php:456
    14861505msgid ""
    14871506"Points to check before relying on your figures. Each alert can be ignored if "
    … …  
    14921511
    14931512#. translators: %d: number of alerts
    1494 #: includes/quality.php:415
     1513#: includes/quality.php:464
    14951514msgid "Possible duplicates (%d)"
    14961515msgstr "Doublons probables (%d)"
    14971516
    1498 #: includes/quality.php:419
     1517#: includes/quality.php:468
    14991518msgid "No possible duplicate."
    15001519msgstr "Aucun doublon probable."
    15011520
    15021521#. translators: %d: number of days
    1503 #: includes/quality.php:424
    1504 msgid ""
    1505 "Same supplier with the same invoice number, or with the same total amount "
    1506 "less than %d days apart."
    1507 msgstr ""
    1508 "Même fournisseur avec le même numéro de facture, ou avec le même montant TTC "
    1509 "à moins de %d jours d’écart."
    1510 
    1511 #: includes/quality.php:432
     1522#: includes/quality.php:473
     1523msgid ""
     1524"Same supplier with the same invoice number and amount, or with the same "
     1525"total amount less than %d days apart."
     1526msgstr ""
     1527"Même fournisseur avec le même numéro de facture et le même montant, ou avec "
     1528"le même montant TTC à moins de %d jours d’écart."
     1529
     1530#: includes/quality.php:481
    15121531msgid "Reason"
    15131532msgstr "Motif"
    15141533
    1515 #: includes/quality.php:433 includes/quality.php:498 includes/quality.php:546
    1516 #: includes/user-management.php:213
     1534#: includes/quality.php:482 includes/quality.php:532 includes/quality.php:585
     1535#: includes/quality.php:633 includes/user-management.php:213
    15171536msgid "Actions"
    15181537msgstr "Actions"
    15191538
    1520 #: includes/quality.php:448
     1539#: includes/quality.php:497
    15211540msgid "Delete this one"
    15221541msgstr "Supprimer celle-ci"
    15231542
    1524 #: includes/quality.php:448
     1543#: includes/quality.php:497
    15251544msgid "Delete this invoice? This cannot be undone."
    15261545msgstr "Supprimer cette facture ? Cette action est irréversible."
    15271546
    1528 #: includes/quality.php:452
    1529 msgid "Same invoice number"
    1530 msgstr "Même numéro de facture"
    1531 
    1532 #: includes/quality.php:452
     1547#: includes/quality.php:501
     1548msgid "Same invoice number and amount"
     1549msgstr "Même numéro et même montant"
     1550
     1551#: includes/quality.php:501
    15331552msgid "Same amount, close dates"
    15341553msgstr "Même montant, dates proches"
    15351554
    1536 #: includes/quality.php:453
     1555#: includes/quality.php:502
    15371556msgid "Not a duplicate"
    15381557msgstr "Pas un doublon"
    15391558
    15401559#. translators: %d: number of rows shown
    1541 #: includes/quality.php:463
     1560#: includes/quality.php:512
    15421561msgid "Only the first %d are shown."
    15431562msgstr "Seuls les %d premiers sont affichés."
    15441563
     1564#. translators: %d: number of suppliers
     1565#: includes/quality.php:522
     1566msgid "Same number, different amounts (%d)"
     1567msgstr "Même numéro, montants différents (%d)"
     1568
     1569#: includes/quality.php:525
     1570msgid ""
     1571"Several documents of these suppliers share the same number with different "
     1572"amounts. It is often normal (instalments, credit notes), but a payment "
     1573"statement imported next to the invoice it settles is counted twice as an "
     1574"expense: open an example and check that each document is a real invoice."
     1575msgstr ""
     1576"Chez ces fournisseurs, plusieurs documents portent le même numéro avec des "
     1577"montants différents. C’est souvent normal (acomptes, avoirs), mais un relevé "
     1578"de paiement importé à côté de la facture qu’il règle compte deux fois en "
     1579"charge : ouvrez un exemple et vérifiez que chaque document est bien une "
     1580"facture."
     1581
     1582#: includes/quality.php:530
     1583msgid "Numbers concerned"
     1584msgstr "Numéros concernés"
     1585
     1586#: includes/quality.php:531
     1587msgid "Example"
     1588msgstr "Exemple"
     1589
     1590#. translators: 1: number of invoice numbers, 2: number of invoices
     1591#: includes/quality.php:541
     1592msgid "%1$s number (%2$s invoices)"
     1593msgid_plural "%1$s numbers (%2$s invoices)"
     1594msgstr[0] "%1$s numéro (%2$s factures)"
     1595msgstr[1] "%1$s numéros (%2$s factures)"
     1596
     1597#: includes/quality.php:546
     1598msgid "See the invoices"
     1599msgstr "Voir les factures"
     1600
     1601#: includes/quality.php:547
     1602msgid "This is normal"
     1603msgstr "C’est normal"
     1604
    15451605#. translators: %d: number of invoices
    1546 #: includes/quality.php:472
     1606#: includes/quality.php:559
    15471607msgid "Uncategorized invoices (%d)"
    15481608msgstr "Factures non catégorisées (%d)"
    15491609
    1550 #: includes/quality.php:476
     1610#: includes/quality.php:563
    15511611msgid "All invoices have a category."
    15521612msgstr "Toutes les factures ont une catégorie."
    15531613
    1554 #: includes/quality.php:479
     1614#: includes/quality.php:566
    15551615msgid ""
    15561616"These invoices are counted in \"Other Invoices\" and as unclassified costs."
    … …  
    15581618"Ces factures sont comptées dans « Autres factures » et en coûts non classés."
    15591619
    1560 #: includes/quality.php:480
     1620#: includes/quality.php:567
    15611621msgid "Show them"
    15621622msgstr "Les afficher"
    15631623
    15641624#. translators: %d: number of groups
    1565 #: includes/quality.php:487
     1625#: includes/quality.php:574
    15661626msgid "Suppliers written in several ways (%d)"
    15671627msgstr "Fournisseurs écrits de plusieurs façons (%d)"
    15681628
    1569 #: includes/quality.php:491
     1629#: includes/quality.php:578
    15701630msgid "No similar supplier names."
    15711631msgstr "Aucun nom de fournisseur similaire."
    15721632
    1573 #: includes/quality.php:493
     1633#: includes/quality.php:580
    15741634msgid "Choose the name to keep: all the invoices of the group will use it."
    15751635msgstr ""
    15761636"Choisissez le nom à garder : toutes les factures du groupe le prendront."
    15771637
    1578 #: includes/quality.php:497
     1638#: includes/quality.php:584
    15791639msgid "Names found (invoices)"
    15801640msgstr "Noms trouvés (factures)"
    15811641
    1582 #: includes/quality.php:519
     1642#: includes/quality.php:606
    15831643msgid "Use this name"
    15841644msgstr "Garder ce nom"
    15851645
    1586 #: includes/quality.php:520
     1646#: includes/quality.php:607
    15871647msgid "Different suppliers"
    15881648msgstr "Fournisseurs différents"
    15891649
    15901650#. translators: %d: number of invoices
    1591 #: includes/quality.php:532
     1651#: includes/quality.php:619
    15921652msgid "Unusual amounts (%d)"
    15931653msgstr "Montants inhabituels (%d)"
    15941654
    1595 #: includes/quality.php:536
     1655#: includes/quality.php:623
    15961656msgid "No unusual amount over the last 12 months."
    15971657msgstr "Aucun montant inhabituel sur les 12 derniers mois."
    15981658
    1599 #: includes/quality.php:538
     1659#: includes/quality.php:625
    16001660msgid ""
    16011661"Invoices of the last 12 months more than 3 times the usual amount (median) "
    … …  
    16051665"(médiane) du fournisseur."
    16061666
    1607 #: includes/quality.php:543
     1667#: includes/quality.php:630
    16081668msgid "Invoice"
    16091669msgstr "Facture"
    16101670
    1611 #: includes/quality.php:545
     1671#: includes/quality.php:632
    16121672msgid "Usual amount"
    16131673msgstr "Montant habituel"
    16141674
    1615 #: includes/quality.php:555
     1675#: includes/quality.php:642
    16161676msgid "Checked"
    16171677msgstr "Vérifié"
    16181678
    16191679#. translators: 1: number of points, 2: opening link, 3: closing link
    1620 #: includes/quality.php:585
     1680#: includes/quality.php:672
    16211681msgid ""
    16221682"%1$d point to check in your data (duplicates, categories, suppliers, "
    … …  
    19772037"The largest expense items of the period, including the costs entered in the "
    19782038"Data page."
    1979 msgstr "Les principaux postes de dépenses de la période, y compris les charges saisies dans la page Données."
     2039msgstr ""
     2040"Les principaux postes de dépenses de la période, y compris les charges "
     2041"saisies dans la page Données."
    19802042
    19812043#: includes/reports.php:277 ultimate-business-dashboard.php:360
    … …  
    19912053"Costs entered in the Data page, amortizations and provisions are fixed; the "
    19922054"cost of goods sold is variable. Invoices follow the type of their category."
    1993 msgstr "Les charges saisies dans la page Données, les amortissements et les provisions sont fixes ; le coût des marchandises vendues est variable. Les factures suivent le type de leur catégorie."
     2055msgstr ""
     2056"Les charges saisies dans la page Données, les amortissements et les "
     2057"provisions sont fixes ; le coût des marchandises vendues est variable. Les "
     2058"factures suivent le type de leur catégorie."
    19942059
    19952060#. translators: 1: break-even revenue, 2: percentage of the actual revenue
    19962061#: includes/reports.php:309
    19972062msgid "Break-even point: %1$s of revenue (%2$s of the actual revenue)."
    1998 msgstr "Point mort : %1$s de chiffre d’affaires (%2$s du chiffre d’affaires réel)."
     2063msgstr ""
     2064"Point mort : %1$s de chiffre d’affaires (%2$s du chiffre d’affaires réel)."
    19992065
    20002066#: includes/reports.php:314
    … …  
    26332699msgstr "Non connecté"
    26342700
    2635 #: ultimate-business-dashboard.php:532
     2701#: ultimate-business-dashboard.php:534
     2702msgctxt "import status"
     2703msgid "Configured"
     2704msgstr "Configuré"
     2705
     2706#: ultimate-business-dashboard.php:537
    26362707msgid ""
    26372708"Automatic import: each invoice processed in Dext is sent here by Zapier."
    2638 msgstr "Import automatique : chaque facture traitée dans Dext est envoyée ici par Zapier."
    2639 
    2640 #: ultimate-business-dashboard.php:532
     2709msgstr ""
     2710"Import automatique : chaque facture traitée dans Dext est envoyée ici par "
     2711"Zapier."
     2712
     2713#: ultimate-business-dashboard.php:537 ultimate-business-dashboard.php:540
     2714msgid "Manage"
     2715msgstr "Gérer"
     2716
     2717#: ultimate-business-dashboard.php:537
    26412718msgid "Set up"
    26422719msgstr "Configurer"
    26432720
    2644 #: ultimate-business-dashboard.php:533
     2721#: ultimate-business-dashboard.php:538
    26452722msgid "Import a CSV export from Dext (\"Dext Prepare Default\" format)."
    26462723msgstr "Importer un export CSV de Dext (format « Dext Prepare Default »)."
    26472724
    2648 #: ultimate-business-dashboard.php:533 ultimate-business-dashboard.php:534
     2725#: ultimate-business-dashboard.php:538 ultimate-business-dashboard.php:539
    26492726msgid "Import a file"
    26502727msgstr "Importer un fichier"
    26512728
    2652 #: ultimate-business-dashboard.php:534
     2729#: ultimate-business-dashboard.php:539
    26532730msgid "Import invoices from any other tool with a simple CSV file."
    26542731msgstr "Importer les factures de tout autre outil avec un simple fichier CSV."
    26552732
    2656 #: ultimate-business-dashboard.php:535
     2733#: ultimate-business-dashboard.php:540
    26572734msgid "Connect QuickBooks Online to import supplier bills every hour."
    2658 msgstr "Connecter QuickBooks Online pour importer les factures fournisseurs toutes les heures."
    2659 
    2660 #: ultimate-business-dashboard.php:535
    2661 msgid "Manage"
    2662 msgstr "Gérer"
    2663 
    2664 #: ultimate-business-dashboard.php:535
     2735msgstr ""
     2736"Connecter QuickBooks Online pour importer les factures fournisseurs toutes "
     2737"les heures."
     2738
     2739#: ultimate-business-dashboard.php:540
    26652740msgid "Connect"
    26662741msgstr "Connecter"
    26672742
    2668 #: ultimate-business-dashboard.php:540
     2743#: ultimate-business-dashboard.php:545
    26692744msgid ""
    26702745"Choose how your supplier invoices reach the dashboard. Duplicates are "
    26712746"ignored automatically, whatever the method."
    2672 msgstr "Choisissez comment vos factures fournisseurs arrivent dans le tableau de bord. Les doublons sont ignorés automatiquement, quelle que soit la méthode."
     2747msgstr ""
     2748"Choisissez comment vos factures fournisseurs arrivent dans le tableau de "
     2749"bord. Les doublons sont ignorés automatiquement, quelle que soit la méthode."
     2750
     2751#. translators: 1: date and time, 2: total number of invoices
     2752#: ultimate-business-dashboard.php:551
     2753msgid "Last invoice added on %1$s · %2$s invoices in total"
     2754msgstr "Dernière facture ajoutée le %1$s · %2$s factures au total"
    26732755
    26742756#~ msgid ""
  • ultimate-business-dashboard/trunk/languages/ultimate-business-dashboard.pot

    r3803022 r3803495  
    33msgid ""
    44msgstr ""
    5 "Project-Id-Version: Ultimate Business Dashboard 2.6\n"
     5"Project-Id-Version: Ultimate Business Dashboard 2.7.1\n"
    66"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ultimate-business-dashboard\n"
    77"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    … …  
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"Content-Transfer-Encoding: 8bit\n"
    12 "POT-Creation-Date: 2026-11-15T09:59:02+00:00\n"
     12"POT-Creation-Date: 2026-11-15T15:30:11+00:00\n"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.11.0\n"
    … …  
    8585#: includes/imports.php:535
    8686#: includes/invoices.php:133
    87 #: includes/quality.php:358
     87#: includes/quality.php:406
    8888#: includes/quickbooks.php:25
    8989#: includes/quickbooks.php:511
    … …  
    237237#: includes/categories.php:244
    238238#: includes/invoices.php:436
    239 #: includes/quality.php:431
     239#: includes/quality.php:480
    240240#: ultimate-business-dashboard.php:138
    241241msgid "Invoices"
    … …  
    839839
    840840#. translators: %s: number. Percentage format; French uses a non-breaking space before the % sign.
    841 #: includes/format.php:93
     841#: includes/format.php:110
    842842msgctxt "percentage"
    843843msgid "%s%%"
    844844msgstr ""
    845845
    846 #: includes/format.php:123
     846#: includes/format.php:140
    847847msgid "No comparison available"
    848848msgstr ""
    849849
    850 #: includes/format.php:126
     850#: includes/format.php:144
     851msgid "Variation too large to be meaningful (very small comparison base)"
     852msgstr ""
     853
     854#: includes/format.php:144
     855#: includes/format.php:147
     856msgid "n/m"
     857msgstr ""
     858
     859#: includes/format.php:147
    851860#: ultimate-business-dashboard.php:352
    852861msgid "Variation not meaningful (transition from loss to profit or vice versa)"
    853 msgstr ""
    854 
    855 #: includes/format.php:126
    856 msgid "n/m"
    857862msgstr ""
    858863
    … …  
    867872
    868873#: includes/import-tabs.php:13
    869 #: ultimate-business-dashboard.php:532
     874#: ultimate-business-dashboard.php:537
    870875msgid "Dext & Zapier"
    871876msgstr ""
    872877
    873878#: includes/import-tabs.php:14
    874 #: ultimate-business-dashboard.php:533
     879#: ultimate-business-dashboard.php:538
    875880msgid "Dext CSV"
    876881msgstr ""
    877882
    878883#: includes/import-tabs.php:15
    879 #: ultimate-business-dashboard.php:534
     884#: ultimate-business-dashboard.php:539
    880885msgid "Other CSV"
    881886msgstr ""
    882887
    883888#: includes/import-tabs.php:16
    884 #: ultimate-business-dashboard.php:535
     889#: ultimate-business-dashboard.php:540
    885890msgid "QuickBooks"
    886891msgstr ""
    … …  
    10361041#: includes/invoices.php:484
    10371042#: includes/invoices.php:513
    1038 #: includes/quality.php:430
    1039 #: includes/quality.php:542
     1043#: includes/quality.php:479
     1044#: includes/quality.php:529
     1045#: includes/quality.php:629
    10401046msgid "Supplier"
    10411047msgstr ""
    … …  
    10721078#: includes/invoices.php:486
    10731079#: includes/invoices.php:537
    1074 #: includes/quality.php:544
     1080#: includes/quality.php:631
    10751081msgid "Net Amount"
    10761082msgstr ""
    … …  
    14111417
    14121418#: includes/invoices.php:507
    1413 #: includes/quality.php:349
     1419#: includes/quality.php:397
    14141420msgid "Open the invoice document"
    14151421msgstr ""
    … …  
    14461452msgstr[1] ""
    14471453
    1448 #: includes/quality.php:367
     1454#: includes/quality.php:415
    14491455msgid "Invoice deleted."
    14501456msgstr ""
    14511457
    1452 #: includes/quality.php:372
     1458#: includes/quality.php:420
    14531459msgid "Alert ignored."
    14541460msgstr ""
    14551461
    14561462#. translators: 1: number of invoices, 2: supplier name
    1457 #: includes/quality.php:379
     1463#: includes/quality.php:427
    14581464msgid "%1$d invoice now uses the supplier name \"%2$s\"."
    14591465msgid_plural "%1$d invoices now use the supplier name \"%2$s\"."
    … …  
    14611467msgstr[1] ""
    14621468
    1463 #: includes/quality.php:406
     1469#: includes/quality.php:455
    14641470#: ultimate-business-dashboard.php:139
    14651471msgid "Checks"
    14661472msgstr ""
    14671473
    1468 #: includes/quality.php:407
     1474#: includes/quality.php:456
    14691475msgid "Points to check before relying on your figures. Each alert can be ignored if it is not a problem."
    14701476msgstr ""
    14711477
    14721478#. translators: %d: number of alerts
    1473 #: includes/quality.php:415
     1479#: includes/quality.php:464
    14741480msgid "Possible duplicates (%d)"
    14751481msgstr ""
    14761482
    1477 #: includes/quality.php:419
     1483#: includes/quality.php:468
    14781484msgid "No possible duplicate."
    14791485msgstr ""
    14801486
    14811487#. translators: %d: number of days
    1482 #: includes/quality.php:424
    1483 msgid "Same supplier with the same invoice number, or with the same total amount less than %d days apart."
    1484 msgstr ""
    1485 
    1486 #: includes/quality.php:432
     1488#: includes/quality.php:473
     1489msgid "Same supplier with the same invoice number and amount, or with the same total amount less than %d days apart."
     1490msgstr ""
     1491
     1492#: includes/quality.php:481
    14871493msgid "Reason"
    14881494msgstr ""
    14891495
    1490 #: includes/quality.php:433
    1491 #: includes/quality.php:498
    1492 #: includes/quality.php:546
     1496#: includes/quality.php:482
     1497#: includes/quality.php:532
     1498#: includes/quality.php:585
     1499#: includes/quality.php:633
    14931500#: includes/user-management.php:213
    14941501msgid "Actions"
    14951502msgstr ""
    14961503
    1497 #: includes/quality.php:448
     1504#: includes/quality.php:497
    14981505msgid "Delete this one"
    14991506msgstr ""
    15001507
    1501 #: includes/quality.php:448
     1508#: includes/quality.php:497
    15021509msgid "Delete this invoice? This cannot be undone."
    15031510msgstr ""
    15041511
    1505 #: includes/quality.php:452
    1506 msgid "Same invoice number"
    1507 msgstr ""
    1508 
    1509 #: includes/quality.php:452
     1512#: includes/quality.php:501
     1513msgid "Same invoice number and amount"
     1514msgstr ""
     1515
     1516#: includes/quality.php:501
    15101517msgid "Same amount, close dates"
    15111518msgstr ""
    15121519
    1513 #: includes/quality.php:453
     1520#: includes/quality.php:502
    15141521msgid "Not a duplicate"
    15151522msgstr ""
    15161523
    15171524#. translators: %d: number of rows shown
    1518 #: includes/quality.php:463
     1525#: includes/quality.php:512
    15191526msgid "Only the first %d are shown."
    15201527msgstr ""
    15211528
     1529#. translators: %d: number of suppliers
     1530#: includes/quality.php:522
     1531msgid "Same number, different amounts (%d)"
     1532msgstr ""
     1533
     1534#: includes/quality.php:525
     1535msgid "Several documents of these suppliers share the same number with different amounts. It is often normal (instalments, credit notes), but a payment statement imported next to the invoice it settles is counted twice as an expense: open an example and check that each document is a real invoice."
     1536msgstr ""
     1537
     1538#: includes/quality.php:530
     1539msgid "Numbers concerned"
     1540msgstr ""
     1541
     1542#: includes/quality.php:531
     1543msgid "Example"
     1544msgstr ""
     1545
     1546#. translators: 1: number of invoice numbers, 2: number of invoices
     1547#: includes/quality.php:541
     1548msgid "%1$s number (%2$s invoices)"
     1549msgid_plural "%1$s numbers (%2$s invoices)"
     1550msgstr[0] ""
     1551msgstr[1] ""
     1552
     1553#: includes/quality.php:546
     1554msgid "See the invoices"
     1555msgstr ""
     1556
     1557#: includes/quality.php:547
     1558msgid "This is normal"
     1559msgstr ""
     1560
    15221561#. translators: %d: number of invoices
    1523 #: includes/quality.php:472
     1562#: includes/quality.php:559
    15241563msgid "Uncategorized invoices (%d)"
    15251564msgstr ""
    15261565
    1527 #: includes/quality.php:476
     1566#: includes/quality.php:563
    15281567msgid "All invoices have a category."
    15291568msgstr ""
    15301569
    1531 #: includes/quality.php:479
     1570#: includes/quality.php:566
    15321571msgid "These invoices are counted in \"Other Invoices\" and as unclassified costs."
    15331572msgstr ""
    15341573
    1535 #: includes/quality.php:480
     1574#: includes/quality.php:567
    15361575msgid "Show them"
    15371576msgstr ""
    15381577
    15391578#. translators: %d: number of groups
    1540 #: includes/quality.php:487
     1579#: includes/quality.php:574
    15411580msgid "Suppliers written in several ways (%d)"
    15421581msgstr ""
    15431582
    1544 #: includes/quality.php:491
     1583#: includes/quality.php:578
    15451584msgid "No similar supplier names."
    15461585msgstr ""
    15471586
    1548 #: includes/quality.php:493
     1587#: includes/quality.php:580
    15491588msgid "Choose the name to keep: all the invoices of the group will use it."
    15501589msgstr ""
    15511590
    1552 #: includes/quality.php:497
     1591#: includes/quality.php:584
    15531592msgid "Names found (invoices)"
    15541593msgstr ""
    15551594
    1556 #: includes/quality.php:519
     1595#: includes/quality.php:606
    15571596msgid "Use this name"
    15581597msgstr ""
    15591598
    1560 #: includes/quality.php:520
     1599#: includes/quality.php:607
    15611600msgid "Different suppliers"
    15621601msgstr ""
    15631602
    15641603#. translators: %d: number of invoices
    1565 #: includes/quality.php:532
     1604#: includes/quality.php:619
    15661605msgid "Unusual amounts (%d)"
    15671606msgstr ""
    15681607
    1569 #: includes/quality.php:536
     1608#: includes/quality.php:623
    15701609msgid "No unusual amount over the last 12 months."
    15711610msgstr ""
    15721611
    1573 #: includes/quality.php:538
     1612#: includes/quality.php:625
    15741613msgid "Invoices of the last 12 months more than 3 times the usual amount (median) of the supplier."
    15751614msgstr ""
    15761615
    1577 #: includes/quality.php:543
     1616#: includes/quality.php:630
    15781617msgid "Invoice"
    15791618msgstr ""
    15801619
    1581 #: includes/quality.php:545
     1620#: includes/quality.php:632
    15821621msgid "Usual amount"
    15831622msgstr ""
    15841623
    1585 #: includes/quality.php:555
     1624#: includes/quality.php:642
    15861625msgid "Checked"
    15871626msgstr ""
    15881627
    15891628#. translators: 1: number of points, 2: opening link, 3: closing link
    1590 #: includes/quality.php:585
     1629#: includes/quality.php:672
    15911630msgid "%1$d point to check in your data (duplicates, categories, suppliers, amounts). %2$sSee the checks%3$s"
    15921631msgid_plural "%1$d points to check in your data (duplicates, categories, suppliers, amounts). %2$sSee the checks%3$s"
    … …  
    24202459msgstr ""
    24212460
    2422 #: ultimate-business-dashboard.php:532
     2461#: ultimate-business-dashboard.php:534
     2462msgctxt "import status"
     2463msgid "Configured"
     2464msgstr ""
     2465
     2466#: ultimate-business-dashboard.php:537
    24232467msgid "Automatic import: each invoice processed in Dext is sent here by Zapier."
    24242468msgstr ""
    24252469
    2426 #: ultimate-business-dashboard.php:532
     2470#: ultimate-business-dashboard.php:537
     2471#: ultimate-business-dashboard.php:540
     2472msgid "Manage"
     2473msgstr ""
     2474
     2475#: ultimate-business-dashboard.php:537
    24272476msgid "Set up"
    24282477msgstr ""
    24292478
    2430 #: ultimate-business-dashboard.php:533
     2479#: ultimate-business-dashboard.php:538
    24312480msgid "Import a CSV export from Dext (\"Dext Prepare Default\" format)."
    24322481msgstr ""
    24332482
    2434 #: ultimate-business-dashboard.php:533
    2435 #: ultimate-business-dashboard.php:534
     2483#: ultimate-business-dashboard.php:538
     2484#: ultimate-business-dashboard.php:539
    24362485msgid "Import a file"
    24372486msgstr ""
    24382487
    2439 #: ultimate-business-dashboard.php:534
     2488#: ultimate-business-dashboard.php:539
    24402489msgid "Import invoices from any other tool with a simple CSV file."
    24412490msgstr ""
    24422491
    2443 #: ultimate-business-dashboard.php:535
     2492#: ultimate-business-dashboard.php:540
    24442493msgid "Connect QuickBooks Online to import supplier bills every hour."
    24452494msgstr ""
    24462495
    2447 #: ultimate-business-dashboard.php:535
    2448 msgid "Manage"
    2449 msgstr ""
    2450 
    2451 #: ultimate-business-dashboard.php:535
     2496#: ultimate-business-dashboard.php:540
    24522497msgid "Connect"
    24532498msgstr ""
    24542499
    2455 #: ultimate-business-dashboard.php:540
     2500#: ultimate-business-dashboard.php:545
    24562501msgid "Choose how your supplier invoices reach the dashboard. Duplicates are ignored automatically, whatever the method."
    24572502msgstr ""
     2503
     2504#. translators: 1: date and time, 2: total number of invoices
     2505#: ultimate-business-dashboard.php:551
     2506msgid "Last invoice added on %1$s · %2$s invoices in total"
     2507msgstr ""
  • ultimate-business-dashboard/trunk/readme.txt

    r3803022 r3803495  
    55Requires at least: 5.5
    66Tested up to: 7.1
    7 Stable tag: 2.7
     7Stable tag: 2.7.1
    88Requires PHP: 7.4
    99License: GPLv2 or later
    … …  
    9696
    9797== Changelog ==
     98= 2.7.1 - 15 November 2026 =
     99* Fixed: The EBITDA line of the dashboard chart was hidden behind the net result line when both were close
     100* Fixed: The currency symbol follows the user's language when its position is automatic (100 € in French, €100 in English), whatever the site language
     101* Fixed: Variations above 1,000 % (very small comparison base) are shown as "n/m"
     102* Improved: Checks: invoices with the same number but different amounts are no longer listed one pair at a time among duplicates, but in a separate "Same number, different amounts" section, one line per supplier (a payment statement imported next to its invoice would be counted twice)
     103* Improved: Icons and text centered in the buttons, wider category column on the Invoices page, aligned duplicate lines on the Checks page
     104* Improved: Imports page shows Dext & Zapier as configured and the date of the last invoice added
     105
    98106= 2.7 - 15 November 2026 =
    99107* Improved: Ratios & Reports redesigned: key figures as tiles compared with the same period of the previous year, ratios with the previous year, expense breakdown as sorted bars (top 8 + others) instead of a pie chart, fixed vs variable costs as a single bar with amounts and the break-even point, cleaner print / PDF
    … …  
    232240
    233241== Upgrade Notice ==
     242= 2.7.1 =
     243Visual fixes (chart, buttons, invoices, checks) and clearer duplicate checks.
     244
    234245= 2.7 =
    235246Redesigned Reports, Invoices (with mobile cards), Data (spreadsheet), Imports, Settings and Categories pages.
  • ultimate-business-dashboard/trunk/ultimate-business-dashboard.php

    r3803022 r3803495  
    44 * Plugin URI: https://tulipemedia.com/en/ultimate-business-dashboard/
    55 * Description: Turn your WordPress dashboard into a Financial Powerhouse.
    6  * Version: 2.7
     6 * Version: 2.7.1
    77 * Author: Ziyad Bachalany
    88 * Author URI: https://tulipemedia.com
    … …  
    1717
    1818// Define plugin constants
    19 define('ULTIBUDA_VERSION', '2.7');
     19define('ULTIBUDA_VERSION', '2.7.1');
    2020define('ULTIBUDA_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2121define('ULTIBUDA_PLUGIN_URL', plugin_dir_url(__FILE__));
    … …  
    529529        $qb_status = ['', __('Not connected', 'ultimate-business-dashboard')];
    530530    }
     531    // Zapier : envois antérieurs à la 2.7 absents du journal ; la clé API indique qu'il est configuré
     532    $zapier_status = $last('zapier');
     533    if ($zapier_status[0] === '' && get_option('ultibuda_webhook_api_key', '')) {
     534        $zapier_status = ['ok', _x('Configured', 'import status', 'ultimate-business-dashboard')];
     535    }
    531536    $cards = [
    532         ['ultibuda-setup-zapier', 'dashicons-update', __('Dext & Zapier', 'ultimate-business-dashboard'), __('Automatic import: each invoice processed in Dext is sent here by Zapier.', 'ultimate-business-dashboard'), $last('zapier'), __('Set up', 'ultimate-business-dashboard')],
     537        ['ultibuda-setup-zapier', 'dashicons-update', __('Dext & Zapier', 'ultimate-business-dashboard'), __('Automatic import: each invoice processed in Dext is sent here by Zapier.', 'ultimate-business-dashboard'), $zapier_status, $zapier_status[0] ? __('Manage', 'ultimate-business-dashboard') : __('Set up', 'ultimate-business-dashboard')],
    533538        ['ultibuda-dext-import', 'dashicons-media-spreadsheet', __('Dext CSV', 'ultimate-business-dashboard'), __('Import a CSV export from Dext ("Dext Prepare Default" format).', 'ultimate-business-dashboard'), $last('dext_csv'), __('Import a file', 'ultimate-business-dashboard')],
    534539        ['ultibuda-other-import', 'dashicons-media-text', __('Other CSV', 'ultimate-business-dashboard'), __('Import invoices from any other tool with a simple CSV file.', 'ultimate-business-dashboard'), $last('other_csv'), __('Import a file', 'ultimate-business-dashboard')],
    … …  
    539544    ?>
    540545        <p class="description"><?php esc_html_e('Choose how your supplier invoices reach the dashboard. Duplicates are ignored automatically, whatever the method.', 'ultimate-business-dashboard'); ?></p>
     546        <?php $last_added = ultibuda_last_invoice_added_time(); ?>
     547        <?php if ($last_added) : ?>
     548            <p>
     549                <?php
     550                /* translators: 1: date and time, 2: total number of invoices */
     551                echo esc_html(sprintf(__('Last invoice added on %1$s · %2$s invoices in total', 'ultimate-business-dashboard'), wp_date(get_option('date_format') . ' ' . get_option('time_format'), $last_added), number_format_i18n(ultibuda_count_invoices())));
     552                ?>
     553            </p>
     554        <?php endif; ?>
    541555        <div class="ultibuda-import-cards">
    542556            <?php foreach ($cards as $card) : ?>
Note: See TracChangeset for help on using the changeset viewer.