[ERP-62] Page Répertoire clients (datatable + Ajouter / Exporter) #44
@@ -86,7 +86,8 @@
|
|||||||
"updateSuccess": "Client mis à jour avec succès",
|
"updateSuccess": "Client mis à jour avec succès",
|
||||||
"archiveSuccess": "Client archivé avec succès",
|
"archiveSuccess": "Client archivé avec succès",
|
||||||
"restoreSuccess": "Client restauré avec succès",
|
"restoreSuccess": "Client restauré avec succès",
|
||||||
"error": "Une erreur est survenue. Réessayez."
|
"error": "Une erreur est survenue. Réessayez.",
|
||||||
|
"exportError": "L'export du répertoire clients a échoué. Réessayez."
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
"informationRequiredForCommercial": "Les informations de l'entreprise sont obligatoires pour le rôle Commerciale.",
|
"informationRequiredForCommercial": "Les informations de l'entreprise sont obligatoires pour le rôle Commerciale.",
|
||||||
|
|||||||
@@ -228,7 +228,13 @@ function formatLastActivity(item: Record<string, unknown>): string {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Date(value).toLocaleDateString('fr-FR')
|
// Garde-fou date invalide : un updatedAt mal forme donnerait « Invalid Date ».
|
||||||
|
const date = new Date(value)
|
||||||
|
if (Number.isNaN(date.getTime())) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.toLocaleDateString('fr-FR')
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clic sur une ligne → ecran Consultation (route a plat /clients/{id}). */
|
/** Clic sur une ligne → ecran Consultation (route a plat /clients/{id}). */
|
||||||
@@ -383,7 +389,7 @@ async function exportXlsx(): Promise<void> {
|
|||||||
catch {
|
catch {
|
||||||
toast.error({
|
toast.error({
|
||||||
title: t('commercial.clients.toast.error'),
|
title: t('commercial.clients.toast.error'),
|
||||||
message: t('commercial.clients.toast.error'),
|
message: t('commercial.clients.toast.exportError'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
* Formatage d'un numero de telephone francais en groupes de 2 chiffres
|
* Formatage d'un numero de telephone francais en groupes de 2 chiffres
|
||||||
* (`XX XX XX XX XX`).
|
* (`XX XX XX XX XX`).
|
||||||
*
|
*
|
||||||
* Signature cible partagee avec le ticket 1.13 / ERP-66 : si ce dernier livre
|
* Helper PARTAGE volontaire : les telephones sont presents un peu partout dans
|
||||||
* une version plus riche (validation, indicatif international), elle remplacera
|
* l'app (fiches clients, contacts, fournisseurs, prestataires...). Introduit ici
|
||||||
* cette implementation minimale. En attendant, on couvre le besoin du Repertoire
|
* comme util transverse stable plutot que duplique a chaque ecran. La signature
|
||||||
* clients (ERP-62) : afficher un telephone lisible a partir de la valeur stockee
|
* `formatPhoneFR(value): string` est coordonnee avec ERP-66, qui pourra enrichir
|
||||||
* en base (deja normalisee en 10 chiffres par le ClientProcessor, RG-1.20).
|
* l'implementation (validation, indicatif international) sans casser les appelants.
|
||||||
*
|
*
|
||||||
* - Ne garde que les chiffres puis groupe par 2 (tolere une saisie deja espacee
|
* - Ne garde que les chiffres puis groupe par 2 (tolere une saisie deja espacee
|
||||||
* ou pointee, ex: `06.12.34.56.78` ou `0612345678`).
|
* ou pointee, ex: `06.12.34.56.78` ou `0612345678`).
|
||||||
|
|||||||
@@ -144,30 +144,47 @@ class DoctrineClientRepository extends ServiceEntityRepository implements Client
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Nettoie une liste de chaines : trim, retrait des vides, reindexation.
|
* Nettoie une liste de chaines : trim, retrait des vides, reindexation.
|
||||||
|
* Defensive : tolere des elements scalaires non-string (cast) et ignore le
|
||||||
|
* reste sans lever de TypeError, le contrat etant justement de normaliser une
|
||||||
|
* entree potentiellement brute (query params).
|
||||||
*
|
*
|
||||||
* @param list<string> $values
|
* @param array<mixed> $values
|
||||||
*
|
*
|
||||||
* @return list<string>
|
* @return list<string>
|
||||||
*/
|
*/
|
||||||
private function normalizeStringList(array $values): array
|
private function normalizeStringList(array $values): array
|
||||||
{
|
{
|
||||||
$cleaned = array_filter(
|
$out = [];
|
||||||
array_map(static fn (string $v): string => trim($v), $values),
|
foreach ($values as $value) {
|
||||||
static fn (string $v): bool => '' !== $v,
|
if (is_string($value) || is_int($value) || is_float($value)) {
|
||||||
);
|
$trimmed = trim((string) $value);
|
||||||
|
if ('' !== $trimmed) {
|
||||||
|
$out[] = $trimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return array_values($cleaned);
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|||||||
/**
|
/**
|
||||||
* Nettoie une liste d'identifiants : cast int, retrait des <= 0, reindexation.
|
* Nettoie une liste d'identifiants : cast int, retrait des <= 0, reindexation.
|
||||||
|
* Defensive (cf. normalizeStringList) : accepte des entiers ou des chaines
|
||||||
|
* numeriques ('1', '2') sans TypeError, ignore le reste.
|
||||||
*
|
*
|
||||||
* @param list<int> $values
|
* @param array<mixed> $values
|
||||||
*
|
*
|
||||||
* @return list<int>
|
* @return list<int>
|
||||||
*/
|
*/
|
||||||
private function normalizeIntList(array $values): array
|
private function normalizeIntList(array $values): array
|
||||||
{
|
{
|
||||||
return array_values(array_filter($values, static fn (int $v): bool => $v > 0));
|
$out = [];
|
||||||
|
foreach ($values as $value) {
|
||||||
|
if (is_numeric($value) && (int) $value > 0) {
|
||||||
|
$out[] = (int) $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user
[Robustesse]
normalizeIntListpeut lever unTypeErrorstrict.Context : la closure type son paramètre
int, mais la signature publique de l'interface estarray $siteIds(éléments non typés).Cause : aujourd'hui sauvé car
ClientProvider::readIntListcaste en amont. Mais un appelant direct (test futur, autre module) passant['1','2'](strings) déclencherait unTypeErrorenstrict_types— fragile pour une méthode censée justement normaliser.Reco : caster dans la closure (
(int) $v > 0aprèsis_numeric) plutôt que de typer le paramètre, pour une normalisation réellement défensive.