Commit 28abaf87 by Mathieu Poisbeau

#143: Gros débogage et nettoyage de l'import des prestataires

parent 078d9c8c
......@@ -18,6 +18,7 @@ use App\Entity\Siege;
use App\Entity\User;
use App\Entity\Usergroup;
use App\Entity\Flux;
use App\Entity\TypePrestataire;
use App\Enum\ImportEnum;
use App\Enum\MoyenEnum;
use App\Events\MLCEvents;
......@@ -81,6 +82,9 @@ class ImportController extends CRUDController
$this->sendemail = false;
}
/**
* @TODO: manage the case of a fatal error (so catch the exception, and display a nice message)!
*/
public function createAction()
{
$this->siege = $this->em->getRepository(Siege::class)->findOneById(1);
......@@ -344,191 +348,180 @@ class ImportController extends CRUDController
{
$operateur = $this->getUser();
$operateur_id = $operateur->getId();
// Iterate over the reader and write each row to the database
// groupe;adresse;cpostal;ville;raison;ecompte;metier;statut;responsable;iban;siret;web;horaires;description;rubriques;tags;tauxreconversion;cotisations;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1;contact1;phone1;email1;contact2;phone2;email2
$line = 1;
$line = 0;
/**
* Iterate over the reader and write each row to the database.
* Each row has at least 6 required columns.
*
* Row format: groupe;adresse;cpostal;ville;raison;ecompte;metier;statut;responsable;iban;siret;web;horaires;...
* description;rubriques;tags;tauxreconversion;cotisations;...
* gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1;...
* contact1;phone1;email1;contact2;phone2;email2
*/
$requiredColumns = [
'groupe', 'raison', 'siret', 'adresse', 'cpostal', 'ville',
];
$warningColumns = [
'metier', 'statut', 'responsable', 'iban', 'web', 'horaires', 'description', 'ecompte',
];
$columns = array_fill_keys(
array_merge($requiredColumns, $warningColumns, ['rubriques', 'tags', 'tauxreconversion', 'cotisations']),
null
);
foreach ($csvRows as $row) {
$hasError = false;
if ($line == 1) {
$line++;
continue;
}
if (!array_key_exists("groupe", $row)) {
$this->addError($row, $line, 'groupe', $this->translator->trans("La colonne 'groupe' est obligatoire !"));
}
if (!array_key_exists("adresse", $row)) {
$this->addError($row, $line, 'adresse', $this->translator->trans("La colonne 'adresse' est obligatoire !"));
}
if (!array_key_exists("cpostal", $row)) {
$this->addError($row, $line, 'cpostal', $this->translator->trans("La colonne 'cpostal' est obligatoire !"));
}
if (!array_key_exists("ville", $row)) {
$this->addError($row, $line, 'ville', $this->translator->trans("La colonne 'ville' est obligatoire !"));
}
if (!array_key_exists("raison", $row)) {
$this->addError($row, $line, 'raison', $this->translator->trans("La colonne 'raison' est obligatoire !"));
}
if (!(array_key_exists("groupe", $row) && array_key_exists("adresse", $row) && array_key_exists("cpostal", $row) && array_key_exists("ville", $row) && array_key_exists("raison", $row))) {
$line++;
$this->nberrors++;
$line++;
// The header is ignored
if ($line === 1) {
continue;
}
$groupe = array_key_exists("groupe", $row) ? $row['groupe'] : '';
$adresse = array_key_exists("adresse", $row) ? $row['adresse'] : '';
$cpostal = array_key_exists("cpostal", $row) ? $row['cpostal'] : '';
$ville = array_key_exists("ville", $row) ? $row['ville'] : '';
$raison = array_key_exists("raison", $row) ? $row['raison'] : '';
if (empty($groupe)) {
$this->addError($row, $line, 'groupe', $this->translator->trans("Le 'groupe' est obligatoire !"));
}
if (empty($adresse)) {
$this->addError($row, $line, 'adresse', $this->translator->trans("Le 'adresse' est obligatoire !"));
}
if (empty($cpostal)) {
$this->addError($row, $line, 'cpostal', $this->translator->trans("Le 'cpostal' est obligatoire !"));
}
if (empty($ville)) {
$this->addError($row, $line, 'ville', $this->translator->trans("Le 'ville' est obligatoire !"));
}
if (empty($raison)) {
$this->addError($row, $line, 'raison', $this->translator->trans("Le 'raison' est obligatoire !"));
// Add the missing columns to the current row (with a null value).
$row += $columns;
/**
* Check the required columns.
* If one is not present or empty => add an error and go to the next line.
*/
foreach ($requiredColumns as $column) {
if (! $row[$column]) {
$this->addError($row, $line, $column,
$this->translator->trans('prestataire.column_required', [$column], 'import')
);
$hasError = true;
}
}
if (empty($groupe) || empty($adresse) || empty($cpostal) || empty($ville) || empty($raison)) {
if ($hasError) {
$this->nberrors++;
$line++;
continue;
}
$ecompte = array_key_exists("ecompte", $row) ? $row['ecompte'] : '';
$metier = array_key_exists("metier", $row) ? $row['metier'] : '';
$statut = array_key_exists("statut", $row) ? $row['statut'] : '';
$responsable = array_key_exists("responsable", $row) ? $row['responsable'] : '';
$iban = array_key_exists("iban", $row) ? $row['iban'] : '';
$siret = array_key_exists("siret", $row) ? $row['siret'] : '';
$web = array_key_exists("web", $row) ? $row['web'] : '';
$horaires = array_key_exists("horaires", $row) ? $row['horaires'] : '';
$description = array_key_exists("description", $row) ? $row['description'] : '';
$rubriques = array_key_exists("rubriques", $row) ? $row['rubriques'] : '';
$tags = array_key_exists("tags", $row) ? $row['tags'] : '';
$tauxreconversion = array_key_exists("tauxreconversion", $row) ? $row['tauxreconversion'] : '';
$cotisations = array_key_exists("cotisations", $row) ? $row['cotisations'] : '';
$prestataire = $this->em->getRepository(Prestataire::class)->findOneBy(array('slug' => $this->slugify($raison)));
if (empty($prestataire)) {
/**
* If it doesn't exist yet, create and fill a Prestataire.
* Otherwise => error!
*/
$prestataire = $this->em->getRepository(Prestataire::class)->findOneBy([
'slug' => $this->slugify($row['raison'])
]);
if (!$prestataire) {
$prestataire = new Prestataire();
if (!empty($raison)) {
$prestataire->setRaison($raison);
} else {
$this->addWarning($row, $line, 'raison', 'empty');
}
if (!empty($metier)) {
$prestataire->setMetier($metier);
} else {
$this->addWarning($row, $line, 'metier', 'empty');
}
if (!empty($statut)) {
$prestataire->setStatut($statut);
} else {
$this->addWarning($row, $line, 'statut', 'empty');
}
if (!empty($responsable)) {
$prestataire->setResponsable($responsable);
} else {
$this->addWarning($row, $line, 'responsable', 'empty');
}
if (!empty($iban)) {
$prestataire->setIban($iban);
} else {
$this->addWarning($row, $line, 'iban', 'empty');
}
if (!empty($siret)) {
$prestataire->setSiret($siret);
} else {
$this->addWarning($row, $line, 'siret', 'empty');
// Actually, each new Prestataire will have the 'prestataire' as TypePrestataire
// @TODO: add a column 'type' in the CSV file (to choose a TypePrestataire)?
$prestataire->setTypePrestataire($this->em->getRepository(TypePrestataire::class)->findOneBy([
'slug' => 'prestataire'
]));
foreach ($requiredColumns as $column) {
// Special processings for these fields => so we skip them
if (in_array($column, ['groupe', 'adresse', 'cpostal', 'ville'])) continue;
$prestataire->{'set'.ucfirst($column)}($row[$column]);
}
if (!empty($web)) {
$prestataire->setWeb($web);
} else {
$this->addWarning($row, $line, 'web', 'empty');
// Special processing for the 'ecompte' field
if ($e =& $row['ecompte']) {
$e = $this->tofloat($e);
}
if (!empty($horaires)) {
$prestataire->setHoraires($horaires);
} else {
$this->addWarning($row, $line, 'horaires', 'empty');
foreach ($warningColumns as $column) {
if ($row[$column]) {
$prestataire->{'set'.ucfirst($column)}($row[$column]);
} else {
$this->addWarning($row, $line, $column, 'empty');
}
}
if (!empty($description)) {
$prestataire->setDescription($description);
} else {
$this->addWarning($row, $line, 'description', 'empty');
/**
* If one or many Contacts are present, we create them for the Prestataire.
* If a phone or an email is defined, the associated 'contact' field must be defined too!
*/
for ($i = 1; $i < 10; $i++) {
$name = $row["contact$i"] ?? null;
$phone = $row["phone$i"] ?? null;
$email = $row["email$i"] ?? null;
if ($name) {
$contact = new ContactPrestataire();
$contact->setPrestataire($prestataire);
$contact->setEnabled(true);
$contact->setName($name);
$contact->setTel($row["phone$i"] ?? '');
$contact->setEmail($row["email$i"] ?? '');
$this->em->persist($contact);
} elseif ($phone || $email) {
$this->addError($row, $line, "contact$i",
$this->translator->trans('prestataire.column_required', ["contact$i"], 'import')
);
$hasError = true;
}
}
$cptContact = 1;
while (array_key_exists("contact".$cptContact, $row) && $cptContact < 10) {
$contact = array_key_exists('contact'.$cptContact, $row) ? $row['contact'.$cptContact] : '';
$phone = array_key_exists('phone'.$cptContact, $row) ? $row['phone'.$cptContact] : '';
$email = array_key_exists('email'.$cptContact, $row) ? $row['email'.$cptContact] : '';
$contactC = new ContactPrestataire();
$contactC->setPrestataire($prestataire);
$contactC->setEnabled(true);
$contactC->setName($contact);
$contactC->setTel($phone);
$contactC->setEmail($email);
$this->em->persist($contactC);
++$cptContact;
if ($hasError) {
$this->nberrors++;
continue;
}
// Importer les gestionnaires du prestataire s'ils existent
$groupeGestionnaire = $this->em->getRepository(Usergroup::class)->findOneByName('Prestataire');
$gestionnaires = $this->importGestionnaires($row, $groupeGestionnaire);
$prestataire->setUsers($gestionnaires);
if (!empty($ecompte)) {
$prestataire->setEcompte($this->tofloat($ecompte));
} else {
$this->addWarning($row, $line, 'ecompte', 'empty');
}
if (!empty($groupe)) {
$groupeFound = $this->em->getRepository(Groupe::class)->findOneBy(array('name' => $groupe));
if (empty($groupeFound)) {
$groupeFound = new Groupe();
$groupeFound->setName($groupe);
$groupeFound->setSiege($this->siege);
$this->em->persist($groupeFound);
$this->addWarning($row, $line, 'groupe', $this->translator->trans('Groupe introuvable, création du groupe : ').$groupe);
}
$prestataire->setGroupe($groupeFound);
} else {
$this->addWarning($row, $line, 'groupe', 'empty');
/**
* If no Groupe object exists for the 'groupe' field, we create one.
* Note: at this point, the 'groupe' field is necessarily not empty (because it was required above).
*/
$groupe = $row['groupe'];
$groupeObj = $this->em->getRepository(Groupe::class)->findOneBy(['name' => $groupe]);
if (! $groupeObj) {
$groupeObj = new Groupe();
$groupeObj->setName($groupe);
$groupeObj->setSiege($this->siege);
$this->em->persist($groupeObj);
$this->addSuccess($row, $line, 'groupe',
$this->translator->trans('prestataire.groupe_notfound_created', [$groupe], 'import')
);
}
if (!empty($cotisations)) {
$prestataire->setGroupe($groupeObj);
if ($cotisations = $row['cotisations']) {
$cotisationArray = explode(',', $cotisations);
if (count($cotisationArray) > 0) {
foreach ($cotisationArray as $cotisationDetails) {
$cotisation = new CotisationPrestataire();
$now = new DateTime();
$cotisation->setReference('Import du '.$now->format('d/m/Y H:i'));
$cotisation->setOperateur($operateur);
$cotisation->setRole('ROLE_SUPER_ADMIN');
$cotisation->setExpediteur($prestataire);
$cotisation->setMoyen(MoyenEnum::MOYEN_AUTRE);
$cotisationDetailsArray = explode(':', $cotisationDetails);
if (count($cotisationDetailsArray) == 1) {
$cotisation->setMontant(intval($cotisationDetails));
$cotisation->getCotisationInfos()->setDebut($now);
$cotisation->getCotisationInfos()->setFin(new DateTime('+ 1 year'));
} else {
$cotisation->setMontant(intval($cotisationDetailsArray[0]));
$cotisation->getCotisationInfos()->setAnnee(intval($cotisationDetailsArray[1]));
$cotisation->getCotisationInfos()->setDebut(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]).'0101'));
$cotisation->getCotisationInfos()->setFin(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]).'1231'));
}
$this->em->persist($cotisation);
$this->addSuccess($row, $line, 'cotisations', $this->translator->trans('Cotisation ajouté : ').$groupe);
foreach ($cotisationArray as $cotisationDetails) {
$cotisation = new CotisationPrestataire();
$now = new DateTime();
$cotisation->setReference('Import du '.$now->format('d/m/Y H:i'));
$cotisation->setOperateur($operateur);
$cotisation->setRole('ROLE_SUPER_ADMIN');
$cotisation->setExpediteur($prestataire);
$cotisation->setMoyen(MoyenEnum::MOYEN_AUTRE);
$cotisationDetailsArray = explode(':', $cotisationDetails);
if (count($cotisationDetailsArray) == 1) {
$cotisation->setMontant(intval($cotisationDetails[0]));
$cotisation->getCotisationInfos()->setDebut($now);
$cotisation->getCotisationInfos()->setFin(new DateTime('+ 1 year'));
} else {
$cotisation->setMontant(intval($cotisationDetailsArray[0]));
$cotisation->getCotisationInfos()->setAnnee(intval($cotisationDetailsArray[1]));
$cotisation->getCotisationInfos()->setDebut(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]).'0101'));
$cotisation->getCotisationInfos()->setFin(DateTime::createFromFormat('Ymd', intval($cotisationDetailsArray[1]).'1231'));
}
$this->em->persist($cotisation);
$this->addSuccess($row, $line, 'cotisations', $this->translator->trans('Cotisation ajouté : ').$groupe);
}
} else {
$this->addWarning($row, $line, 'cotisations', 'empty');
}
if (!empty($rubriques)) {
if ($rubriques = $row['rubriques']) {
$rubriquesArray = explode(',', $rubriques);
foreach ($rubriquesArray as $rubrique) {
$rubriquesFound = $this->em->getRepository(Rubrique::class)->findOneBy(array('slug' => $this->slugify($rubrique)));
......@@ -543,7 +536,8 @@ class ImportController extends CRUDController
} else {
$this->addWarning($row, $line, 'rubriques', 'empty');
}
if (!empty($tags)) {
if ($tags = $row['tags']) {
$tagsArray = explode(',', $tags);
foreach ($tagsArray as $tag) {
$tagsFound = $this->em->getRepository(EtatPrestataire::class)->findOneBy(array('slug' => $this->slugify($tag)));
......@@ -557,36 +551,49 @@ class ImportController extends CRUDController
} else {
$this->addWarning($row, $line, 'tags', 'empty');
}
if (!empty($adresse) || !empty($cpostal) || !empty($ville)) {
$geolocP = new GeolocPrestataire();
$geolocP->setName('Adresse');
$geolocP->setPrestataire($prestataire);
$geolocFound = new Geoloc();
$geolocFound->setEnabled(true);
$geolocFound->setAdresse($adresse);
$geolocFound->setCpostal(intval($cpostal));
$geolocFound->setVille($ville);
$geolocP->setGeoloc($geolocFound);
$prestataire->setGeolocs([$geolocP]);
$this->em->persist($geolocP);
}
/**
* Add a Geoloc for this Prestataire.
* At this point, 'adresse', 'cpostal' and 'ville' fields exist and are not empty.
*/
$geoloc = new Geoloc();
$geoloc->setEnabled(true);
$geoloc->setAdresse($row['adresse']);
$geoloc->setCpostal($row['cpostal']);
$geoloc->setVille($row['ville']);
$geolocP = new GeolocPrestataire();
$geolocP->setName('Adresse');
$geolocP->setPrestataire($prestataire);
$geolocP->setGeoloc($geoloc);
$this->em->persist($geolocP);
$prestataire->setGeolocs([$geolocP]);
} else {
$this->addError($row, $line, 'name', $this->translator->trans("Le prestataire avec cette raison '".$raison."' existe déjà !"));
$this->addError($row, $line, 'raison',
$this->translator->trans('prestataire.already_exists', [$row['raison']], 'import')
);
$this->nberrors++;
$hasError = true;
}
if (!$hasError) {
$this->addSuccess($row, $line, 'user', $this->translator->trans('Prestataire bien ajouté : ').$prestataire->__toString());
$this->nbsuccess++;
$this->em->persist($prestataire);
$this->em->flush();
$this->em->clear();
// em is fully cleared: we need to refetch entities we get from em during process
$operateur = $this->em->getRepository(User::class)->findOneBy(array('id' => $operateur_id));
}
$operateur = $this->em->getRepository(User::class)->findOneById($operateur_id);
$this->siege = $this->em->getRepository(Siege::class)->findOneById(1);
$line++;
$this->addSuccess($row, $line, 'user',
$this->translator->trans('prestataire.added', [(string) $prestataire], 'import')
);
$this->nbsuccess++;
}
}
ksort($this->errors);
ksort($this->warnings);
}
......
......@@ -11,7 +11,7 @@ trait ContactEmailTelTrait
/**
* @var null|string
*
* @ORM\Column(name="tel", type="string", length=20, nullable=true)
* @ORM\Column(name="tel", type="string", length=100, nullable=true)
* @Groups({"read", "write"})
*/
protected $tel;
......
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200925152216 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE contact_comptoir CHANGE tel tel VARCHAR(100) DEFAULT NULL');
$this->addSql('ALTER TABLE contact_prestataire CHANGE tel tel VARCHAR(100) DEFAULT NULL');
$this->addSql('ALTER TABLE groupeprestaire CHANGE tel tel VARCHAR(100) DEFAULT NULL');
$this->addSql('ALTER TABLE siege CHANGE ecompte ecompte NUMERIC(12, 2) DEFAULT \'0\' NOT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE contact_comptoir CHANGE tel tel VARCHAR(20) CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`');
$this->addSql('ALTER TABLE contact_prestataire CHANGE tel tel VARCHAR(20) CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`');
$this->addSql('ALTER TABLE groupeprestaire CHANGE tel tel VARCHAR(20) CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`');
$this->addSql('ALTER TABLE siege CHANGE ecompte ecompte NUMERIC(12, 2) NOT NULL');
}
}
prestataire:
already_exists: 'Le prestataire avec la raison "0" existe déjà !'
column_required: 'La colonne "0" ne doit pas être vide'
groupe_notfound_created: 'Création du groupe "0" car introuvable'
added: 'Prestaitaire bien ajouté : 0'
prestataire:
already_exists: 'Le prestataire avec la raison "0" existe déjà !'
column_required: 'La colonne "0" ne doit pas être vide'
groupe_notfound_created: 'Création du groupe "0" car introuvable'
added: 'Prestaitaire bien ajouté : 0'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment