Hook beforeSave et changement d'écran vers un objet archivé + coloriage des lignes archivées

Request description

Bonjour,
Je tente d’utiliser le hook beforeSave. Mon code vise à proposer, en cas de duplicate key avec un élement archivé, de restorer l’archive au lieu de l’objet en cours de création.
Si l’utilisateur répond oui, je le redirige vers l’archive “désarchivée” sans sauvegarder sa création.
Mais il me semble que je n’arrive pas à sortir du hook malgré le cbk(false). Je suis bien redirigée vers l’archive, mais je n’ai pas la main et ça mouline.

Pouvez vous m’aider ?
Merci !
Emmanuelle

Le code qui pose problème

											objDup.save(function(){
													$ui.displayForm(null, objDup.getName(), objDup.getRowId(), { nav: "new"}, function(){cbk(false);});

Moulinage

Code complet

Simplicite.UI.Globals.form.beforesave  = function(ctn, obj, index, cbk) {
					
					if (obj.getName().startsWith("Rci"))
					{
						var keys = obj.getUserKeyFields();
						var objDup = $ui.getAjax().getBusinessObject(obj.getName());
						var filters = {};

						
						for (var i = 0 ; i < keys.length ; i++)
						{
							var key = keys[i];
							if (key.refField == null)
								filters[key.name] = obj.getFieldValue(key.name);
						}
						
						filters["rciFieldIsArchived"] = "1";

						
						objDup.resetFilters();
						objDup.search(function(list) {
	
							if (list.length > 0)
							{
								if (confirm("This object already exists and had been archived. Do you want to restore it ?"))
								{
									objDup.resetFilters();
									
									objDup.selectForUpdate(
										function(item) {
											objDup.getField("rciFieldIsArchived").setValue(false);
											objDup.item.rciFieldIsArchived = false;
											objDup.save(function(){
													$ui.displayForm(null, objDup.getName(), objDup.getRowId(), { nav: "new"}, function(){cbk(false);});
													
													
												}
											);
										}
										, list[0].row_id);
									
									
								}
								else
									cbk();

							}
							else
								cbk();

						}
						,
							filters
						);
					
					}
					else
						cbk();
				};

Steps to reproduce

This request concerns an up-to-date Simplicité instance
and these are the steps to reproduce it:

Technical information

Instance /health
[Platform]
Status=OK
Version=5.3.10
BuiltOn=2023-07-28 09:49

Bonjour,

Ici cbk(false) empêche le save serveur et ne fait plus rien.
Si l’archive est bien restaurée en back et le bon formulaire affiché en mise à jour, il suffit à priori de retirer le spinner posé par la bouton “save” quand c’est OK :

$ui.displayForm(null, objDup.getName(), objDup.getRowId(), { nav:"new" }, function() {
   $ui.view.hideLoading(); // hide spinner
   cbk(false); // false = stop default back-end save
});

Sinon il faut mettre un debugger et voir où ça sort en erreur.

Par ailleurs ce code ne teste pas que le formulaire est en création obj.isNew().
En mise à jour de la clé fonctionnelle, il faut plutôt retourner une erreur standard = la clé fonctionnelle existe déjà ? et pas nécessairement archivée ?

Merci ça fonctionne :slight_smile:
Pour le isNew, je me suis dit que s’il prenait à l’utilisateur l’envie de changer de clé plutôt que Delete et Create un nouveau, je dois quand même faire ce traitement. Sinon il ne va pas comprendre pourquoi il a l’erreur vu que les archives sont invisibles.

Ok mais il faut distinguer 2 cas si la clé fonctionnelle est modifiable :

  • la clé modifiée existe déjà
  • existe déjà mais archivée

Sinon, il faut que la clé fonctionnelle ne soit pas modifiable hors création.

Ensuite la question est aussi :

  • de savoir si on peut recréer un objet déjà archivé mais qui n’a rien a voir (comme un homonyme)
  • si une référence qui pointe sur un objet archivé est un lien mort ? outer | inner join vers l’archive ?
  • regle de “delete restrict” si l’objet pointe sur une archive ?
  • archivage cascade à la place du delete cascade ?
  • process d’accès aux archives et restauration
  • et purge périodique

Si Simplicité n’a pas traité ce cas d’usage, c’est que l’archivage est un sujet complexe qui n’a pas de solution commune/généralisable.

Mais euh :sob: :sob: :sob:

Oui j’ai bien distingué les deux cas, si ça existe mais pas archivé on arrive sur l’erreur normale.

Vu la façon dont j’ai géré les clés les homonymes ne posent pas de problème (les clés sont toujours des ID)
Quand on archive un objet ça archive récursivement tout ce qui est lié.
L’accès aux archives se fait par un bouton que j’ai mis dans les shortcut qui permet de les afficher / masquer, quand actif les lignes archivées s’affichent en rouge
La purge, je n’ai pas encore mis en place car on doit en discuter.

Mais oui c’est super compliqué … j’avais demandé si ça existait en natif :sweat_smile:

1 Like

François,

Je me prends les pieds dans les clés virtuelles … un objet non archivé ramené par clé virtuelle qui elle est archivée reste visible en onglet.
En back, j’arrive à bidouiller en récupérant le searchSpec mais ce n’est pas très joli.
En front, pour mon code qui met les lignes archivées en rouge, je n’ai pas trouvé de solution.

Y a-t-il une méthode back pour changer la couleur d’une ligne ? Comme le getStyle mais pour une ligne.
Sinon ai-je un moyen d’accéder au searchSpec d’un lien virtuel en front ?

:sweat_smile:

Pour des raisons évidentes de sécurité, le front n’a aucune vocation à accéder au SQL back (select, update, search spec…), tout comme accéder aux droits du user.

La search-spec d’un lien virtuel reste donc en back :

  • dans la définition du link (à corriger avec un jointure/test “archivé”)
  • ou dynamiquement via accesseur sur la foreign-key du link :

exemple pour surcharger le filtre s’il y en a un dans le postLoad de l’objet lié :

ObjectField fk = obj.getField("refField");
String spec = fk.getRefSearchSpec();
if (!Tool.isEmpty(spec))
  spec = "(" + spec +") and ";
else
  spec = "";
spec += "exists (select 1 from ... not archived ...)";
fk.setRefSearchSpec(spec);

Pour la partie front, il faut utiliser le hook list.onload ou list.onloadrow pour colorier les lignes archivées si elles ne sont pas filtrées / visibles, dans ce cas la colonne/info “archivé” doit être présente en liste pour faire le test et ajouter une classe aux tr/td.

ou sinon (la colonne est cachée ou pas de hook front), il faut retourner la classe de chaque field=td par hook back :

@Override
public String getStyle(ObjectField f, String[] row) {
	Grant g = getGrant();
	if (archived(g, row)) // TODO
		return "row-archived";
	return super.getStyle(f, row);
}

et définir la classe .row-archived en front dans une ressource STYLES.

td.row-archived {
	background: red !important;
}

Attention Le hook getStyle doit bien évidement être rapide car appelé pour chaque cellule de la liste.

Merci beaucoup François, je m’en suis sortie avec un champ calculé pour le changement de style en front dans onLoadRow.
Pour le masquage des lignes archivées, je suis passée en back par le preSearch pour conserver le bon nombre de lignes par page. La recherche n’étant apparemment pas possible sur les champs calculés, j’ai implémenté la modification dynamiquement sur le getRefSearchSpec de mon lien virtuel.

Ca a l’air tout ok :slight_smile:

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.