Ajustement detect tva

This commit is contained in:
Jean-Philippe Staelen 2026-01-26 10:59:25 +01:00
parent feaa43c289
commit 9ed2c2009e
2 changed files with 122 additions and 154 deletions

View File

@ -708,8 +708,7 @@ class PEPPOL_Plugin {
/** /**
* Détecte automatiquement les champs TVA lors de l'installation. * Détecte automatiquement les champs TVA lors de l'installation.
* Limite la recherche aux champs billing et shipping dans cet ordre. * Utilise la fonction helper PEPPOL_Woo_Helper::esi_get_vat_meta_keys().
* Utilise la fonction helper PEPPOL_Woo_Helper::esi_detect_vat_fields_billing_shipping().
* *
* @return string|null La clé du champ TVA détecté, ou null si aucun trouvé * @return string|null La clé du champ TVA détecté, ou null si aucun trouvé
*/ */
@ -721,66 +720,22 @@ class PEPPOL_Plugin {
} }
// Vérifier si WooCommerce est disponible // Vérifier si WooCommerce est disponible
if (!function_exists('wc_get_orders')) { if (!function_exists('wc_get_order')) {
// Marquer que la détection a été tentée (même si WooCommerce n'est pas disponible) // Marquer que la détection a été tentée (même si WooCommerce n'est pas disponible)
update_option('esi_peppol_vat_field_auto_detected', true); update_option('esi_peppol_vat_field_auto_detected', true);
return null; return null;
} }
// Récupérer les dernières commandes pour scanner les champs TVA $vat_keys = \ESI_PEPPOL\helpers\PEPPOL_Woo_Helper::esi_get_vat_meta_keys(50);
$orders = wc_get_orders([
'limit' => 50,
'orderby' => 'date',
'order' => 'DESC',
'status' => ['completed', 'processing', 'on-hold'],
]);
$vat_fields_found = [];
// Utiliser la fonction helper pour détecter les champs TVA dans chaque commande
foreach ($orders as $order) {
if (!$order instanceof \WC_Order) {
continue;
}
$fields = \ESI_PEPPOL\helpers\PEPPOL_Woo_Helper::esi_detect_vat_fields_billing_shipping($order);
// Compter les occurrences de chaque champ
foreach ($fields as $field) {
$key = $field['key'];
if (!isset($vat_fields_found[$key])) {
$vat_fields_found[$key] = [
'key' => $key,
'count' => 0,
'group' => $field['group'],
];
}
$vat_fields_found[$key]['count']++;
}
}
// Si aucun champ trouvé, marquer que la détection a été effectuée et retourner null // Si aucun champ trouvé, marquer que la détection a été effectuée et retourner null
if (empty($vat_fields_found)) { if (empty($vat_keys)) {
update_option('esi_peppol_vat_field_auto_detected', true); update_option('esi_peppol_vat_field_auto_detected', true);
return null; return null;
} }
// Trier : d'abord par groupe (billing avant shipping), puis par nombre d'occurrences // Prendre la première clé trouvée
usort($vat_fields_found, function ($a, $b) { $vat_field_key = reset($vat_keys);
// Priorité au groupe billing
if ($a['group'] === 'billing' && $b['group'] !== 'billing') {
return -1;
}
if ($a['group'] !== 'billing' && $b['group'] === 'billing') {
return 1;
}
// Si même groupe, trier par nombre d'occurrences
return $b['count'] - $a['count'];
});
// Prendre le premier champ trouvé (priorité billing)
$selected_field = reset($vat_fields_found);
$vat_field_key = $selected_field['key'];
// Sauvegarder le champ détecté // Sauvegarder le champ détecté
update_option('esi_peppol_vat_field_key', $vat_field_key); update_option('esi_peppol_vat_field_key', $vat_field_key);
@ -815,109 +770,14 @@ class PEPPOL_Plugin {
); );
} }
// Récupérer les dernières commandes pour scanner les champs TVA $vat_keys = \ESI_PEPPOL\helpers\PEPPOL_Woo_Helper::esi_get_vat_meta_keys();
$orders = wc_get_orders([ $vat_fields_found = array_map(function ($key) {
'limit' => 50, return [
'orderby' => 'date', 'key' => $key,
'order' => 'DESC', 'count' => 0,
'status' => ['completed', 'processing', 'on-hold'], 'sample_value' => null,
]); ];
}, $vat_keys);
$vat_fields_found = [];
foreach ($orders as $order) {
if (!$order instanceof \WC_Order) {
continue;
}
// Utiliser la fonction helper pour scanner tous les champs TVA possibles
$vat_candidates = [];
// Scanner les meta keys contenant vat/tva
foreach ($order->get_meta_data() as $meta) {
$k = (string) $meta->key;
if (preg_match('/\b(vat|tva)\b/i', $k) || preg_match('/(vat|tva)/i', $k)) {
$v = $meta->value;
if (is_string($v)) {
$v = trim($v);
}
if (!empty($v)) {
if (!isset($vat_candidates[$k])) {
$vat_candidates[$k] = [
'key' => $k,
'value' => $v,
'count' => 0,
];
}
$vat_candidates[$k]['count']++;
}
}
}
// Scanner les champs de checkout
if (function_exists('WC') && WC()->checkout()) {
$fields = WC()->checkout()->get_checkout_fields();
$patterns = ['vat', 'tva', 'btw', 'ust', 'mwst', 'piva', 'moms', 'mva'];
foreach ($fields as $group_fields) {
foreach ($group_fields as $key => $def) {
$k = strtolower($key);
$found = false;
foreach ($patterns as $p) {
if (strpos($k, $p) !== false) {
$found = true;
break;
}
}
if (!$found) {
$label = strtolower((string) ($def['label'] ?? ''));
foreach ($patterns as $p) {
if (preg_match('/\b' . $p . '\b/i', $label)) {
$found = true;
break;
}
}
}
if ($found) {
foreach ([$key, '_' . $key] as $meta_key) {
$val = $order->get_meta($meta_key, true);
if (!empty($val)) {
if (!isset($vat_candidates[$meta_key])) {
$vat_candidates[$meta_key] = [
'key' => $meta_key,
'value' => trim((string) $val),
'count' => 0,
];
}
$vat_candidates[$meta_key]['count']++;
}
}
}
}
}
}
// Ajouter les candidats trouvés
foreach ($vat_candidates as $candidate) {
$key = $candidate['key'];
if (!isset($vat_fields_found[$key])) {
$vat_fields_found[$key] = [
'key' => $key,
'count' => 0,
'sample_value' => $candidate['value'],
];
}
$vat_fields_found[$key]['count'] += $candidate['count'];
}
}
// Trier par nombre d'occurrences (décroissant)
usort($vat_fields_found, function ($a, $b) {
return $b['count'] - $a['count'];
});
wp_send_json_success([ wp_send_json_success([
'fields' => array_values($vat_fields_found), 'fields' => array_values($vat_fields_found),

View File

@ -187,6 +187,114 @@ class PEPPOL_Woo_Helper {
]; ];
} }
/**
* Retourne les IDs des commandes ayant un meta_key TVA/VAT.
* Compatible HPOS et legacy.
*
* @param int $limit 0 pour aucune limite.
* @param string $order ASC|DESC
* @param array $statuses Statuts Woo (sans préfixe wc-).
* @return int[]
*/
public static function esi_get_order_ids_with_vat_meta(
int $limit = 0,
string $order = 'DESC',
array $statuses = ['completed', 'processing', 'on-hold']
): array {
global $wpdb;
$order = strtoupper($order) === 'ASC' ? 'ASC' : 'DESC';
$like_tva = '%tva%';
$like_vat = '%vat%';
$exclude_key = 'is_vat_exempt';
$statuses = array_map(function ($status) {
$status = (string) $status;
return strpos($status, 'wc-') === 0 ? $status : 'wc-' . $status;
}, $statuses);
$status_placeholders = implode(',', array_fill(0, count($statuses), '%s'));
$is_hpos = class_exists('\Automattic\WooCommerce\Utilities\OrderUtil')
&& \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
if ($is_hpos) {
$orders_table = $wpdb->prefix . 'wc_orders';
$orders_meta_table = $wpdb->prefix . 'wc_orders_meta';
$sql = "
SELECT DISTINCT o.id
FROM {$orders_table} o
INNER JOIN {$orders_meta_table} om ON om.order_id = o.id
WHERE o.type = 'shop_order'
AND (om.meta_key LIKE %s OR om.meta_key LIKE %s)
AND om.meta_key != %s
AND o.status IN ({$status_placeholders})
ORDER BY o.date_created_gmt {$order}
";
} else {
$sql = "
SELECT DISTINCT p.ID
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
WHERE p.post_type = 'shop_order'
AND (pm.meta_key LIKE %s OR pm.meta_key LIKE %s)
AND pm.meta_key != %s
AND p.post_status IN ({$status_placeholders})
ORDER BY p.post_date {$order}
";
}
$params = array_merge([$like_tva, $like_vat, $exclude_key], $statuses);
if ($limit > 0) {
$sql .= ' LIMIT %d';
$params[] = $limit;
}
$prepared_sql = $wpdb->prepare($sql, $params);
$ids = $wpdb->get_col($prepared_sql);
return array_map('intval', $ids);
}
/**
* Retourne les meta_key TVA/VAT distinctes.
* Compatible HPOS et legacy.
*
* @param int $limit
* @return string[]
*/
public static function esi_get_vat_meta_keys( int $limit = 50 ): array {
global $wpdb;
$like_tva = '%tva%';
$like_vat = '%vat%';
$exclude_key = 'is_vat_exempt';
$is_hpos = class_exists('\Automattic\WooCommerce\Utilities\OrderUtil')
&& \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
$meta_table = $is_hpos ? $wpdb->prefix . 'wc_orders_meta' : $wpdb->postmeta;
$sql = "
SELECT DISTINCT meta_key
FROM {$meta_table}
WHERE (meta_key LIKE %s OR meta_key LIKE %s)
AND meta_key <> %s
LIMIT %d
";
$prepared_sql = $wpdb->prepare($sql, $like_tva, $like_vat, $exclude_key, $limit);
$keys = $wpdb->get_col($prepared_sql);
$keys = array_values(array_unique(array_map('strval', $keys)));
$keys = array_values(array_filter($keys, function ($key) {
return $key !== 'is_vat_exempt';
}));
return $keys;
}
/** /**
* Détecte tous les champs TVA dans une commande, limités aux groupes billing et shipping. * Détecte tous les champs TVA dans une commande, limités aux groupes billing et shipping.
* Retourne un tableau de tous les champs trouvés avec leur groupe et leur valeur. * Retourne un tableau de tous les champs trouvés avec leur groupe et leur valeur.