Commit 5659b01b by Julien Jorry

Import : Amélioration et modification de l'import => migrate BDD + composer install

parent aae553d4
...@@ -66,11 +66,11 @@ ...@@ -66,11 +66,11 @@
"symfony/webpack-encore-bundle": "^1.7", "symfony/webpack-encore-bundle": "^1.7",
"symfony/yaml": "4.4.*", "symfony/yaml": "4.4.*",
"vich/uploader-bundle": "^1.8", "vich/uploader-bundle": "^1.8",
"willdurand/geocoder-bundle": "^5.0" "willdurand/geocoder-bundle": "^5.0",
"doctrine/doctrine-fixtures-bundle": "^3.0",
"hautelook/alice-bundle": "^2.3"
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"hautelook/alice-bundle": "^2.3",
"sensiolabs/security-checker": "^5.0", "sensiolabs/security-checker": "^5.0",
"symfony/browser-kit": "4.4.*", "symfony/browser-kit": "4.4.*",
"symfony/css-selector": "4.4.*", "symfony/css-selector": "4.4.*",
......
...@@ -29,10 +29,10 @@ return [ ...@@ -29,10 +29,10 @@ return [
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true], Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true], Knp\Bundle\PaginatorBundle\KnpPaginatorBundle::class => ['all' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['all' => true],
Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true], Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['all' => true],
Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'test' => true], Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['all' => true],
Hautelook\AliceBundle\HautelookAliceBundle::class => ['dev' => true, 'test' => true], Hautelook\AliceBundle\HautelookAliceBundle::class => ['all' => true],
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true], JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
Sonata\MediaBundle\SonataMediaBundle::class => ['all' => true], Sonata\MediaBundle\SonataMediaBundle::class => ['all' => true],
App\Application\Sonata\MediaBundle\ApplicationSonataMediaBundle::class => ['all' => true], App\Application\Sonata\MediaBundle\ApplicationSonataMediaBundle::class => ['all' => true],
......
sonata_doctrine_orm_admin:
templates:
types:
show: # or "list"
json: '@SonataAdmin/show_json.html.twig'
sonata_admin: sonata_admin:
security: security:
# handler: sonata.admin.security.handler.role # handler: sonata.admin.security.handler.role
......
...@@ -14,21 +14,29 @@ parameters: ...@@ -14,21 +14,29 @@ parameters:
app.import.separator: ';' app.import.separator: ';'
app.import.header: app.import.header:
groupe: groupe:
header: 'name;content;compte' header: 'nom;description;compte'
example: 'Groupe local n°1;<b>Groupe local n°1</b>;123' example: 'Groupe local n°1;<b>Groupe local n°1</b>;123'
file: '/csv/groupe.csv' filecsv: '/csv/groupe.csv'
filexls: '/csv/groupe.xlsx'
filenum: '/csv/groupe.numbers'
comptoir: comptoir:
header: 'groupe;name;content;phone;adresse;cpostal;ville;compte' header: 'groupe;nom;description;adresse;cpostal;ville;latitude;longitude;compte;contact1;phone1;email1;contact2;phone2;email2;contact3;phone3;email3'
example: 'Comptoir n°1;Comptoir n°1;<b>Comptoir n°1</b>;0123456789;2, rue charles de gaulle;12345;Paris;123,45' example: 'Groupe local n°1;Comptoir n°1;<b>Comptoir n°1</b>;2, rue charles de gaulle;12345;Paris;45,12345;3,12345;123;M. Jean Dupont;0612345678;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com;Contact 3;0198765432;contact.comptoir2@email.com'
file: '/csv/comptoir.csv' filecsv: '/csv/comptoir.csv'
filexls: '/csv/comptoir.xlsx'
filenum: '/csv/comptoir.numbers'
adherent: adherent:
header: 'groupe;firstname;lastname;email;phone;mobile;adresse;cpostal;ville;ecompte;cotisations' header: 'groupe;firstname;lastname;email;phone;mobile;adresse;cpostal;ville;ecompte;cotisations'
example: 'Groupe local n°1;Jean;Dupont;jean.dupont@gmail.com;013456789;0612345678;"2; rue Charles de gaulle";12345;Paris;"12,34";"10:2017,10:2018,10:2019"' example: 'Groupe local n°1;Jean;Dupont;jean.dupont@gmail.com;013456789;0612345678;"2; rue Charles de gaulle";12345;Paris;"12,34";"10:2017,10:2018,10:2019"'
file: '/csv/adherent.csv' filecsv: '/csv/adherent.csv'
filexls: '/csv/adherent.xlsx'
filenum: '/csv/adherent.numbers'
prestataire: prestataire:
header: 'groupe;adresse;cpostal;ville;raison;metier;statut;responsable;iban;siret;web;compte;horaires;description;firstname;lastname;email;phone;mobile;rubriques;cotisations' header: 'groupe;adresse;cpostal;ville;raison;ecompte;metier;statut;responsable;iban;siret;web;horaires;description;rubriques;tags;tauxreconversion;contact1;phone1;email1;contact2;phone2;email2;contact3;phone3;email3'
example: 'Groupe local n°1;"2; rue Charles de gaulle";12345;Paris;Amap d’exemple;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;"123,45";Dimanche de 8h à 12h;<b>Description du prestataire</b>;Jean;Dupont;jean@gmail.com;0123456789;0612345678;Amap,Fruits,Légumes,Marchés;"10:2017,10:2018,10:2019"' example: 'Groupe local n°1;2, rue Charles de gaulle;12345;Paris;Nom du prestataire;123,45;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0698765432;contact.comptoir@email.com;Contact 3;0198765432;contact.comptoir2@email.com'
file: '/csv/prestataire.csv' filecsv: '/csv/prestataire.csv'
filexls: '/csv/prestataire.xlsx'
filenum: '/csv/prestataire.numbers'
# SERVICES # SERVICES
services: services:
...@@ -411,7 +419,7 @@ services: ...@@ -411,7 +419,7 @@ services:
admin.import: admin.import:
class: App\Admin\ImportAdmin class: App\Admin\ImportAdmin
arguments: [~, ~, App\Controller\ImportController] arguments: [~, App\Entity\Import, App\Controller\ImportController]
tags: tags:
- name: sonata.admin - name: sonata.admin
manager_type: orm manager_type: orm
......
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
"entrypoints": { "entrypoints": {
"app": { "app": {
"js": [ "js": [
"/build/runtime.js", "/build/runtime.420770e4.js",
"/build/app.js" "/build/app.a6090119.js"
], ],
"css": [ "css": [
"/build/app.css" "/build/app.b1a10d11.css"
] ]
}, },
"admin": { "admin": {
"js": [ "js": [
"/build/runtime.js", "/build/runtime.420770e4.js",
"/build/admin.js" "/build/admin.da628ab6.js"
], ],
"css": [ "css": [
"/build/admin.css" "/build/admin.b8c3eca8.css"
] ]
} }
} }
......
{ {
"build/admin.css": "/build/admin.css", "build/admin.css": "/build/admin.b8c3eca8.css",
"build/admin.js": "/build/admin.js", "build/admin.js": "/build/admin.da628ab6.js",
"build/app.css": "/build/app.css", "build/app.css": "/build/app.b1a10d11.css",
"build/app.js": "/build/app.js", "build/app.js": "/build/app.a6090119.js",
"build/runtime.js": "/build/runtime.js", "build/runtime.js": "/build/runtime.420770e4.js",
"build/ckeditor/adapters/jquery.js": "/build/ckeditor/adapters/jquery.js", "build/ckeditor/adapters/jquery.js": "/build/ckeditor/adapters/jquery.js",
"build/ckeditor/ckeditor.js": "/build/ckeditor/ckeditor.js", "build/ckeditor/ckeditor.js": "/build/ckeditor/ckeditor.js",
"build/ckeditor/config.js": "/build/ckeditor/config.js", "build/ckeditor/config.js": "/build/ckeditor/config.js",
......
groupe;firstname;lastname;email;phone;mobile;adresse;cpostal;ville;ecompte;cotisations groupe;email;prenom;nom;phone;mobile;adresse;cpostal;ville;ecompte;cotisations
Nom du groupe local;Prénom;Nom de famille;Courriel / Email valide;Numéro de téléphone fixe;Numéro de téléphone mobile;Adresse complète;Code postal;Nom de la ville;Compte numérique (non obligatoire);Cotisations (montant:année,montant:année... => exemple : 10:2017,10,2018,10:2019) Groupe local n°1;jean.dupont@gmail.com;Jean;Dupont;13456789;612345678;2, rue Charles de gaulle;12345;Paris;123;10:2017,10:2018,10:2019
"Groupe local n°1";Jean;Dupont;"jean.dupont@gmail.com";013456789;0612345678;"2, rue Charles de gaulle";12345;Paris;"12,34";"10:2017,10:2018,10:2019" \ No newline at end of file
\ No newline at end of file
groupe;name;content;phone;mobile;adresse;cpostal;ville;compte groupe;nom;description;adresse;cpostal;ville;latitude;longitude;compte;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1;contact1;phone1;email1;contact2;phone2;email2
Nom du groupe local;Nom du comptoir;Description du comptoir (html);Téléphone fixe du comptoir;Téléphone mobile du comptoir;Adresse complète;Code postal;Nom de la ville;Compte du comtoir en monnaie locale Groupe local n°1;Comptoir n°1;<b>Comptoir n°1</b>;2, rue charles de gaulle;12345;Paris;45,12345;3,12345;123;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
Groupe local n°1;Comptoir n°1;<b>Comptoir n°1</b>;123,45;0123456789;0612345678;2, rue charles de gaulle;12345;Paris;123,45 Groupe local n°1;;;2, rue charles de gaulle;;Paris;45,12345;3,12345;123;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
\ No newline at end of file \ No newline at end of file
name;content;compte nom;description;compte;gestionnaire_email1;gestionnaire_nom1;gestionnaire_prenom1;gestionnaire_phone1;gestionnaire_mobile1
Nom du groupe local;Description du groupe (html);Compte de billet MLC Groupe local n°1;<b>Groupe local n°1</b>;123;john.doe@email.com;Doe;John;0123456789;0623456789
Groupe local n°1;<b>Groupe local n°1</b>;123 \ No newline at end of file
\ No newline at end of file
groupe;adresse;cpostal;ville;raison;metier;statut;responsable;iban;siret;web;compte;horaires;description;firstname;lastname;email;phone;mobile;rubriques;cotisations 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
Nom du groupe local;Adresse complète;Code postal;Nom de la ville;Raison social;Métier de l’utilisateur;Statut;Nom du responsable;Numéro IBAN;Numéro de SIRET;Site internet;Compte de monnaie locale;Horaires (non obligatoire, html);Description (html);Prénom de l’utilisateur;Nom de l’utilisateur;Courriel / Email;Téléphone fixe;Téléphone mobile;Rubriques (séparés par une virgule);"10:2018,10:2019" Groupe local n°1;2, rue Charles de gaulle;12345;Paris;Nom du prestataire;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
Groupe local n°1;2, rue Charles de gaulle;12345;Paris;Amap d’exemple;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;123,45;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Jean;Dupont;jean@gmail.com;0123456789;0612345678;Amap,Fruits,Légumes,Marchés;10 Groupe local n°2;;12345;Paris;Nom du prestataire;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
\ No newline at end of file ;a;12345;Paris;Nom du prestataire;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
Groupe local n°3;a;;Paris;Nom du prestataire;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
Groupe local n°4;a;75001;;Nom du prestataire;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
Groupe local n°5;a;75001;Paris;;0;Directeur;SARL;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
;;;;;;;;Jean Dupont;FR7630001007941234567890185;732 829 320 00074;www.siteweb.com;Dimanche de 8h à 12h;<b>Description du prestataire</b>;Amap,Fruits,Légumes,Marchés;tag1,tag2;2;10:2017,10:2018,10:2019;john.doe@email.com;Doe;John;0123456789;0623456789;M. Jean Dupont;0123456789;jean.dupont@email.com;Contact comptoir;0198765432;contact.comptoir@email.com
...@@ -8,6 +8,7 @@ use Sonata\AdminBundle\Datagrid\ListMapper; ...@@ -8,6 +8,7 @@ use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Form\Type\Filter\ChoiceType; use Sonata\AdminBundle\Form\Type\Filter\ChoiceType;
use Sonata\AdminBundle\Route\RouteCollection; use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
...@@ -21,19 +22,108 @@ class ImportAdmin extends AbstractAdmin ...@@ -21,19 +22,108 @@ class ImportAdmin extends AbstractAdmin
{ {
protected $baseRoutePattern = 'importdata'; protected $baseRoutePattern = 'importdata';
protected $baseRouteName = 'importdata'; protected $baseRouteName = 'importdata';
protected $datagridValues = [
// reverse order (default = 'ASC')
'_sort_order' => 'DESC',
// name of the ordered field (default = the model's id field, if any)
'_sort_by' => 'createdAt',
// '_page' => 1,
// '_per_page' => 32
];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function configureRoutes(RouteCollection $collection) protected function configureRoutes(RouteCollection $collection)
{ {
$collection->clearExcept('list'); $collection->clearExcept(array('list', 'create', 'show'));
}
/**
* {@inheritdoc}
*/
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
$query
->innerJoin($query->getRootAliases()[0] .'.user', 'u')
->addSelect('u')
;
return $query;
}
public function configureActionButtons($action, $object = null)
{
$list = parent::configureActionButtons($action, $object);
$list['create']['template'] = '@SonataAdmin/CRUD/import_button.html.twig';
// $list['show']['template'] = '@SonataAdmin/CRUD/import_button.html.twig';
return $list;
} }
protected function configureListFields(ListMapper $listMapper): void protected function configureListFields(ListMapper $listMapper): void
{ {
parent::configureListFields($listMapper); parent::configureListFields($listMapper);
unset($this->listModes['mosaic']); unset($this->listModes['mosaic']);
$listMapper
->addIdentifier('createdAt', 'datetime', ['label' => 'Date'])
->add('user', null, ['label' => 'Utilisateur'])
->addIdentifier('type')
->add('nbentityadded', null, ['label' => 'Lignes correctes'])
->add('nbentityerror', null, ['label' => 'Lignes en erreurs'])
->add('media', null, ['label' => 'Fichier'])
->add('_action', null, [
'actions' => [
'show' => [],
]
])
;
}
protected function configureShowFields(ShowMapper $showMapper): void
{
$object = $showMapper->getAdmin()->getSubject();
$showMapper
->with('Import')
->add('createdAt')
->add('user')
->add('type')
->add('media')
->add('nbentityadded', null, ['label' => 'Lignes correctes'])
->add('nbentityerror', null, ['label' => 'Lignes en erreurs'])
->end();
if (!empty(json_decode($object->getSuccess()))) {
$showMapper
->with('Correct', [
'box_class' => 'box box-solid box-success',
// 'description' => 'Lorem ipsum',
])
->add('success', 'json', ['label' => false])
->end()
;
}
if (!empty(json_decode($object->getWarnings()))) {
$showMapper
->with('Warnings', [
'box_class' => 'box box-solid box-warning',
// 'description' => 'Lorem ipsum',
])
->add('warnings', 'json', ['label' => false])
->end()
;
}
if (!empty(json_decode($object->getErrors()))) {
$showMapper
->with('Erreurs', [
'box_class' => 'box box-solid box-danger',
// 'description' => 'Lorem ipsum',
])
->add('errors', 'json', ['label' => false])
->end()
;
}
;
} }
public function getBatchActions() public function getBatchActions()
......
...@@ -89,7 +89,7 @@ class AdminController extends Controller ...@@ -89,7 +89,7 @@ class AdminController extends Controller
/** /**
* @Route("/admin/getcsv", name="getcsv") * @Route("/admin/getcsv", name="getcsv")
* @IsGranted({"ROLE_ADMIN_IMPORT_EDIT", "ROLE_ADMIN_IMPORT_LIST", "ROLE_ADMIN_IMPORT_CREATE", "ROLE_ADMIN_IMPORT_VIEW", "ROLE_ADMIN_IMPORT_DELETE", "ROLE_ADMIN_IMPORT_EXPORT", "ROLE_ADMIN_IMPORT_ALL"}) * @IsGranted({"ROLE_SUPER_ADMIN", "ROLE_ADMIN_IMPORT_EDIT", "ROLE_ADMIN_IMPORT_LIST", "ROLE_ADMIN_IMPORT_CREATE", "ROLE_ADMIN_IMPORT_VIEW", "ROLE_ADMIN_IMPORT_DELETE", "ROLE_ADMIN_IMPORT_EXPORT", "ROLE_ADMIN_IMPORT_ALL"})
*/ */
public function getCsvAction(Request $request) public function getCsvAction(Request $request)
{ {
......
...@@ -42,6 +42,55 @@ class Import ...@@ -42,6 +42,55 @@ class Import
*/ */
private $user; private $user;
/**
* @var string|null
*
* @ORM\Column(type="json", nullable=true)
*/
private $errors;
/**
* @var string|null
*
* @ORM\Column(type="json", nullable=true)
*/
private $success;
/**
* @var string|null
*
* @ORM\Column(type="json", nullable=true)
*/
private $warnings;
/**
* @var string
*
* @ORM\Column(name="type", type="string", length=100)
*/
private $type;
/**
* @var string
*
* @ORM\Column(name="nbentityadded", type="integer", nullable=true)
*/
private $nbentityadded;
/**
* @var string
*
* @ORM\Column(name="nbentityerror", type="integer", nullable=true)
*/
private $nbentityerror;
/**
* @var string
*
* @ORM\Column(name="sendemail", type="string", length=100)
*/
private $sendemail;
public function __construct() public function __construct()
{ {
$this->setEnabled(false); $this->setEnabled(false);
...@@ -92,8 +141,141 @@ class Import ...@@ -92,8 +141,141 @@ class Import
return $this; return $this;
} }
/**
* Get errors
* @return
*/
public function getErrors()
{
return $this->errors;
}
/**
* Set errors
* @return $this
*/
public function setErrors($errors)
{
$this->errors = $errors;
return $this;
}
/**
* Get success
* @return
*/
public function getSuccess()
{
return $this->success;
}
/**
* Set success
* @return $this
*/
public function setSuccess($success)
{
$this->success = $success;
return $this;
}
/**
* Get warnings
* @return
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* Set warnings
* @return $this
*/
public function setWarnings($warnings)
{
$this->warnings = $warnings;
return $this;
}
/**
* Get type
* @return
*/
public function getType(): ?string
{
return $this->type;
}
/**
* Get sendemail
* @return
*/
public function getSendemail()
{
return $this->sendemail;
}
/**
* Set sendemail
* @return $this
*/
public function setSendemail($sendemail)
{
$this->sendemail = $sendemail;
return $this;
}
/**
* Get nbentityadded
* @return
*/
public function getNbentityadded()
{
return $this->nbentityadded;
}
/**
* Set nbentityadded
* @return $this
*/
public function setNbentityadded($nbentityadded)
{
$this->nbentityadded = $nbentityadded;
return $this;
}
/**
* Get nbentityerror
* @return
*/
public function getNbentityerror()
{
return $this->nbentityerror;
}
/**
* Set nbentityerror
* @return $this
*/
public function setNbentityerror($nbentityerror)
{
$this->nbentityerror = $nbentityerror;
return $this;
}
/**
* Set type
* @return $this
*/
public function setType(?string $type): self
{
$this->type = $type;
return $this;
}
public function __toString(): string public function __toString(): string
{ {
return 'Import du '.$this->getCreatedAt()?$this->getCreatedAt()->format('d/m/Y H:i'):'?'; return 'Import de '.$this->getType().' du '.($this->getCreatedAt()?$this->getCreatedAt()->format('d/m/Y H:i'):'?');
} }
} }
...@@ -37,7 +37,6 @@ class Prestataire ...@@ -37,7 +37,6 @@ class Prestataire
{ {
use EnablableEntityTrait, use EnablableEntityTrait,
TimestampableEntity, TimestampableEntity,
HasCompteEntity,
HasEcompteEntity; HasEcompteEntity;
/** /**
...@@ -101,6 +100,7 @@ class Prestataire ...@@ -101,6 +100,7 @@ class Prestataire
/** /**
* @ORM\Column(name="iban", type="string", length=100, nullable=true) * @ORM\Column(name="iban", type="string", length=100, nullable=true)
* @todo : vérification de l'IBAN via assert/iban
* Assert\Iban(message="L'IBAN(International Bank Account Number) est invalide.") * Assert\Iban(message="L'IBAN(International Bank Account Number) est invalide.")
* @Groups({"read", "write"}) * @Groups({"read", "write"})
*/ */
...@@ -109,7 +109,7 @@ class Prestataire ...@@ -109,7 +109,7 @@ class Prestataire
/** /**
* @var string * @var string
* *
* @ORM\Column(name="siret", type="string", length=50) * @ORM\Column(name="siret", type="string", length=50, nullable=true)
* @Groups({"read", "write"}) * @Groups({"read", "write"})
*/ */
private $siret; private $siret;
......
...@@ -531,7 +531,7 @@ class User extends BaseUser ...@@ -531,7 +531,7 @@ class User extends BaseUser
public function __toString() public function __toString()
{ {
if (empty($this->getFullname())) { if (empty(trim($this->getFullname()))) {
return $this->getEmail(); return $this->getEmail();
} }
return $this->getFullname(); return $this->getFullname();
...@@ -539,7 +539,7 @@ class User extends BaseUser ...@@ -539,7 +539,7 @@ class User extends BaseUser
public function getName() public function getName()
{ {
if (empty($this->getFullname())) { if (empty(trim($this->getFullname()))) {
return $this->__toString(); return $this->__toString();
} }
return $this->getFullname(); return $this->getFullname();
......
<?php
namespace App\Enum;
abstract class ImportEnum
{
const IMPORT_GROUPE = "groupe";
const IMPORT_COMPTOIR = "comptoir";
const IMPORT_PRESTATAIRE = "prestataire";
const IMPORT_ADHERENT = "adherent";
/** @var array user friendly named type */
protected static $typeName = [
self::IMPORT_GROUPE => 'Groupe(s)',
self::IMPORT_COMPTOIR => 'Comptoir(s)',
self::IMPORT_PRESTATAIRE => 'Prestataire(s)',
self::IMPORT_ADHERENT => 'Adherent(s)',
];
/**
* @param string $typeShortName
* @return string
*/
public static function getTypeName($typeShortName)
{
if (!isset(static::$typeName[$typeShortName])) {
return "Unknown type ($typeShortName)";
}
return static::$typeName[$typeShortName];
}
/**
* @return array<string>
*/
public static function getAvailableTypes()
{
return [
self::IMPORT_GROUPE,
self::IMPORT_COMPTOIR,
self::IMPORT_PRESTATAIRE,
self::IMPORT_ADHERENT
];
}
}
...@@ -107,14 +107,11 @@ class MLCEventListener implements EventSubscriberInterface ...@@ -107,14 +107,11 @@ class MLCEventListener implements EventSubscriberInterface
public function onFlux(FluxEvent $event) public function onFlux(FluxEvent $event)
{ {
dump("onflux");
foreach ($event->getFlux()->getUsersToNotify() as $user) { foreach ($event->getFlux()->getUsersToNotify() as $user) {
dump($user);
if ($user instanceof User && $user->getAlertemailflux()) { if ($user instanceof User && $user->getAlertemailflux()) {
$this->sendMail($user, $event->getFlux()); $this->sendMail($user, $event->getFlux());
} elseif ($user == 'siege') { } elseif ($user == 'siege') {
$users = $this->em->getRepository(User::class)->findByRole('ROLE_ADMIN_SIEGE'); $users = $this->em->getRepository(User::class)->findByRole('ROLE_ADMIN_SIEGE');
dump($users);
foreach ($users as $userAdminSiege) { foreach ($users as $userAdminSiege) {
if ($userAdminSiege->getAlertemailflux()) { if ($userAdminSiege->getAlertemailflux()) {
$this->sendMail($userAdminSiege, $event->getFlux()); $this->sendMail($userAdminSiege, $event->getFlux());
......
...@@ -4,11 +4,14 @@ namespace App\Form\Type; ...@@ -4,11 +4,14 @@ namespace App\Form\Type;
use App\Entity\Import; use App\Entity\Import;
use App\Entity\User; use App\Entity\User;
use App\Enum\ImportEnum;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Sonata\MediaBundle\Form\Type\MediaType; use Sonata\MediaBundle\Form\Type\MediaType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
...@@ -26,7 +29,7 @@ class ImportFormType extends AbstractType ...@@ -26,7 +29,7 @@ class ImportFormType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options) public function buildForm(FormBuilderInterface $builder, array $options)
{ {
if (empty($this->security) && !empty($this->security->getUser())) { if (empty($this->security) || empty($this->security->getUser())) {
throw new \Exception("Opération impossible ! Utilisateur non connecté !"); throw new \Exception("Opération impossible ! Utilisateur non connecté !");
} }
$builder $builder
...@@ -34,15 +37,29 @@ class ImportFormType extends AbstractType ...@@ -34,15 +37,29 @@ class ImportFormType extends AbstractType
'provider' => 'sonata.media.provider.file', 'provider' => 'sonata.media.provider.file',
'context' => 'import', 'context' => 'import',
'label' => 'Fichier .csv', 'label' => 'Fichier .csv',
'show_unlink' => false 'show_unlink' => false,
'required' => true,
)) ))
->add('user', HiddenType::class, array( ->add('user', HiddenType::class, array(
'data_class' => null, 'data_class' => null,
'data' => $this->security->getUser()->getId(), 'data' => $this->security->getUser()->getId(),
'entity_class' => User::class, 'entity_class' => User::class,
'em' => $this->em 'em' => $this->em
)) ))
->add('type', ChoiceType::class, array(
'label' => 'Choisir le type de données à importer : ',
'placeholder' => '',
'required' => true,
'choices' => ImportEnum::getAvailableTypes(),
'choice_label' => function ($choice) {
return ImportEnum::getTypeName($choice);
},
))
->add('sendemail', CheckboxType::class, array(
'label' => 'Envoyé un email aux nouveaux comptes créés ?',
'required' => false,
'label_attr' => array('class' => 'checkbox-inline')
))
->add('save', SubmitType::class, ['label' => "Importer les données"]) ->add('save', SubmitType::class, ['label' => "Importer les données"])
; ;
} }
......
<?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 Version20200619102406 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->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE import ADD type VARCHAR(100) NOT NULL, ADD errors LONGTEXT DEFAULT NULL');
$this->addSql('ALTER TABLE prestataire DROP compte, CHANGE siret siret VARCHAR(50) DEFAULT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
$this->addSql('ALTER TABLE import DROP type, DROP errors');
$this->addSql('ALTER TABLE prestataire ADD compte NUMERIC(12, 2) NOT NULL, CHANGE siret siret VARCHAR(50) CHARACTER SET utf8 NOT NULL COLLATE `utf8_general_ci`');
}
}
<?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 Version20200619122226 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 import ADD success LONGTEXT DEFAULT NULL, ADD warnings LONGTEXT DEFAULT NULL');
$this->addSql('ALTER TABLE siege CHANGE ecompte ecompte NUMERIC(12, 2) NOT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE import DROP success, DROP warnings');
$this->addSql('ALTER TABLE siege CHANGE ecompte ecompte NUMERIC(12, 2) DEFAULT \'0.00\' NOT NULL');
}
}
<?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 Version20200619134116 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 import ADD sendemail VARCHAR(100) NOT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE import DROP sendemail');
}
}
<?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 Version20200622095500 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 import ADD nbentityadded INT DEFAULT NULL, ADD nbentityerror INT DEFAULT NULL, CHANGE errors errors LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json)\', CHANGE success success LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json)\', CHANGE warnings warnings LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:json)\'');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE import DROP nbentityadded, DROP nbentityerror, CHANGE errors errors LONGTEXT CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`, CHANGE success success LONGTEXT CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`, CHANGE warnings warnings LONGTEXT CHARACTER SET utf8 DEFAULT NULL COLLATE `utf8_general_ci`');
}
}
...@@ -64,6 +64,19 @@ class AppExtension extends AbstractExtension ...@@ -64,6 +64,19 @@ class AppExtension extends AbstractExtension
]; ];
} }
public function getFilters()
{
return array(
new \Twig_SimpleFilter('json_decode', [$this, 'jsonDecode']),
new \Twig_SimpleFilter('safe_email', [$this, 'safeEmailFilter']),
);
}
public function jsonDecode($string)
{
return json_decode($string, true);
}
public function showModalGroupChoice() public function showModalGroupChoice()
{ {
if ($this->security->getUser() != null) { if ($this->security->getUser() != null) {
...@@ -157,18 +170,6 @@ class AppExtension extends AbstractExtension ...@@ -157,18 +170,6 @@ class AppExtension extends AbstractExtension
return $this->em->getRepository(Rubrique::class)->findBy(array('enabled' => true), array('name'=> 'ASC')); return $this->em->getRepository(Rubrique::class)->findBy(array('enabled' => true), array('name'=> 'ASC'));
} }
/**
* Return a list of all filters.
*
* @return array
*/
public function getFilters()
{
return [
new \Twig_SimpleFilter('safe_email', [$this, 'safeEmailFilter']),
];
}
public function getAllFlux(User $user, Request $request, $parenttype = null) public function getAllFlux(User $user, Request $request, $parenttype = null)
{ {
$query = null; $query = null;
......
...@@ -16,25 +16,56 @@ ...@@ -16,25 +16,56 @@
{{ 'Import de données'|trans }} {{ 'Import de données'|trans }}
{% endblock %} {% endblock %}
{% block sonata_admin_content_actions_wrappers %}
<div class="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<a class="sonata-action-element" href="{{ admin.generateUrl('list') }}">
<i class="fa fa-list" aria-hidden="true"></i>
{{ 'link_action_list'|trans({}, 'SonataAdminBundle') }}
</a>
</li>
</ul>
</div>
{% endblock sonata_admin_content_actions_wrappers %}
{% block navbar_title %} {% block navbar_title %}
{{ block('title') }} {{ block('title') }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="p-4"> <div class="px-3">
<h4><u>{{ "Exemples d'importations possible (Fichiers .csv uniquement):"|trans }}</u></h4> <h3>Recommandations et instructions :</h3>
<ul>
<li>{{ "L'importation de données ne fonctionne qu'avec des fichiers .CSV, et ayant au moins les colonnes obligatoires (celle en rouge dans les fichiers d'instructions)"|trans }}</li>
<li>{{ "L'ordre des colonnes n'a pas d'importance, mais les noms des colonnes utilisés dans la première ligne du fichier CSV ne sont pas modifiable."|trans }}</li>
<li>{{ "Pour chaque type de données (groupe, comptoir, prestataire, adherent) à importer, vous pouvez télécharger des fichiers d'exemples et d'instructions .XLSX (Excel - Windows) et .NUMBERS (Mac - Numbers), mais seul un fichier .CSV peut être importé !"|trans }}</li>
<li>{{ "Les gestionnaires (de comptoir, groupe et prestataire) correspondent aux adhérents ayant accès à l'interface d'administration !"|trans }}</li>
<li>{{ "Les contacts (de comptoir, groupe et prestataire) correspondent à des informations publiques permettant de contacter les comptoirs, groupes et prestataires, ils n'ont pas de compte crée avec leur email !"|trans }}</li>
<li>{{ "Pour les comptoirs, groupes et prestataires, vous pouvez ajouter un ou plusieurs gestionnaires (gestionnaire_email1, gestionnaire_email2), un ou plusieurs contacts par défaut visible en public (contact1, contact2) et jusqu'à 10 de chaque !"|trans }}</li>
</ul>
<h3>Exemples de fichiers :</h3>
<div class='mb-5'> <div class='mb-5'>
{% for key, csvparam in csvparams %} {% for key, csvparam in csvparams %}
<h5><strong>{{ key|capitalize }} : </strong><a class='ml-4' target='_blank' href='{{ csvparam.file }}'>Télécharger un exemple</a></h5> <h4>{{ key|capitalize }}(s) : </h4>
<p class='ml-4'><i>{{ csvparam.header }}</i></p> <p>
<p class='ml-4 mb-4'><i>{{ 'Exemple'|trans }} :</i> {{ csvparam.example }}</p> <a class='btn btn-default ml-4' target='_blank' href='{{ csvparam.filexls }}'>Instructions en .xlsx</a>
<a class='btn btn-default ml-4' target='_blank' href='{{ csvparam.filenum }}'>Instructions en .numbers</a>
<a class='btn btn-default ml-4' target='_blank' href='{{ csvparam.filecsv }}'>Exemple .csv</a>
</p>
{# <p class='ml-4'><i>{{ csvparam.header }}</i></p>
<p class='ml-4 mb-4'><i>{{ 'Exemple'|trans }} :</i> {{ csvparam.example }}</p> #}
{% endfor %} {% endfor %}
</div> </div>
{{form_start(form)}} <hr class='color-blue'/>
{{ form_start(form) }}
{{ form_row(form.type) }}
{{ form_row(form.sendemail) }}
{{ form_row(form.media) }} {{ form_row(form.media) }}
{{ form_errors(form) }}
{{ form_row(form.user) }} {{ form_row(form.user) }}
{{ form_row(form.save) }} {{ form_row(form.save) }}
{{form_end(form)}} {{ form_end(form) }}
{% if errors is defined and errors|length > 0 %} {% if errors is defined and errors|length > 0 %}
<div class='container bg-danger w-100 py-4 row'> <div class='container bg-danger w-100 py-4 row'>
......
{% trans_default_domain 'messages' %}
{% set userlogintitle = 'Créer votre mot de passe'|trans %}
{% extends "@FOSUser/layout.html.twig" %}
{% block fos_user_content %}
{{ form_start(form, { 'action': path('fos_user_resetting_reset', {'token': token}), 'attr': { 'class': 'fos_user_resetting_reset' } }) }}
{{ form_widget(form) }}
<div>
<input type="submit" value="{{ 'Valider'|trans }}" />
</div>
{{ form_end(form) }}
{% endblock fos_user_content %}
{% if admin.hasAccess('create') and admin.hasRoute('create') %}
{% if admin.subClasses is empty %}
<li>
<a class="sonata-action-element" href="{{ admin.generateUrl('create') }}">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
{{ 'Importer'|trans({}, 'messages') }}
</a>
</li>
{% else %}
{% for subclass in admin.subclasses|keys %}
<li>
<a class="sonata-action-element" href="{{ admin.generateUrl('create', {'subclass': subclass}) }}">
<i class="fa fa-plus-circle" aria-hidden="true"></i>
{{ 'Importer'|trans({}, 'messages') }} {{ subclass|trans({}, admin.translationdomain) }}
</a>
</li>
{% endfor %}
{% endif %}
{% endif %}
{# templates/fieldtypes/show_json.html.twig #}
{% extends '@SonataAdmin/CRUD/base_show_field.html.twig' %}
{% block field %}
{% set valarray = value|json_decode %}
{# {{dump(valarray|raw)}} #}
{# {{ value|json_decode|raw }} #}
<p><em>( La ligne 1 est ignorée, elle contient le nom des colonnes )</em></p>
{% for key, val in valarray %}
<p><strong>Ligne {{key}}</strong></p>
<ul>
{% for key2, val2 in val %}
<li>Colonne "{{key2}}" <ul><li>{{val2}}</li></ul></li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
\ No newline at end of file
...@@ -9,10 +9,11 @@ ...@@ -9,10 +9,11 @@
<h2 style="font-size: 18px; color: #111111; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-weight: bold; line-height: 1.2em; margin: 40px 0 10px;">{{ 'Valider la création de votre compte'|trans }}</h2><br/> <h2 style="font-size: 18px; color: #111111; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-weight: bold; line-height: 1.2em; margin: 40px 0 10px;">{{ 'Valider la création de votre compte'|trans }}</h2><br/>
<p> <p>
{{ 'Un administreur a crée votre nouveau compte MLC'|trans }} {{ 'Un administreur a crée votre nouveau compte MLC'|trans }}
{{ user.commonname|title }} {{ user.name|title }}
</p> </p>
<p> <p>
{{ 'Pour valider votre nouveau compte, cliquez '|trans }}<a href='{{confirmationUrl}}'>{{ 'ICI'|trans }}</a> {{ 'Pour valider votre nouveau compte, cliquez sur ce lien : '|trans }}<br/>
<a href='{{confirmationUrl}}'>{{confirmationUrl}}</a>
</p> </p>
{% endblock %} {% endblock %}
\ No newline at end of file
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