Bundle Import / Jobs
Ref : PHPR_Système d’import_2015
Path : PROJECT/job/import/
Ex : https://phpc.phpreaction.com/job/import/
Description
Slogan :
“Quelques clics bien placés, des milliers de données importés!” ?
URL : /*/import/
Ex : /product/import/
Ex : /prospect/import/
Objectif
Gère l’import de fichiers CSV dans PHPR. Ceux-ci servent a créer une “Job d’import”, ayant comme objectif d’ajouter à l’ERP les entités listées dans le CSV. Si la première entités d’une ligne existe déja dans l’ERP, les champs seront Updatés pour cet entité.
Logic
| Key | Description | Utilisation |
|---|---|---|
| (vide / N/A) | Création de nouvelle ligne | Comportement par défaut |
skip | Permet de ne pas modifier les lignes en conflit | Seulement lors de la création de nouvelle ligne (check sur la valeur de la colonne) |
update | Permet de mettre à jour les lignes en conflit | Check sur la valeur de la colonne |
updateOnly | Permet de mettre à jour les lignes en conflit et ignorer celles inexistantes | Check sur la valeur de la colonne |
date | Convertit le champ en date (YYYY-MM-DD) | Quand le champ devrait être une date au format YYYY-MM-DD |
*Conflit = on duplicate
Ne peut avoir qu’une seule clé par champ
Data migration
Procédure
-
Analyser le format de donné reçu
- Certains format sont plus commun (XSL => CSV, XML, SQL)
-
Accès au donnée par un script de donnée
-
Adaptation de la source de donnée vers un format le plus simple possible
-
Remplir les objets représentant la base de donnée finale
- Utilisation simple des entities Doctrine
-
Sauvegarde les Objets dans la base de donnée
CSV
Il est possible des les loader directement en SQL si il représentante seulement une table avec “Data Load”
SQL
Il est possible de faire des requêtes de migration pour arriver au format final
Fonctionnement
Processus
Utilisation UX
- Préparer le document CSV avec les bonne entête (première ligne).
Dans PHPR
-
Pour lancer une “job d’import”, allez dans les paramètres, puis “Système” et enfin “Tâche d’import” Importez ensuite le CSV avec l’aide du formulaire.
-
Bien s’assurer qu’un champ requis par l’entités créée n’a pas été laissée vide, puisque cela causerait un “crash” de l’application.
-
Si l’import échoue, il est possible de relancer celui-ci:
-
Depuis les CLI
./console phpreaction:import:job 450 -
Depuis le U.I : Boutons Relancer l’import :
-
Open image2017-2-13 16:56:7.png
(Route name = import_job_launch)
-
Possibilité de passer une fonction custom
-
Ajouter un | suivi du nom de votre fonction dans le header
-
Ajouter la fonction dans le repository de l’entité importée
-
Translatable
Pour updater un champs translatable, ajouter l’action spéciale ‘|setLang’ dans le header de la locale.
importInventoryAdjust
Plutôt que de faire une entrée `uyn nombre demandé, on demande de faire l’ajustement entre l’inventaire actuel et celui demandé.
number|importInventoryAdjust 10 10 -20
Donc, si l’inventaire des produits est respectivement de 5, 11 et 0, les entrés seront de 5 (5+5=10), de -1 (11-1=10) et -20 (0-20=-20)
FindBy
Possibilité de cibler une relation par un de ses champs autre que par ID :
product|findBy(sku)
On met le champs à cibler entre paranthèse.
tagging
resourceId|findByClientCode
<?php namespace PHPReaction\TagBundle\Entity; use Doctrine\ORM\EntityManager; use PHPReaction\CommonBundle\Entity\EntityRepository; class TaggingRepository extends EntityRepository { public function getBasicListingQueryBuilder() { $qb = $this->createQueryBuilder('self'); $qb->addOrderBy('self.id', 'DESC'); return $qb; } public function getTaggableTypesSimpleList() { $querybuilder = $this->createQueryBuilder('self'); $querybuilder->select('self.resourceType')->distinct(); return $querybuilder; } /** * @param EntityManager $entityManager * @param $search * @param $entity * * @return mixed * @throws \Exception * // @todo make this into a trait */ public function getProductIdBySKU(EntityManager $entityManager, $search, $entity) { $product = $entityManager ->getRepository('PHPReactionProductBundle:Product') ->findOneBy(['sku' => $search]); if ($product == null) { $error = 'ERR:5d255aa2b0890'; throw new \Exception('There is no product with this SKU : ' . $search . ' ' . $error); } else { return $product->getId(); } } /** * @param EntityManager $entityManager * @param $search * @param $entity * * @return mixed * @throws \Exception * // @todo make this into a trait */ public function getProductIdByClientCode(EntityManager $entityManager, $search, $entity) { $product = $entityManager ->getRepository('PHPReactionProductBundle:Product') ->findOneBy(['clientCode' => $search]); if ($product == null) { $error = 'ERR:5d255ab1b1d82'; throw new \Exception('There is no product with this Client Code : ' . $search . ' ' . $error); } else { return $product->getId(); } } /** * @param EntityManager $entityManager * @param $search * @param $entity * * @return mixed * @throws \Exception * // @todo make this into a trait */ public function getProductIdBySupplierCode(EntityManager $entityManager, $search, $entity) { $product = $entityManager ->getRepository('PHPReactionProductBundle:Product') ->findOneBy(['supplierCode' => $search]); if ($product == null) { $error = 'ERR:5d255ac792b62'; throw new \Exception('There is no product with this Supplier Code : ' . $search . ' ' . $error); } else { return $product->getId(); } } /** * @param EntityManager $entityManager * @param $search * @param $entity * * @return mixed * @throws \Exception */ public function getTagIdByName(EntityManager $entityManager, $search, $entity) { $tag = $entityManager ->getRepository('PHPReactionTagBundle:Tag') ->findOneBy(['name' => $search]); if ($tag == null) { $error = 'ERR:5d255ad7b136b'; throw new \Exception('There is no tag with this name : ' . $search . ' ' . $error); } else { return $tag->getId(); } } /** * @param EntityManager $entityManager * @param $search * @param $entity * * @return mixed * @throws \Exception */ public function getTagIdBySlug(EntityManager $entityManager, $search, $entity) { $tag = $entityManager ->getRepository('PHPReactionTagBundle:Tag') ->findOneBy(['slug' => $search]); if ($tag == null) { $error = 'ERR:5d255adc2f8db'; throw new \Exception('There is no tag with this slug : ' . $search . ' ' . $error); } else { return $tag->getId(); } } }
Exemples
Files:
Metadata
Ajouter la documentation au niveau du metadata nouvelle pages ???
Parameter => Import => Configuration => Metadata
Ex Liste : https://dev1.phpreaction.com/metadata/entities
Ex Entité : https://dev1.phpreaction.com/metadata/entity/PHPReaction%5CProductBundle%5CEntity%5CProduct
Exemple de Job
Exemples-tests fichiers imports
GART_Multi-inventaire-Import_2016
librairielerepere.com_Import_2017
Importation PHPR du Répertoire (import : User, prospect, coordonnée, suivi)
Documentation Client
http://phpreaction.com/fonctionnalites/assistance-importation/
Améliorations / features à ajouter
-
Fonction |skip-update
- Permettre de faire un update, mais plutôt que de créer les entrées qui n’existent pas encore, les skip. @Simon Inkel (Unlicensed)