Vous consultez une page technique concernant le logiciel de gestion Mercator. Celle-ci contient des informations spécifiques destinées aux professionnels de Mercator. Souhaitez-vous être redirigés vers des informations plus générales ?


   Ne plus poser cette question

Détecter les incohérences dans les rayons, familles et sous-familles des articles

0000002807     -      19/03/2018

Des incohérences peuvent être rencontrées au niveau des rayons, familles et sous-familles des articles :

  • certains rayons, certaines familles ou sous-familles n'existent plus
  • certains articles sont attachés à une famille dont le parent n'est pas le rayon de l'article
  • ...

Ces erreurs sont difficiles à détecter dans l'interface de Mercator car les déroulants ne montrent que les valeurs possibles. Les valeurs incorrectes sont dès lors toujours invisibles.

La réparation des données ne peut se faire que par identification des articles fautifs, en effectuant les 3 étapes suivantes :

Identifier les articles pour lesquels les rayons sont incorrects

select s_id,s_id_rayon from STOCK 
where (s_id_rayon<>'') and not exists(select * from RAYONS where s_id_rayon=id)

 

Identifier les articles pour lesquels les familles sont incorrectes

select s_id,s_id_rayon,s_id_famil from STOCK 
where (s_id_famil<>'') and not exists(select * from FAMILLES where (s_id_famil=id) and (id_rayon=s_id_rayon))

 

Identifier les articles pour lesquels les sous-familles sont incorrectes

select s_id,s_id_rayon,s_id_famil,s_id_ssfam from STOCK 
where (s_id_ssfam<>'') and not exists(select * from SS_FAMIL where (s_id_ssfam=id) and (id_famille=s_id_famil))

 


Pourquoi Mercator n'impose-t-il pas cette vérification par défaut sur la base de données ?

L'application non circonstanciée de la théorie imposerait de placer à cet endroit des contraintes sur la base de données. La réalité de ce qu'est un vrai ERP, évoluant en dehors d'un cadre idéal et théorique, n'a strictement rien à voir avec celle d'un programme, menant derrière lui tout un historique, dont notamment celui de la conception de la base de données de Mercator, et évoluant dans de vraies entreprises non disposées à revoir en permanence des éléments fonctionnels sans raison compréhensible pour l'utilisateur final. La continuité nous paraît plus essentielle que l'application de principes. Mercator dispose d'un éditeur de rapports : il permet à chacun d'établir ses propres rapports, donc ses propres requêtes SQL. Il n'est pas concevable de modifier unilatéralement les hypothèses qui ont été prises en compte par tout un chacun, dont du personnel en dehors de Mercator, pour réaliser ces requêtes.

L'équipe de programmation de Mercator a donc évalué cette situation et donné par rapport à celle-ci cette réponse :

  • Dans la plupart des dossiers, l'utilisation des rayons, familles et sous-familles est telle que l'intégrité référentielle concernant des relations vers ces tables peut être considérée comme non stratégique.
  • Depuis toujours, donc depuis la version DBF de Mercator, il n'est pas obligatoire qu'un article soit associé à un rayon, une famille ou une sous-famille. Dans ce cas l'information est à blanc (vide).
  • Le placement de contraintes de clés étrangères imposeraient une valeur null. Etant donné le principe de continuité expliqué ci-dessus, il n'est pas imaginable que Mercator, d'autorité, change cette hypothèse.
  • En informatique de gestion, chaque chose a un coût. L'abus de contraintes aussi. Nous savons qu'une telle modification aura un impact indéniable sur les chargements, par exemple par import Excel, de fichiers contenant plusieurs dizaines de milliers d'articles (opération très fréquente chez certains utilisateurs)

En conséquence, il a été décidé de ne pas imposer de contraintes sur les relations entre, d'une part les articles, et d'autre part, les rayons, familles et sous-familles.


Comment mettre quand même en place ces contraintes ?

Deux cas de figures se présentent. Ils peuvent se combiner.

1. Soit tous les articles doivent être associés à un rayon, une famille et une sous-famille. Dans ce cas, il est très simple de mettre en place des contraintes de clés étrangères avec le code SQL repris ci-dessous.

