THELIA Forum

Welcome to the THELIA support and discusssion forum

Announcement

Rejoignez la communauté sur le Discord Thelia : https://discord.gg/YgwpYEE3y3

Offline

#1 Features / FeatureAvs

(02-05-2024 09:48:12)


Hello tout le monde!

Je suis en train de développer un module de synchronisation des produits entre Thelia et un logiciel interne.

Le but étant de générer un csv depuis le logiciel interne, de l'envoyer sur le serveur et, via une tâche cron, vérifier la présence de ce fichier et, s'il est présent, mettre à jour la BDD thelia.

Tout fonctionne correctement mais là je m'occupe des caractéristiques et à chaque fois que je dois intervenir sur cette partie, je me fais la même réflexion...

Pour savoir si une caractéristique est un champ libre, il faut que je cherche s'il existe des feature_av pour la feature ET si ces feature_av sont enregistrées dans feature_product avec is_free_text à 1.

Je trouve qu'il aurait été plus simple d'ajouter un champ "is_free_text" à la table feature défini à 1 par défaut et si on ajoute une valeur feature_av (via le BO), is_free_text passe à 0 et si on les supprime toutes, ça repasse à 1.

ça ne pourrait pas être une update qui faciliterait le fonctionnement ?

Après je dis ça mais pour mes modules de champs additionnels (category, folder, ... ) j'ai gardé le même principe de fonctionnement pour rester cohérent avec l'existant.


Aide les autres, ils t'aideront en retour.

Offline

#2 Re: Features / FeatureAvs

(02-05-2024 09:57:22)


Elyos wrote:

Pour savoir si une caractéristique est un champ libre, il faut que je cherche s'il existe des feature_av pour la feature ET si ces feature_av sont enregistrées dans feature_product avec is_free_text à 1.

Ou plutôt l'inverse via :

$featureAvs = FeatureAvQuery::create()
	->filterByFeatureId($idFeature)
	->useFeatureProductQuery()
		->filterByIsFreeText(false)
		->_or()
		->filterByIsFreeText(null)
	->endUse()
	->find();
if(null !== $featureAvs){
	//Not free text
}else{
	//Free text
}

Last edited by Elyos (02-05-2024 09:57:49)


Aide les autres, ils t'aideront en retour.

Offline

#3 Re: Features / FeatureAvs

(02-05-2024 10:01:47)


Hé oui, c'est bien merdique cette gestion des valeurs de caractéristiques.

Mais si on change la structure de données, il faudra fournir une migration de l'existant qui marche dans tous les cas.


OpenStudio Toulouse

Offline

#4 Re: Features / FeatureAvs

(02-05-2024 10:07:20)


Bon bah... dès que j'aurais un peu de temps je m'y collerais peut être... mais il y aura pas mal de chose à modifier...


Aide les autres, ils t'aideront en retour.

Offline

#5 Re: Features / FeatureAvs

(02-05-2024 11:47:28)


Déjà

$featureAvs = FeatureAvQuery::create()
	->filterByFeatureId($idFeature)
	->useFeatureProductQuery()
		->filterByIsFreeText(false)
		->_or()
		->filterByIsFreeText(null)
	->endUse()
	->find();
if(null !== $featureAvs){
	//Not free text
}else{
	//Free text
}

ça ne va pas vu que ça ne me retourne pas "null" pour les free text...


Aide les autres, ils t'aideront en retour.

Offline

#6 Re: Features / FeatureAvs

(02-05-2024 14:21:49)


Je nage...............................

$featureAvs = FeatureAvQuery::create()
	->filterByFeatureId($featureId)
	->useFeatureProductQuery()
		->filterByIsFreeText(false)
		->_or()
		->filterByIsFreeText(null)
	->endUse()
	->distinct()
	->find();
$featureValues = array();
if(null !== $featureAvs){ // ne retourne jamais null.....
	foreach($featureAvs as $featureAv){ //du coup je boucle pour enregistrer les feature_av_id (non free text normalement)
		$featureValues[] = $featureAv->getId();
	}
}
$featuresProduct = FeatureProductQuery::create()
	->filterByProductId($productId)
	->filterByFeatureId($featureId);
