Ajouter les favoris utilisateur à une vue filtrée (Filtre SQL + favoris)

Request description

:waving_hand: Bonjour,

Je souhaite créer une vue filtrée dans mon objet qui affiche :

  1. les enregistrements créés par l’utilisateur connecté

  2. ou dont il est contributeur (via les colonnes legal_text_person_id, legal_text_publisher_id, ou des champs texte comme legal_text_juridique_contributor, legal_text_business_contributor qui peuvent contenir plusieurs row_id séparés par ;)

  3. et également ses favoris, même s’il n’est pas contributeur ni créateur.

:magnifying_glass_tilted_left: Pour les contributeurs et créateurs, voici le filtre SQL que j’utilise dans le champ Filtre additionnel SQL (vwi_search_spec) :

(
  t.created_by = [LOGIN]
  OR t.legal_text_person_id = [USERID]
  OR t.legal_text_publisher_id = [USERID]
  OR t.legal_text_juridique_contributor LIKE CONCAT('%', [USERID], '%')
  OR t.legal_text_business_contributor LIKE CONCAT('%', [USERID], '%')
)

Ce filtre fonctionne correctement.

:red_question_mark: Problème :

Je voudrais ajouter les favoris de l’utilisateur même si le record ne correspond pas aux critères ci-dessus.

Or :

  • Les favoris ne sont pas stockés dans les colonnes de l’objet
  • Ils sont gérés côté UI, via les préférences utilisateurs (icône étoile)
  • Et comme vu dans les paramètres utilisateur, chaque vue d’accueil a ses propres favoris

:camera: Voici ce que je constate :

  • Les favoris sont bien visibles quand je consulte la liste complète (non filtrée) et les bons records filtré sont aussi en favoris dans la liste filtré
  • Mais dès que j’applique un filtre SQL, seuls les enregistrements correspondant au filtre apparaissent, meme cas pour les favoris

Auriez-vous une idée de comment gérer ce besoin de filtre sur un objet avec en + les favoris lié au user ?

En attente d’un retour, à bientot !

Technical information

Instance /health
[Platform]
Status=OK
Version=6.2.10
BuiltOn=2025-05-23 10:17
Git=6.2/db71f45b7b47f1aea2d669dc5b22c5369ec75d92
Encoding=UTF-8
EndpointIP=100.88.228.130
EndpointURL=http://lbc-77449-app-8ddbc79cf-cl52t:8080
TimeZone=Europe/Paris
SystemDate=2025-07-28 15:52:17

[Application]
ApplicationVersion=1.0.0
ContextPath=
ContextURL=https://ldm-app.ext.gke2.dev.gcp.renault.com
ActiveSessions=2
TotalUsers=304
EnabledUsers=16
LastLoginDate=2025-07-28 15:44:26

[Server]
ServerInfo=Apache Tomcat/9.0.105
ServerType=WEB
ServerDevMode=false
ServerCompiler=true
ServerActiveSessions=2
ServerSessionTimeout=30
CronStarted=true
Simplicité logs
---paste the content of the **relevant** server-side logs---
Browser logs
---paste content of the **relevant** browser-side logs---
Other relevant information

----E.g. type of deployment, browser vendor and version, etc.----

Cette syntaxe me semble invalide car LOGIN est un String donc plutôt à mettre entre quote, mais peut être que le parser est malin et les ajoute en escapant le login en SQL.

t.created_by = '[LOGIN]'

Sinon pour avoir les bookmarks, ils sont persistés en base au niveau des paramètres du User par scope/accueil, et monté en session dans un objet JSON qu’on peut convertir en SQL

Par exemple

// convert JSON bookmarks to 't.row_id in (10,23,543...)'
String bm = "";
// object bookmarks in current session/scope
JSONObject o = getGrant().getBookmarks().find(obj.getName());
// List of bookmarks
JSONArray a = o!=null ? o.optJSONArray("b", null) : null;
if (a!=null) {
	for (int i=0; i<a.length(); i++) {
		if (i>0) bm += ",";
		bm += a.getJSONObject(i).optString("id");
	}
}
// add to searchspec / additionnal search spec / view filters...
if (bm.length()>0)
   obj.setSearchSpec("... or t.row_id in (" + bm + ")");
1 Like

Et aussi

pose problème avec LIKE CONCAT('%', [USERID], '%')

si on a ‘12;123;1234’
avec ce like si je suis 23, je vois le record.

pourquoi ne pas faire une jointure avec une table de relation ?
Simplicité ne gère pas de lien 0,N avec des ids concaténés.

Merci François pour ton retour détaillée,

nous nous sommes focalisés sur le JSON en param et la table d’association et le filtre SQL suivant ramène exactement les filtres ainsi que les favoris lié.
Voici la version fonctionnelle du filtre complet, avec tous les cas :

filtre complet
(
  t.created_by = '[LOGIN]'
  OR t.legal_text_person_id = '[USERID]'
  OR t.legal_text_publisher_id = '[USERID]'
  OR EXISTS (
    SELECT 1 FROM lbc_legal_text_person_business pb
    WHERE pb.legal_text_id_person_business = t.row_id
      AND pb.legal_text_person_business_id = [USERID]
  )
  OR EXISTS (
    SELECT 1 FROM lbc_legal_text_person_juridical pj
    WHERE pj.legal_text_id_person_juridical = t.row_id
      AND pj.legal_text_person_juridical_id = [USERID]
  )
  OR t.row_id IN (
    SELECT (b_elem->>'id')::int AS id
    FROM (
      SELECT jsonb_array_elements(json_val->'list') AS list_elem
      FROM (
        SELECT usp_value::jsonb AS json_val
        FROM m_user_sysparam
        WHERE usp_user_id = [USERID]
          AND usp_param_id = (
            SELECT row_id
            FROM m_system
            WHERE sys_code = 'BOOKMARKS LBCHomeUser'
          )
      ) sub
    ) parsed,
    jsonb_array_elements(list_elem->'b') AS b_elem
    WHERE list_elem->>'o' = 'LbcLegalText'
  )
)

Nous avons suivi votre recommandation sur l’abandon des colonnes contenant des row_id concaténés en remplacant cela par les deux vraies tables de jointure, c’est beaucoup plus propre et sécurisé.
Cette solution fonctionne parfaitement maintenant, et la vue ramène à la fois les contributeurs, les auteurs et les favoris.

Encore merci pour votre aide.

1 Like

Bravo, parser le JSON en SQL c’est balaise et assez original !

Mais cela n’est pas transposable sur d’autres SGBD.
Personnellement quand c’est complexe je préfère faire du java et placer les filtres en SQL “standard” par code au postLoad en fonction du nom de l’instance dans ma vue.

Les FK sont des integer en base, donc ce n’est pas utile de mettre des quotes / et ça peut provoquer des erreurs de cast implicite car PGSQL est généralement assez strict sur les types des colonnes comparées.

1 Like