ALTER TABLE STOCK WITH CHECK ADD CONSTRAINT FK_STOCK_RAYONS FOREIGN KEY(S_ID_RAYON) REFERENCES RAYONS (ID)
CREATE UNIQUE INDEX FAMILLES_PK2 ON FAMILLES (ID,ID_RAYON) 
ALTER TABLE STOCK WITH CHECK ADD CONSTRAINT FK_STOCK_FAMILLES FOREIGN KEY(S_ID_FAMIL,S_ID_RAYON) REFERENCES FAMILLES (ID,ID_RAYON)
CREATE UNIQUE INDEX SS_FAMIL_PK2 ON SS_FAMIL (ID,ID_FAMILLE)
ALTER TABLE STOCK WITH CHECK ADD CONSTRAINT FK_STOCK_SS_FAMIL FOREIGN KEY(S_ID_SSFAM,S_ID_FAMIL) REFERENCES SS_FAMIL (ID,ID_FAMILLE)

 

2. Soit certains articles peuvent ne pas être associés à un rayon, une famille ou une sous-famille. Dans pareil cas, deux solutions peuvent être envisagées.

2a. Mise en place d'une contrainte de contenu faisant appel à une fonction scalaire. Cela peut avoir un impact significatif sur les performances lors du traitement en masse (modifications, imports, ...) de fiches articles.

Il faut d'abord installer cette fonction scalaire :

CREATE FUNCTION dbo.RFS_EXISTS
(
@id char(10),
@id_parent char(10),
@rfs char(1)
)
RETURNS bit
AS
BEGIN
declare @r bit
set @r=0
if (@rfs='R') and exists(select * from RAYONS (NOLOCK) where id=@id)
    set @r=1
if (@rfs='F') and exists(select * from FAMILLES (NOLOCK) where id=@id and id_rayon=@id_parent)
    set @r=1
if (@rfs='S') and exists(select * from SS_FAMIL (NOLOCK) where id=@id and id_famille=@id_parent)
    set @r=1
return @r
END

Ensuite, procéder à l'installation des contraintes :

ALTER TABLE STOCK WITH CHECK ADD CONSTRAINT CHECK_RFS CHECK (
(S_ID_RAYON='' or dbo.RFS_EXISTS(S_ID_RAYON, null, 'R')=1) and 
(S_ID_FAMIL='' or dbo.RFS_EXISTS(S_ID_FAMIL, S_ID_RAYON, 'F')=1) and
(S_ID_SSFAM='' or dbo.RFS_EXISTS(S_ID_SSFAM, S_ID_FAMIL, 'S')=1))

 

2b. Installation d'un trigger empêchant la liaison d'articles à des rayons, familles ou sous-familles n'existant pas. Cette solution n'apporte aucune validation quant aux données existant déjà dans la table STOCK.

CREATE TRIGGER dbo.TR_STOCK_CHECK_RFS
on dbo.STOCK
FOR INSERT,UPDATE 
AS
BEGIN
declare @msg varchar(100)

if update(s_id_rayon) and exists(
select * from inserted i where (i.s_id_rayon<>'') and not exists(select * from RAYONS r where r.id=i.s_id_rayon))
set @msg='Rayon inexistant ! '

if update(s_id_famil) and exists(
select * from inserted i where (i.s_id_famil<>'') and not exists(select * from FAMILLES f where (f.id=i.s_id_famil) and (f.id_rayon=i.s_id_rayon)))
set @msg=isnull(@msg,'')+ 'Famille inexistante ! '

if update(s_id_ssfam) and exists(
select * from inserted i where (i.s_id_ssfam<>'') and not exists(select * from SS_FAMIL s where (s.id=i.s_id_ssfam) and (s.id_famille=i.s_id_famil)))
set @msg=isnull(@msg,'')+ 'Sous-famille inexistante !'

if @msg is not null
begin
if @@TRANCOUNT > 0 ROLLBACK TRAN
RAISERROR(@msg,16,1)
end
END

Mercator dispose en standard de triggers qui empêchent la suppression/modification d'un rayon, d'une famille ou d'une sous-famille utilisée.