if(count($featureValues)){ // et je vérifie s'il y a des feature_av_id (non free text normalement)
	$featuresProduct->find(); //je récupère toutes les valeurs enregistrées
	foreach($featuresProduct as $featureProduct){
		$featureProduct->delete(); // pour les supprimer
	}
	Tlog::getInstance()->info($this->getTranslator()->trans('All features av. for feature ID=%id deleted.', ['%id' => $featureId], ProductsSync::DOMAIN_NAME, $locale));
	foreach($value as $val){ //et je boucle sur les valeurs à enregistrer
		$featureProduct = new FeatureProduct();
		$featureProduct->setProductId($productId)
			->setFeatureId($featureId)
			->setFeatureAvId($val)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature av. ID=%val for feature ID=%id saved.', ['%id' => $featureId,'%val' => $val], ProductsSync::DOMAIN_NAME, $locale));
	}
}else{ //sinon
	$featuresProduct->findOne(); // il n'y a normalement qu'une valeur donc j'en prends qu'une
	if(null !== $featuresProduct){ // ça ne me retourne pas null si aucune valeur enregistrée dans la BDD........... pourtant ça devrait ?!!!
		$featureAvId = $featuresProduct->getFeatureAvId(); // et du coup là ça me retourne une erreur quand il n'y a pas de valeur enregistrée dans la BDD!!!!
		$featureAv = FeatureAvQuery::create()
			->findOneById($featureAvId);
		if($value == ''){
			$featureAv->delete();
			Tlog::getInstance()->info($this->getTranslator()->trans('Free text feature av. ID="%value" for feature ID=%id deleted.', ['%id' => $featureId,'%value' => $featureAvId], ProductsSync::DOMAIN_NAME, $locale));
			/*$featuresProduct->delete();
			Tlog::getInstance()->info($this->getTranslator()->trans('Feature product for feature ID=%id deleted.', ['%id' => $featureId], ProductsSync::DOMAIN_NAME, $locale));*/
		}else{
			if($findLocale && isset($dataProduct['locale'])){
				$featureAv->setLocale($dataProduct['locale']);
			}else{
				$featureAv->setLocale($defaultLocale);
			}
			$featureAv->setTitle($value)
				->save();
			Tlog::getInstance()->info($this->getTranslator()->trans('Free Feature av. "%value" for feature ID=%id saved.', ['%id' => $featureId,'%value' => $value], ProductsSync::DOMAIN_NAME, $locale));
		}
	}else if($value != ''){
		$featureAv = new FeatureAv();
		$featureAv->setFeatureId($featureId);
		if($findLocale && isset($dataProduct['locale'])){
			$featureAv->setLocale($dataProduct['locale']);
		}else{
			$featureAv->setLocale($defaultLocale);
		}
		$featureAv->setTitle($value)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature av. "%value" for feature ID=%id saved.', ['%id' => $featureId,'%value' => $value], ProductsSync::DOMAIN_NAME, $locale));
		$featureProduct = new FeatureProduct();
		$featureProduct->setProductId($productId)
			->setFeatureId($featureId)
			->setFeatureAvId($featureAv->getId())
			->setIsFreeText(true)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature product for feature av. ID=%val for feature ID=%id saved.', ['%id' => $featureId,'%val' => $featureAv->getId()], ProductsSync::DOMAIN_NAME, $locale));
	}
}

L'erreur retournée

Undefined method Propel\Runtime\ActiveQuery\ModelCriteria::getFeatureAvId()

Last edited by Elyos (02-05-2024 14:22:14)


Aide les autres, ils t'aideront en retour.

Offline

#7 Re: Features / FeatureAvs

(02-05-2024 15:13:49)


Pfiouuuuuuuuuuuuuuuuu!

Ce que j'ai pas dû faire.......

Code de vérification des valeurs :

$featureId = str_replace('feature:','',$field);
$featureValues = array();
$feature = FeatureQuery::create()
	->findOneById($featureId);
if(null === $feature){
	Tlog::getInstance()->addError($this->getTranslator()->trans('Feature id="%id" not found.', ['%id' => $featureId], ProductsSync::DOMAIN_NAME, $locale));
	continue 2;
}
$featureAvs = FeatureAvQuery::create()
	->filterByFeatureId($featureId)
	->useFeatureProductQuery()
		->filterByIsFreeText(false)
		->_or()
		->filterByIsFreeText(null)
	->endUse()
	->distinct()
	->find();
if(null !== $featureAvs){
	foreach($featureAvs as $featureAv){
		$featureValues[] = $featureAv->getId();
	}
	if(count($featureValues) && $oldValue != ''){
		if(!is_array($value)){
			$value = explode(",",$value);
		}
		foreach($value as $val){
			if(!in_array($val,$featureValues)){
				Tlog::getInstance()->addError($this->getTranslator()->trans('Value for feature ID=%id must be in %values.', ['%id' => $featureId,'%values' => implode(', ',$featureValues)], 'productssync.bo.default', $locale));
				continue 2;
			}
		}
	}
}

Code de sauvegarde en BDD

$featureId = $dataFeatureProduct['id'];
$value = $dataFeatureProduct['value'];
$featureAvs = FeatureAvQuery::create()
	->filterByFeatureId($featureId)
	->useFeatureProductQuery()
		->filterByIsFreeText(false)
		->_or()
		->filterByIsFreeText(null)
	->endUse()
	->distinct()
	->find();
$featureValues = array();
if(null !== $featureAvs){
	foreach($featureAvs as $featureAv){
		$featureValues[] = $featureAv->getId();
	}
}
if(count($featureValues)){
	$featuresProduct = FeatureProductQuery::create()
		->filterByProductId($productId)
		->filterByFeatureId($featureId)
		->find();
	foreach($featuresProduct as $featureProduct){
		$featureProduct->delete();
	}
	Tlog::getInstance()->info($this->getTranslator()->trans('All features av. for feature ID=%id deleted.', ['%id' => $featureId], ProductsSync::DOMAIN_NAME, $locale));
	foreach($value as $val){
		$featureProduct = new FeatureProduct();
		$featureProduct->setProductId($productId)
			->setFeatureId($featureId)
			->setFeatureAvId($val)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature av. ID=%val for feature ID=%id saved.', ['%id' => $featureId,'%val' => $val], ProductsSync::DOMAIN_NAME, $locale));
	}
}else{
	$featureProduct = FeatureProductQuery::create()
		->filterByProductId($productId)
		->findOneByFeatureId($featureId);
	if(null !== $featureProduct){
		$featureAvId = $featureProduct->getFeatureAvId();
		$featureAv = FeatureAvQuery::create()
			->findOneById($featureAvId);
		if($value == ''){
			$featureAv->delete();
			Tlog::getInstance()->info($this->getTranslator()->trans('Free text feature av. ID="%value" for feature ID=%id deleted.', ['%id' => $featureId,'%value' => $featureAvId], ProductsSync::DOMAIN_NAME, $locale));
			/*$featureProduct->delete(); // <===== inutile
			Tlog::getInstance()->info($this->getTranslator()->trans('Feature product for feature ID=%id deleted.', ['%id' => $featureId], ProductsSync::DOMAIN_NAME, $locale));*/
		}else{
			if($findLocale && isset($dataProduct['locale'])){
				$featureAv->setLocale($dataProduct['locale']);
			}else{
				$featureAv->setLocale($defaultLocale);
			}
			$featureAv->setTitle($value)
				->save();
			Tlog::getInstance()->info($this->getTranslator()->trans('Free Feature av. "%value" for feature ID=%id saved.', ['%id' => $featureId,'%value' => $value], ProductsSync::DOMAIN_NAME, $locale));
		}
	}else if($value != ''){
		$featureAv = new FeatureAv();
		$featureAv->setFeatureId($featureId);
		if($findLocale && isset($dataProduct['locale'])){
			$featureAv->setLocale($dataProduct['locale']);
		}else{
			$featureAv->setLocale($defaultLocale);
		}
		$featureAv->setTitle($value)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature av. "%value" for feature ID=%id saved.', ['%id' => $featureId,'%value' => $value], ProductsSync::DOMAIN_NAME, $locale));
		$featureProduct = new FeatureProduct();
		$featureProduct->setProductId($productId)
			->setFeatureId($featureId)
			->setFeatureAvId($featureAv->getId())
			->setIsFreeText(true)
			->save();
		Tlog::getInstance()->info($this->getTranslator()->trans('Feature product for feature av. ID=%val for feature ID=%id saved.', ['%id' => $featureId,'%val' => $featureAv->getId()], ProductsSync::DOMAIN_NAME, $locale));
	}
}

ça a l'air de fonctionner... si quelqu'un peut jeter un oeil vite fait ça serait cool big_smile

Sinon peut-on me confirmer que

$featureProduct->delete();

est inutile si avant on lance un

$featureAv->delete();

(en sachant bien sûr que le feature_av_id correspond).


Aide les autres, ils t'aideront en retour.