Merge remote-tracking branch 'origin/master' into features/household-validation

This commit is contained in:
2021-06-18 12:02:34 +02:00
83 changed files with 3539 additions and 647 deletions

View File

@@ -0,0 +1,41 @@
<?php
namespace Chill\MainBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Intl\Intl;
use Chill\MainBundle\Entity\Notification;
/**
* Load notififications into database
*/
trait LoadAbstractNotificationsTrait
{
public function load(ObjectManager $manager)
{
foreach ($this->notifs as $notif) {
$entityId = $this->getReference($notif['entityRef'])->getId();
print('Adding notification for '.$notif['entityClass'].'(entity id:'.$entityId.")\n");
$newNotif = (new Notification())
->setMessage($notif['message'])
->setSender($this->getReference($notif['sender']))
->setRelatedEntityClass($notif['entityClass'])
->setRelatedEntityId($entityId)
->setDate(new \DateTimeImmutable('now'))
->setRead([])
;
foreach ($notif['addressees'] as $addressee) {
$newNotif->addAddressee($this->getReference($addressee));
}
$manager->persist($newNotif);
$manager->flush();
}
}
}

View File

@@ -115,7 +115,6 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
$loader->load('services.yaml');
$loader->load('services/doctrine.yaml');
$loader->load('services/logger.yaml');
$loader->load('services/repositories.yaml');
$loader->load('services/pagination.yaml');
$loader->load('services/export.yaml');
$loader->load('services/form.yaml');
@@ -278,7 +277,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
'methods' => [
Request::METHOD_GET => true,
Request::METHOD_POST => true,
Request::METHOD_HEAD => true
Request::METHOD_HEAD => true,
Request::METHOD_PATCH => true
]
],
]
@@ -320,7 +320,8 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
'_entity' => [
'methods' => [
Request::METHOD_GET => true,
Request::METHOD_HEAD => true
Request::METHOD_HEAD => true,
Request::METHOD_POST => true,
]
],
]

View File

@@ -11,7 +11,7 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty;
/**
* Address
*
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="chill_main_address")
* @ORM\HasLifecycleCallbacks()
*/

View File

@@ -7,7 +7,7 @@ use Chill\MainBundle\Doctrine\Model\Point;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="chill_main_address_reference")
* @ORM\HasLifecycleCallbacks()
*/

View File

@@ -25,7 +25,7 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\CenterRepository")
* @ORM\Entity
* @ORM\Table(name="centers")
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>

View File

@@ -8,7 +8,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
/**
* Country
*
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="country")
* @ORM\Cache(usage="READ_ONLY", region="country_cache_region")
* @ORM\HasLifecycleCallbacks()

View File

@@ -27,7 +27,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="group_centers")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
*

View File

@@ -25,7 +25,7 @@ use Doctrine\ORM\Mapping as ORM;
/**
* Language
*
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="language")
* @ORM\Cache(usage="READ_ONLY", region="language_cache_region")
* @ORM\HasLifecycleCallbacks()

View File

@@ -0,0 +1,187 @@
<?php
/*
* Copyright (C) 2021 Champs-Libres <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Entity;
use Chill\MainBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(
* name="chill_main_notification",
* uniqueConstraints={
* @ORM\UniqueConstraint(columns={"relatedEntityClass", "relatedEntityId"})
* }
* )
*/
class Notification
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private int $id;
/**
* @ORM\Column(type="text")
*/
private string $message;
/**
* @ORM\Column(type="datetime_immutable")
*/
private \DateTimeImmutable $date;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=false)
*/
private User $sender;
/**
* @ORM\ManyToMany(targetEntity=User::class)
* @ORM\JoinTable(name="chill_main_notification_addresses_user")
*/
private Collection $addressees;
/**
* @ORM\Column(type="string", length=255)
*/
private string $relatedEntityClass;
/**
* @ORM\Column(type="integer")
*/
private int $relatedEntityId;
/**
* @ORM\Column(type="json")
*/
private array $read;
public function __construct()
{
$this->addressees = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getMessage(): ?string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
public function getDate(): ?\DateTimeImmutable
{
return $this->date;
}
public function setDate(\DateTimeImmutable $date): self
{
$this->date = $date;
return $this;
}
public function getSender(): ?User
{
return $this->sender;
}
public function setSender(?User $sender): self
{
$this->sender = $sender;
return $this;
}
/**
* @return Collection|User[]
*/
public function getAddressees(): Collection
{
return $this->addressees;
}
public function addAddressee(User $addressee): self
{
if (!$this->addressees->contains($addressee)) {
$this->addressees[] = $addressee;
}
return $this;
}
public function removeAddressee(User $addressee): self
{
$this->addressees->removeElement($addressee);
return $this;
}
public function getRelatedEntityClass(): ?string
{
return $this->relatedEntityClass;
}
public function setRelatedEntityClass(string $relatedEntityClass): self
{
$this->relatedEntityClass = $relatedEntityClass;
return $this;
}
public function getRelatedEntityId(): ?int
{
return $this->relatedEntityId;
}
public function setRelatedEntityId(int $relatedEntityId): self
{
$this->relatedEntityId = $relatedEntityId;
return $this;
}
public function getRead(): array
{
return $this->read;
}
public function setRead(array $read): self
{
$this->read = $read;
return $this;
}
}

View File

@@ -27,7 +27,7 @@ use Chill\MainBundle\Entity\RoleScope;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="permission_groups")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
*

View File

@@ -8,7 +8,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
/**
* PostalCode
*
* @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\PostalCodeRepository")
* @ORM\Entity
* @ORM\Table(
* name="chill_main_postal_code",
* indexes={@ORM\Index(
@@ -26,7 +26,7 @@ class PostalCode
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @groups({"read"})
* @groups({"write", "read"})
*/
private $id;
@@ -34,7 +34,7 @@ class PostalCode
* @var string
*
* @ORM\Column(type="string", length=255, name="label")
* @groups({"read"})
* @groups({"write", "read"})
*/
private $name;
@@ -42,7 +42,7 @@ class PostalCode
* @var string
*
* @ORM\Column(type="string", length=100)
* @groups({"read"})
* @groups({"write", "read"})
*/
private $code;
@@ -50,10 +50,17 @@ class PostalCode
* @var Country
*
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Country")
* @groups({"read"})
* @groups({"write", "read"})
*/
private $country;
/**
* @var integer
*
* @ORM\Column(name="origin", type="integer", nullable=true)
* @groups({"write", "read"})
*/
private $origin = 0;
/**
* Get id
@@ -65,6 +72,32 @@ class PostalCode
return $this->id;
}
/**
* Set origin
*
* @param int $origin
*
* @return PostalCode
*/
public function setOrigin($origin)
{
$this->origin = $origin;
return $this;
}
/**
* Get origin
*
* @return int
*/
public function getOrigin()
{
return $this->origin;
}
/**
* Set name
*

View File

@@ -25,7 +25,7 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="role_scopes")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
*

View File

@@ -28,7 +28,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/**
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="scopes")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
* @DiscriminatorMap(typeProperty="type", mapping={

View File

@@ -12,7 +12,7 @@ use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/**
* User
*
* @ORM\Entity(repositoryClass="Chill\MainBundle\Repository\UserRepository")
* @ORM\Entity
* @ORM\Table(name="users")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE", region="acl_cache_region")
* @DiscriminatorMap(typeProperty="type", mapping={

View File

@@ -19,26 +19,18 @@
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Chill\MainBundle\Entity\Center;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Exception\TransformationFailedException;
/**
* Transform a center object to his id, and vice-versa
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class CenterTransformer implements DataTransformerInterface
{
/**
*
* @var ObjectManager
*/
private $om;
public function __construct(ObjectManager $om)
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{
$this->om = $om;
$this->em = $em;
}
public function reverseTransform($id)
@@ -46,15 +38,17 @@ class CenterTransformer implements DataTransformerInterface
if ($id === NULL) {
return NULL;
}
$center = $this->om->getRepository('ChillMainBundle:Center')
->find($id);
$center = $this
->em
->getRepository(Center::class)
->find($id);
if ($center === NULL) {
throw new TransformationFailedException(sprintf(
'No center found with id %d', $id));
}
return $center;
}
@@ -63,7 +57,7 @@ class CenterTransformer implements DataTransformerInterface
if ($center === NULL) {
return '';
}
return $center->getId();
}

View File

@@ -24,28 +24,20 @@ use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
class MultipleObjectsToIdTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $em;
/**
* @var string
*/
private $class;
/**
* @param ObjectManager $em
*/
public function __construct(ObjectManager $em, $class)
private EntityManagerInterface $em;
private ?string $class;
public function __construct(EntityManagerInterface $em, ?string $class = null)
{
$this->em = $em;
$this->class = $class;
}
/**
* Transforms an object (use) to a string (id).
*

View File

@@ -20,28 +20,20 @@
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Persistence\ObjectManager;
class ObjectToIdTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
private EntityManagerInterface $em;
/**
* @var string
*/
private $class;
private ?string $class;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om, $class)
public function __construct(EntityManagerInterface $em, ?string $class = null)
{
$this->om = $om;
$this->em = $em;
$this->class = $class;
}
@@ -73,7 +65,7 @@ class ObjectToIdTransformer implements DataTransformerInterface
return null;
}
$object = $this->om
$object = $this->em
->getRepository($this->class)
->find($id)
;

View File

@@ -19,41 +19,28 @@
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Chill\MainBundle\Entity\Scope;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityManagerInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ScopeTransformer implements DataTransformerInterface
{
/**
*
* @var ObjectManager
*/
protected $om;
/**
*
* @var TranslatableStringHelper
*/
protected $helper;
public function __construct(ObjectManager $om)
private EntityManagerInterface $em;
public function __construct(EntityManagerInterface $em)
{
$this->om = $om;
$this->em = $em;
}
public function transform($scope)
{
if ($scope === NULL) {
return NULL;
}
return $scope->getId();
}
@@ -62,15 +49,17 @@ class ScopeTransformer implements DataTransformerInterface
if ($id == NULL) {
return NULL;
}
$scope = $this->om->getRepository('ChillMainBundle:Scope')
->find($id);
$scope = $this
->em
->getRepository(Scope::class)
->find($id);
if ($scope === NULL) {
throw new TransformationFailedException(sprintf("The scope with id "
. "'%d' were not found", $id));
}
return $scope;
}

View File

@@ -22,6 +22,7 @@ use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\DataMapper\ScopePickerDataMapper;
use Chill\MainBundle\Repository\ScopeRepository;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
@@ -60,7 +61,7 @@ class ScopePickerType extends AbstractType
protected $tokenStorage;
/**
* @var EntityRepository
* @var ScopeRepository
*/
protected $scopeRepository;
@@ -72,7 +73,7 @@ class ScopePickerType extends AbstractType
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $scopeRepository,
ScopeRepository $scopeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->authorizationHelper = $authorizationHelper;

View File

@@ -25,6 +25,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Repository\UserRepository;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Role\Role;
@@ -53,16 +54,12 @@ class UserPickerType extends AbstractType
*/
protected $tokenStorage;
/**
*
* @var \Chill\MainBundle\Repository\UserRepository
*/
protected $userRepository;
protected UserRepository $userRepository;
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $userRepository
UserRepository $userRepository
) {
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;

View File

@@ -1,50 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\AddressReference;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
/**
* @method AddressReference|null find($id, $lockMode = null, $lockVersion = null)
* @method AddressReference|null findOneBy(array $criteria, array $orderBy = null)
* @method AddressReference[] findAll()
* @method AddressReference[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class AddressReferenceRepository extends ServiceEntityRepository
final class AddressReferenceRepository implements ObjectRepository
{
public function __construct(ManagerRegistry $registry)
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
parent::__construct($registry, AddressReference::class);
$this->repository = $entityManager->getRepository(AddressReference::class);
}
// /**
// * @return AddressReference[] Returns an array of AddressReference objects
// */
/*
public function findByExampleField($value)
public function find($id, $lockMode = null, $lockVersion = null): ?AddressReference
{
return $this->createQueryBuilder('a')
->andWhere('a.exampleField = :val')
->setParameter('val', $value)
->orderBy('a.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
return $this->repository->find($id, $lockMode, $lockVersion);
}
*/
/*
public function findOneBySomeField($value): ?AddressReference
public function findOneBy(array $criteria, array $orderBy = null): ?AddressReference
{
return $this->createQueryBuilder('a')
->andWhere('a.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return AddressReference[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return AddressReference[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return AddressReference::class;
}
*/
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\Address;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class AddressRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Address::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Address
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Address
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Address[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Address[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Address::class;
}
}

View File

@@ -1,27 +1,50 @@
<?php
/*
* Copyright (C) 2018 Champs-Libres <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
/**
*
*
*/
class CenterRepository extends \Doctrine\ORM\EntityRepository
use Chill\MainBundle\Entity\Center;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class CenterRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Center::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Center
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Center
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Center[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Center[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Center::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\Country;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class CountryRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Country::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Country
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Country
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Country[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Country[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Country::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\GroupCenter;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class GroupCenterRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(GroupCenter::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?GroupCenter
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?GroupCenter
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return GroupCenter[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return GroupCenter[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return GroupCenter::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\Language;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class LanguageRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Language::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Language
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Language
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Language[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Language[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Language::class;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* Copyright (C) 2021 Champs-Libres <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\Notification;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class NotificationRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Notification::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Notification
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Notification
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Notification[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Notification[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Notification::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\PermissionsGroup;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class PermissionsGroupRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(PermissionsGroup::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?PermissionsGroup
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?PermissionsGroup
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return PermissionsGroup[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return PermissionsGroup[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return PermissionsGroup::class;
}
}

View File

@@ -1,28 +1,50 @@
<?php
/*
* Copyright (C) 2018 Champs-Libres <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PostalCodeRepository extends \Doctrine\ORM\EntityRepository
use Chill\MainBundle\Entity\PostalCode;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class PostalCodeRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(PostalCode::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?PostalCode
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?PostalCode
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return PostalCode[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return PostalCode[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return PostalCode::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\RoleScope;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class RoleScopeRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(RoleScope::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?RoleScope
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?RoleScope
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return RoleScope[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return RoleScope[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return RoleScope::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\Scope;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\Persistence\ObjectRepository;
final class ScopeRepository implements ObjectRepository
{
private EntityRepository $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Scope::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?Scope
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?Scope
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return Scope[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return Scope[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return Scope::class;
}
}

View File

@@ -1,121 +1,148 @@
<?php
/*
* Copyright (C) 2018 Julien Fastré <julien.fastre@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Repository;
use Chill\MainBundle\Entity\GroupCenter;
use Chill\MainBundle\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ObjectRepository;
/**
*
*
*/
class UserRepository extends \Doctrine\ORM\EntityRepository
final class UserRepository implements ObjectRepository
{
public function countByUsernameOrEmail($pattern)
private EntityRepository $repository;
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
$this->repository = $entityManager->getRepository(User::class);
}
public function find($id, $lockMode = null, $lockVersion = null): ?User
{
return $this->repository->find($id, $lockMode, $lockVersion);
}
public function findOneBy(array $criteria, array $orderBy = null): ?User
{
return $this->repository->findOneBy($criteria, $orderBy);
}
/**
* @return User[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @return User[]
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function getClassName() {
return User::class;
}
public function countByUsernameOrEmail(string $pattern): int
{
$qb = $this->queryByUsernameOrEmail($pattern);
$qb->select('COUNT(u)');
return (int) $qb->getQuery()->getSingleScalarResult();
}
public function findByUsernameOrEmail($pattern)
public function findByUsernameOrEmail(string $pattern)
{
$qb = $this->queryByUsernameOrEmail($pattern);
return $qb->getQuery()->getResult();
}
public function findOneByUsernameOrEmail($pattern)
public function findOneByUsernameOrEmail(string $pattern)
{
$qb = $this->queryByUsernameOrEmail($pattern);
return $qb->getQuery()->getSingleResult();
}
/**
* Get the users having a specific flags
*
* If provided, only the users amongst "filtered users" are searched. This
* allows to make a first search amongst users based on role and center
*
* If provided, only the users amongst "filtered users" are searched. This
* allows to make a first search amongst users based on role and center
* and, then filter those users having some flags.
*
*
* @param \Chill\MainBundle\Entity\User[] $amongstUsers
*/
public function findUsersHavingFlags($flag, $amongstUsers = [])
public function findUsersHavingFlags($flag, array $amongstUsers = []): array
{
$gcs = $this->_em->createQuery("SELECT DISTINCT gc "
. "FROM ".GroupCenter::class." gc "
. "JOIN gc.permissionsGroup pg "
. "WHERE "
. "JSONB_EXISTS_IN_ARRAY(pg.flags, :flag) = :true ")
$gcs = $this
->entityManager
->createQuery(
"SELECT DISTINCT gc " .
"FROM ".GroupCenter::class." gc " .
"JOIN gc.permissionsGroup pg " .
"WHERE " .
"JSONB_EXISTS_IN_ARRAY(pg.flags, :flag) = :true "
)
->setParameters([
'true' => true,
'flag' => $flag
])
->getResult();
if (count($gcs) === 0) {
return [];
}
$qb = $this->_em->createQueryBuilder();
$qb = $this->entityManager->createQueryBuilder();
$qb
->select('DISTINCT u')
->from(User::class, 'u')
->where("u.enabled = 'TRUE'")
;
->where("u.enabled = 'TRUE'");
$orx = $qb->expr()->orX();
foreach($gcs as $i => $gc) {
$orx->add(':gc_'.$i.' MEMBER OF u.groupCenters');
$qb->setParameter('gc_'.$i, $gc);
$orx->add(':gc_' . $i . ' MEMBER OF u.groupCenters');
$qb->setParameter('gc_' . $i, $gc);
}
$qb->andWhere($orx);
if (count($amongstUsers) > 0) {
if ($amongstUsers !== []) {
$qb
->andWhere($qb->expr()->in('u', ':amongstUsers'))
->setParameter('amongstUsers', $amongstUsers)
;
->setParameter('amongstUsers', $amongstUsers);
}
return $qb->getQuery()->getResult();
}
protected function queryByUsernameOrEmail($pattern)
protected function queryByUsernameOrEmail(string $pattern): QueryBuilder
{
$qb = $this->createQueryBuilder('u');
$qb = $this->entityManager->createQueryBuilder('u');
$searchByPattern = $qb->expr()->orX();
$searchByPattern
->add($qb->expr()->eq('u.usernameCanonical', 'LOWER(UNACCENT(:pattern))'))
->add($qb->expr()->eq('u.emailCanonical', 'LOWER(UNACCENT(:pattern))'))
;
->add($qb->expr()->eq('u.emailCanonical', 'LOWER(UNACCENT(:pattern))'));
$qb
->where($searchByPattern)
->setParameter('pattern', $pattern)
;
->setParameter('pattern', $pattern);
return $qb;
}
}

View File

@@ -252,6 +252,9 @@ div.address_form {
display: flex;
flex-direction: column;
flex-grow: 1;
div.custom-address, div.custom-postcode {
padding: 12px;
}
}
div.address_form__select__map {
@@ -259,13 +262,20 @@ div.address_form {
div#address_map {
height:400px;
width:400px;
input {
border: 1px solid #999;
}
}
}
}
div.address_form__more {
& > div {
display: flex;
& > label {
width: 30%;
}
}
}
}

View File

@@ -1,33 +1,73 @@
<template>
<div v-if="address.address">
{{ address.address.street }}, {{ address.address.streetNumber }}
<div class='person__address__create'>
<div>
<h2 v-if="!edit">{{ $t('create_a_new_address') }}</h2>
<h2 v-else>{{ $t('edit_a_new_address') }}</h2>
<add-address
@addNewAddress="addNewAddress">
</add-address>
</div>
<div>
<show-address
v-if="address"
v-bind:address="address">
</show-address>
</div>
</div>
<div v-if="address.city">
{{ address.city.code }} {{ address.city.name }}
</div>
<div v-if="address.country">
{{ address.country.name }}
<div v-if="!edit" class='person__address__valid'>
<h2>{{ $t('date') }}</h2>
<input
type="date"
name="validFrom"
:placeholder="$t('validFrom')"
v-model="validFrom"/>
<div v-if="errors.length > 0">
{{ errors }}
</div>
</div>
<div>
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a :href=backUrl class="sc-button bt-cancel">{{ $t('back_to_the_list') }}</a>
</li>
<li v-if="!edit">
<button type="submit" class="sc-button bt-update centered" @click="addToPerson">
{{ $t('add_an_address_to_person') }}
</button>
</li>
</ul>
</div>
<add-address
@addNewAddress="addNewAddress">
</add-address>
</template>
<script>
import { mapState } from 'vuex';
import AddAddress from '../_components/AddAddress.vue';
import ShowAddress from '../_components/ShowAddress.vue';
export default {
name: 'App',
components: {
AddAddress
AddAddress,
ShowAddress
},
data() {
return {
edit: window.mode === 'edit',
personId: window.personId,
addressId: window.addressId,
backUrl: `/fr/person/${window.personId}/address/list`, //TODO better way to pass this
validFrom: new Date().toISOString().split('T')[0]
}
},
computed: {
address() {
return this.$store.state.address;
},
errors() {
return this.$store.state.errorMsg;
}
},
methods: {
@@ -36,9 +76,9 @@ export default {
let newAddress = {
'isNoAddress': address.isNoAddress,
'street': address.selected.address.street,
'streetNumber': address.selected.address.streetNumber,
'postcode': {'id': address.selected.city.id },
'street': address.isNoAddress ? '' : address.street,
'streetNumber': address.isNoAddress ? '' : address.streetNumber,
'postcode': {'id': address.selected.city.id},
'floor': address.floor,
'corridor': address.corridor,
'steps': address.steps,
@@ -49,12 +89,47 @@ export default {
};
if (address.selected.address.point !== undefined){
newAddress = Object.assign(newAddress, {'point': address.selected.address.point.coordinates});
newAddress = Object.assign(newAddress, {
'point': address.selected.address.point.coordinates
});
}
if (address.writeNewPostalCode){
let newPostalCode = address.newPostalCode;
newPostalCode = Object.assign(newPostalCode, {
'country': {'id': address.selected.country.id },
});
newAddress = Object.assign(newAddress, {
'newPostalCode': newPostalCode
});
}
if (this.edit){
this.$store.dispatch('updateAddress', {
addressId: this.addressId,
newAddress: newAddress
});
} else {
this.$store.dispatch('addAddress', newAddress);
}
this.$store.dispatch('addAddress', newAddress);
modal.showModal = false;
},
addToPerson() {
this.$store.dispatch('addDateToAddressAndAddressToPerson', {
personId: this.personId,
addressId: this.$store.state.address.address_id,
body: { validFrom: {datetime: `${this.validFrom}T00:00:00+0100`}}
})
},
getEditAddress() {
this.$store.dispatch('getEditAddress', this.addressId);
}
}
},
mounted() {
if (this.edit) {
this.getEditAddress();
}
},
};
</script>

View File

@@ -1,20 +1,32 @@
const addressMessages = {
fr: {
add_an_address_title: 'Ajouter une adresse',
add_an_address_title: 'Créer une adresse',
edit_an_address_title: 'Modifier une adresse',
create_a_new_address: 'Créer une nouvelle adresse',
edit_a_new_address: 'Modifier l\'adresse',
select_an_address_title: 'Sélectionner une adresse',
fill_an_address: 'Compléter l\'adresse',
select_country: 'Choisir le pays',
select_city: 'Choisir une localité',
select_address: 'Choisir une adresse',
create_address: 'Appuyer sur "Entrée" pour créer une nouvelle adresse',
create_address: 'Adresse inconnue. Cliquez ici pour créer une nouvelle adresse',
isNoAddress: 'Pas d\'adresse complète',
street: 'Nom de rue',
streetNumber: 'Numéro',
floor: 'Étage',
corridor: 'Couloir',
steps: 'Escalier',
flat: 'Appartement',
buildingName: 'Nom du batiment',
extra: 'Complément d\'adresse',
distribution: 'Service particulier de distribution'
distribution: 'Service particulier de distribution',
create_postal_code: 'Localité inconnue. Cliquez ici pour créer une nouvelle localité',
postalCode_name: 'Nom de la localité',
postalCode_code: 'Code postal de la localité',
date: 'Date de la nouvelle adresse',
add_an_address_to_person: 'Ajouter l\'adresse à la personne',
validFrom: 'Date de la nouvelle adresse',
back_to_the_list: 'Retour à la liste'
}
};

View File

@@ -1,7 +1,7 @@
import 'es6-promise/auto';
import { createStore } from 'vuex';
import { postAddress } from '../../_api/AddAddress'
import { patchAddress, postAddress, postPostalCode, postAddressToPerson, getAddress } from '../../_api/AddAddress'
const debug = process.env.NODE_ENV !== 'production';
@@ -9,6 +9,8 @@ const store = createStore({
strict: debug,
state: {
address: {},
editAddress: {}, //TODO or should be address?
person: {},
errorMsg: []
},
getters: {
@@ -20,25 +22,119 @@ const store = createStore({
addAddress(state, address) {
console.log('@M addAddress address', address);
state.address = address;
}
},
updateAddress(state, address) {
console.log('@M updateAddress address', address);
state.address = address;
},
addAddressToPerson(state, person) {
console.log('@M addAddressToPerson person', person);
state.person = person;
},
addDateToAddress(state, validFrom) {
console.log('@M addDateToAddress address.validFrom', validFrom);
state.validFrom = validFrom;
},
getEditAddress(state, address) {
console.log('@M getEditAddress address', address);
state.editAddress = address;
},
},
actions: {
addAddress({ commit }, payload) {
console.log('@A addAddress payload', payload);
//commit('addAddress', payload); // à remplacer par la suite
//fetch POST qui envoie l'adresse, et récupère la confirmation que c'est ok.
//La confirmation est l'adresse elle-même.
if('newPostalCode' in payload){
let postalCodeBody = payload.newPostalCode;
postalCodeBody = Object.assign(postalCodeBody, {'origin': 3});
postPostalCode(postalCodeBody)
.then(postalCode => {
let body = payload;
body.postcode = {'id': postalCode.id},
postAddress(body)
.then(address => new Promise((resolve, reject) => {
commit('addAddress', address);
resolve();
}))
.catch((error) => {
commit('catchError', error);
});
})
postAddress(payload)
} else {
postAddress(payload)
.then(address => new Promise((resolve, reject) => {
commit('addAddress', address);
resolve();
}))
.catch((error) => {
commit('catchError', error);
});
}
},
addDateToAddressAndAddressToPerson({ commit }, payload) {
console.log('@A addDateToAddressAndAddressToPerson payload', payload);
patchAddress(payload.addressId, payload.body)
.then(address => new Promise((resolve, reject) => {
commit('addAddress', address);
commit('addDateToAddress', address.validFrom);
resolve();
}))
}).then(
postAddressToPerson(payload.personId, payload.addressId)
.then(person => new Promise((resolve, reject) => {
commit('addAddressToPerson', person);
resolve();
}))
.catch((error) => {
commit('catchError', error);
})
))
.catch((error) => {
commit('catchError', error);
});
}
},
updateAddress({ commit }, payload) {
console.log('@A updateAddress payload', payload);
if('newPostalCode' in payload.newAddress){ // TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode
let postalCodeBody = payload.newAddress.newPostalCode;
postalCodeBody = Object.assign(postalCodeBody, {'origin': 3});
postPostalCode(postalCodeBody)
.then(postalCode => {
let body = payload.newAddress;
body.postcode = {'id': postalCode.id },
patchAddress(payload.addressId, body)
.then(address => new Promise((resolve, reject) => {
commit('updateAddress', address);
resolve();
}))
.catch((error) => {
commit('catchError', error);
});
})
} else {
patchAddress(payload.addressId, payload.newAddress)
.then(address => new Promise((resolve, reject) => {
commit('updateAddress', address);
resolve();
}))
.catch((error) => {
commit('catchError', error);
});
}
},
getEditAddress({ commit }, payload) {
console.log('@A getEditAddress payload', payload);
getAddress(payload).then(address => new Promise((resolve, reject) => {
commit('getEditAddress', address);
resolve();
}))
.catch((error) => {
commit('catchError', error);
});
},
}
});

View File

@@ -36,7 +36,6 @@ const fetchCities = (country) => {
*/
const fetchReferenceAddresses = (postalCode) => {
console.log('<<< fetching references addresses for', postalCode);
//TODO deal with huge number of addresses... we should do suggestion...
const url = `/api/1.0/main/address-reference.json?item_per_page=1000&postal_code=${postalCode.id}`;
return fetch(url)
.then(response => {
@@ -45,16 +44,75 @@ const fetchReferenceAddresses = (postalCode) => {
});
};
/*
* Endpoint chill_api_single_address_reference__index
* method GET, get AddressReference Object
* @returns {Promise} a promise containing all AddressReference objects filtered with postal code
*/
const fetchAddresses = () => {
console.log('<<< fetching addresses');
//TODO deal with huge number of addresses... we should do suggestion...
const url = `/api/1.0/main/address.json?item_per_page=1000`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
/*
* Endpoint chill_api_single_address__entity__create
* method POST, post Address Object
* @returns {Promise}
*/
const postAddress = (address) => {
console.log(address);
const url = `/api/1.0/main/address.json?`;
const body = address;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(body)
}).then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
/*
* Endpoint chill_api_single_address__entity__create
* method PATCH, patch Address Instance
*
* @id integer - id of address
* @body Object - dictionary with changes to post
*/
const patchAddress = (id, body) => {
const url = `/api/1.0/main/address/${id}.json`;
return fetch(url, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
/*
* Endpoint chill_api_single_postal_code__entity_create
* method POST, post Postal Code Object
* @returns {Promise}
*/
const postPostalCode = (postalCode) => {
const url = `/api/1.0/main/postal-code.json?`;
const body = postalCode;
return fetch(url, {
method: 'POST',
headers: {
@@ -67,9 +125,55 @@ const postAddress = (address) => {
});
};
/*
* Endpoint chill_api_single_person_address
* method POST, post Person instance
*
* @id integer - id of Person
* @body Object - dictionary with changes to post
*/
const postAddressToPerson = (personId, addressId) => {
console.log(personId);
console.log(addressId);
const body = {
'id': addressId
};
const url = `/api/1.0/person/person/${personId}/address.json`
return fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
/*
* Endpoint chill_api_single_address__index
* method GET, get Address Object
* @params {id} the address id
* @returns {Promise} a promise containing a Address object
*/
const getAddress = (id) => {
console.log('<<< get address');
const url = `/api/1.0/main/address/${id}.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
};
export {
fetchCountries,
fetchCities,
fetchReferenceAddresses,
postAddress
fetchAddresses,
postAddress,
patchAddress,
postPostalCode,
postAddressToPerson,
getAddress
};

View File

@@ -1,7 +1,10 @@
<template>
<button class="sc-button bt-create centered mt-4" @click="openModal">
<button v-if="!edit" class="sc-button bt-create mt-4" @click="openModal">
{{ $t('add_an_address_title') }}
</button>
<button v-else class="sc-button bt-create mt-4" @click="openModal">
{{ $t('edit_an_address_title') }}
</button>
<teleport to="body">
<modal v-if="modal.showModal"
@@ -9,7 +12,8 @@
@close="modal.showModal = false">
<template v-slot:header>
<h3 class="modal-title">{{ $t('add_an_address_title') }}</h3>
<h3 v-if="!edit" class="modal-title">{{ $t('add_an_address_title') }}</h3>
<h3 v-if="edit" class="modal-title">{{ $t('edit_an_address_title') }}</h3>
</template>
<template v-slot:body>
@@ -42,6 +46,7 @@
</city-selection>
<address-selection
v-if="!isNoAddress"
v-bind:address="address"
v-bind:updateMapCenter="updateMapCenter">
</address-selection>
@@ -100,11 +105,14 @@ export default {
emits: ['addNewAddress'],
data() {
return {
edit: window.mode === 'edit',
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl"
},
address: {
writeNewAddress: false,
writeNewPostalCode: false,
loaded: {
countries: [],
cities: [],
@@ -115,11 +123,17 @@ export default {
city: {},
address: {},
},
newPostalCode: {
code: null,
name: null
},
addressMap: {
center : [48.8589, 2.3469], // Note: LeafletJs demands [lat, lon] cfr https://macwright.com/lonlat/
zoom: 12
},
isNoAddress: false,
street: null,
streetNumber: null,
floor: null,
corridor: null,
steps: null,
@@ -167,8 +181,8 @@ export default {
getCities(country) {
console.log('getCities for', country.name);
fetchCities(country).then(cities => new Promise((resolve, reject) => {
this.address.loaded.cities = cities.results;
resolve()
this.address.loaded.cities = cities.results.filter(c => c.origin !== 3); // filter out user-defined cities
resolve();
}))
.catch((error) => {
this.errorMsg.push(error.message);
@@ -198,6 +212,23 @@ export default {
this.address.loaded.cities = [];
this.address.selected.city = {};
this.address.selected.country = {};
this.address.isNoAddress = this.edit ? this.$store.state.editAddress.isNoAddress: false;;
this.address.street = this.edit ? this.$store.state.editAddress.street: null;
this.address.streetNumber = this.edit ? this.$store.state.editAddress.streetNumber: null;
this.address.floor = this.edit ? this.$store.state.editAddress.floor: null;
this.address.corridor = this.edit ? this.$store.state.editAddress.corridor: null;
this.address.steps = this.edit ? this.$store.state.editAddress.steps: null;
this.address.flat = this.edit ? this.$store.state.editAddress.flat: null;
this.address.buildingName = this.edit ? this.$store.state.editAddress.buildingName: null;
this.address.distribution = this.edit ? this.$store.state.editAddress.distribution: null;
this.address.extra = this.edit ? this.$store.state.editAddress.extra: null;
this.address.writeNewAddress = this.edit;
this.address.writeNewPostalCode = this.edit;
this.address.newPostalCode = this.edit ?
{
code: this.$store.state.editAddress.postcode !== undefined ? this.$store.state.editAddress.postcode.code : null,
name: this.$store.state.editAddress.postcode !== undefined ? this.$store.state.editAddress.postcode.name : null
} : {};
console.log('cities and addresses', this.address.loaded.cities, this.address.loaded.addresses);
}
}

View File

@@ -40,7 +40,7 @@ export default {
update() {
console.log('update map with : ', this.address.addressMap.center)
marker.setLatLng(this.address.addressMap.center);
map.setView(this.address.addressMap.center, 12);
map.setView(this.address.addressMap.center, 15);
}
},
mounted(){

View File

@@ -1,37 +1,56 @@
<template>
<h4>{{ $t('fill_an_address') }}</h4>
<div>
<h4>{{ $t('fill_an_address') }}</h4>
<input
<label for="floor">{{ $t('floor') }}</label>
<input
type="text"
name="floor"
:placeholder="$t('floor')"
v-model="floor"/>
<input
</div>
<div>
<label for="corridor">{{ $t('corridor') }}</label>
<input
type="text"
name="corridor"
:placeholder="$t('corridor')"
v-model="corridor"/>
<input
</div>
<div>
<label for="steps">{{ $t('steps') }}</label>
<input
type="text"
name="steps"
:placeholder="$t('steps')"
v-model="steps"/>
<input
</div>
<div>
<label for="flat">{{ $t('flat') }}</label>
<input
type="text"
name="flat"
:placeholder="$t('flat')"
v-model="flat"/>
<input
</div>
<div>
<label for="buildingName">{{ $t('buildingName') }}</label>
<input
type="text"
name="buildingName"
:placeholder="$t('buildingName')"
v-model="buildingName"/>
<input
</div>
<div>
<label for="extra">{{ $t('extra') }}</label>
<input
type="text"
name="extra"
:placeholder="$t('extra')"
v-model="extra"/>
<input
</div>
<div>
<label for="distribution">{{ $t('distribution') }}</label>
<input
type="text"
name="distribution"
:placeholder="$t('distribution')"

View File

@@ -15,6 +15,18 @@
:options="addresses">
</VueMultiselect>
</div>
<div class="custom-address" v-if="writeNewAddress || writeNewPostalCode">
<input
type="text"
name="street"
:placeholder="$t('street')"
v-model="street"/>
<input
type="text"
name="streetNumber"
:placeholder="$t('streetNumber')"
v-model="streetNumber"/>
</div>
</template>
<script>
@@ -30,9 +42,31 @@ export default {
}
},
computed: {
writeNewAddress() {
return this.address.writeNewAddress;
},
writeNewPostalCode() {
return this.address.writeNewPostalCode;
},
addresses() {
return this.address.loaded.addresses;
}
},
street: {
set(value) {
this.address.street = value;
},
get() {
return this.address.street;
}
},
streetNumber: {
set(value) {
this.address.streetNumber = value;
},
get() {
return this.address.streetNumber;
}
},
},
methods: {
transName(value) {
@@ -40,14 +74,12 @@ export default {
},
selectAddress(value) {
this.address.selected.address = value;
this.address.street = value.street;
this.address.streetNumber = value.streetNumber;
this.updateMapCenter(value.point);
},
addAddress (newAddress) {
const address = {
street: newAddress
};
this.value = address;
this.address.selected.address = address;
addAddress() {
this.address.writeNewAddress = true;
}
}
};

View File

@@ -8,9 +8,25 @@
label="value"
:custom-label="transName"
:placeholder="$t('select_city')"
:taggable="true"
:multiple="false"
@tag="addPostalCode"
:tagPlaceholder="$t('create_postal_code')"
:options="cities">
</VueMultiselect>
</div>
<div class="custom-postcode" v-if="writeNewPostalCode">
<input
type="text"
name="name"
:placeholder="$t('postalCode_name')"
v-model="name"/>
<input
type="text"
name="code"
:placeholder="$t('postalCode_code')"
v-model="code"/>
</div>
</template>
<script>
@@ -25,18 +41,42 @@ export default {
value: null
}
},
computed: {
writeNewPostalCode() {
return this.address.writeNewPostalCode;
},
cities() {
return this.address.loaded.cities;
},
name: {
set(value) {
this.address.newPostalCode.name = value;
},
get() {
return this.address.newPostalCode.name;
}
},
code: {
set(value) {
this.address.newPostalCode.code= value;
},
get() {
return this.address.newPostalCode.code;
}
},
},
methods: {
transName(value) {
return `${value.code}-${value.name}`
},
selectCity(value) {
this.address.selected.city = value;
this.address.newPostalCode.name = value.name;
this.address.newPostalCode.code = value.code;
this.getReferenceAddresses(value);
},
},
computed: {
cities() {
return this.address.loaded.cities;
addPostalCode() {
this.address.writeNewPostalCode = true;
}
}
};

View File

@@ -22,13 +22,18 @@ export default {
props: ['address', 'getCities'],
data() {
return {
value: this.address.loaded.countries.filter(c => c.countryCode === 'FR')[0]
edit: window.mode === 'edit',
defaultCountry: this.edit ? this.$store.state.editAddress.country.code : 'FR',
value: this.address.loaded.countries.filter(c => c.countryCode === this.defaultCountry)[0]
}
},
methods: {
init() {
this.value = this.edit ?
this.address.loaded.countries.filter(c => c.countryCode === this.$store.state.editAddress.country.code)[0]:
this.address.loaded.countries.filter(c => c.countryCode === 'FR')[0]
if (this.value !== undefined) {
this.getCities(this.value);
this.selectCountry(this.value);
}
},
transName ({ name }) {

View File

@@ -0,0 +1,44 @@
<template>
<div v-if="address.text">
{{ address.text }}
</div>
<div v-if="address.postcode">
{{ address.postcode.name }}
</div>
<div v-if="address.country">
{{ address.country.name.fr }}
</div>
<div v-if="address.floor">
<span>{{ $t('floor') }}</span>: {{ address.floor }}
</div>
<div v-if="address.corridor">
<span>{{ $t('corridor') }}</span>: {{ address.corridor }}
</div>
<div v-if="address.steps">
<span>{{ $t('steps') }}</span>: {{ address.steps }}
</div>
<div v-if="address.flat">
<span>{{ $t('flat') }}</span>: {{ address.flat }}
</div>
<div v-if="address.buildingName">
<span>{{ $t('buildingName') }}</span>: {{ address.buildingName }}
</div>
<div v-if="address.extra">
<span>{{ $t('extra') }}</span>: {{ address.extra }}
</div>
<div v-if="address.distribution">
<span>{{ $t('distribution') }}</span>: {{ address.distribution }}
</div>
</template>
<script>
export default {
name: 'ShowAddress',
props: ['address'],
data() {
return {
}
},
};
</script>

View File

@@ -14,8 +14,20 @@ class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface
public function normalize($address, string $format = null, array $context = [])
{
$data['address_id'] = $address->getId();
$data['text'] = $address->getStreet().', '.$address->getBuildingName();
$data['text'] = $address->getStreet().', '.$address->getStreetNumber();
$data['street'] = $address->getStreet();
$data['streetNumber'] = $address->getStreetNumber();
$data['postcode']['name'] = $address->getPostCode()->getName();
$data['postcode']['code'] = $address->getPostCode()->getCode();
$data['country']['name'] = $address->getPostCode()->getCountry()->getName();
$data['country']['code'] = $address->getPostCode()->getCountry()->getCountryCode();
$data['floor'] = $address->getFloor();
$data['corridor'] = $address->getCorridor();
$data['steps'] = $address->getSteps();
$data['flat'] = $address->getBuildingName();
$data['buildingName'] = $address->getFlat();
$data['distribution'] = $address->getDistribution();
$data['extra'] = $address->getExtra();
return $data;
}
@@ -25,5 +37,5 @@ class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface
return $data instanceof Address;
}
}

View File

@@ -17,6 +17,93 @@ components:
type: integer
name:
type: string
Address:
type: object
properties:
address_id:
type: integer
text:
type: string
postcode:
type: object
properties:
name:
type: string
Country:
type: object
properties:
id:
type: integer
name:
type: object
countryCode:
type: string
PostalCode:
type: object
properties:
id:
type: integer
name:
type: string
code:
type: string
country:
type: object
properties:
id:
type: integer
name:
type: object
countryCode:
type: string
AddressReference:
type: object
properties:
id:
type: integer
refId:
type: string
street:
type: string
streetNumber:
type: string
postcode:
type: object
properties:
id:
type: integer
name:
type: string
code:
type: string
country:
type: object
properties:
id:
type: integer
name:
type: object
countryCode:
type: string
municipalityCode:
type: string
source:
type: string
point:
type: object
properties:
type:
type: string
coordinates:
type: array
items:
type: number
minItems: 2
maxItems: 2
paths:
/1.0/search.json:
@@ -29,7 +116,7 @@ paths:
description: >
**Warning**: This is currently a stub (not really implemented
The search is performed across multiple entities. The entities must be listed into
The search is performed across multiple entities. The entities must be listed into
`type` parameters.
The results are ordered by relevance, from the most to the lowest relevant.
@@ -55,4 +142,286 @@ paths:
responses:
200:
description: "OK"
/1.0/main/address.json:
get:
tags:
- address
summary: Return a list of all Chill addresses
responses:
200:
description: "ok"
post:
tags:
- address
summary: create a new address
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
buildingName:
type: string
corridor:
type: string
distribution:
type: string
extra:
type: string
flat:
type: string
floor:
type: string
isNoAddress:
type: boolean
point:
type: array
items:
type: number
minItems: 2
maxItems: 2
postcode:
$ref: '#/components/schemas/PostalCode'
steps:
type: string
street:
type: string
streetNumber:
type: string
responses:
401:
description: "Unauthorized"
404:
description: "Not found"
200:
description: "OK"
422:
description: "Unprocessable entity (validation errors)"
400:
description: "transition cannot be applyed"
patch:
tags:
- address
summary: patch an address
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
buildingName:
type: string
corridor:
type: string
distribution:
type: string
extra:
type: string
flat:
type: string
floor:
type: string
isNoAddress:
type: boolean
point:
type: array
items:
type: number
minItems: 2
maxItems: 2
postcode:
$ref: '#/components/schemas/PostalCode'
steps:
type: string
street:
type: string
streetNumber:
type: string
validFrom:
type: string
validTo:
type: string
responses:
401:
description: "Unauthorized"
404:
description: "Not found"
200:
description: "OK"
422:
description: "Unprocessable entity (validation errors)"
400:
description: "transition cannot be applyed"
/1.0/main/address/{id}.json:
get:
tags:
- address
summary: Return an address by id
parameters:
- name: id
in: path
required: true
description: The address id
schema:
type: integer
format: integer
minimum: 1
responses:
200:
description: "ok"
content:
application/json:
schema:
$ref: '#/components/schemas/Address'
404:
description: "not found"
401:
description: "Unauthorized"
/1.0/main/address-reference.json:
get:
tags:
- address
summary: Return a list of all reference addresses
parameters:
- in: query
name: postal_code
required: false
schema:
type: integer
description: The id of a postal code to filter the reference addresses
responses:
200:
description: "ok"
/1.0/main/address-reference/{id}.json:
get:
tags:
- address
summary: Return a reference address by id
parameters:
- name: id
in: path
required: true
description: The reference address id
schema:
type: integer
format: integer
minimum: 1
responses:
200:
description: "ok"
content:
application/json:
schema:
$ref: '#/components/schemas/AddressReference'
404:
description: "not found"
401:
description: "Unauthorized"
/1.0/main/postal-code.json:
get:
tags:
- address
summary: Return a list of all postal-code
parameters:
- in: query
name: country
required: false
schema:
type: integer
description: The id of a country to filter the postal code
responses:
200:
description: "ok"
post:
tags:
- address
summary: create a new PostalCode
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
code:
type: string
country:
$ref: '#/components/schemas/Country'
responses:
401:
description: "Unauthorized"
404:
description: "Not found"
200:
description: "OK"
422:
description: "Unprocessable entity (validation errors)"
400:
description: "transition cannot be applyed"
/1.0/main/postal-code/{id}.json:
get:
tags:
- address
summary: Return a postal code by id
parameters:
- name: id
in: path
required: true
description: The postal code id
schema:
type: integer
format: integer
minimum: 1
responses:
200:
description: "ok"
content:
application/json:
schema:
$ref: '#/components/schemas/PostalCode'
404:
description: "not found"
401:
description: "Unauthorized"
/1.0/main/country.json:
get:
tags:
- address
summary: Return a list of all countries
responses:
200:
description: "ok"
/1.0/main/country/{id}.json:
get:
tags:
- address
summary: Return a country by id
parameters:
- name: id
in: path
required: true
description: The country id
schema:
type: integer
format: integer
minimum: 1
responses:
200:
description: "ok"
content:
application/json:
schema:
$ref: '#/components/schemas/Country'
404:
description: "not found"
401:
description: "Unauthorized"

View File

@@ -2,17 +2,33 @@ parameters:
# cl_chill_main.example.class: Chill\MainBundle\Example
services:
_defaults:
autowire: true
autoconfigure: true
Chill\MainBundle\Repository\:
resource: '../Repository/'
autowire: true
autoconfigure: true
Chill\MainBundle\Serializer\Normalizer\:
resource: '../Serializer/Normalizer'
autoconfigure: true
autowire: true
tags:
- { name: 'serializer.normalizer', priority: 64 }
Chill\MainBundle\Form\Type\:
resource: '../Form/Type'
autoconfigure: true
autowire: true
tags:
- { name: form.type }
Chill\MainBundle\Doctrine\Event\:
resource: '../Doctrine/Event/'
autowire: true
tags:
tags:
- { name: 'doctrine.event_subscriber' }
chill.main.helper.translatable_string:

View File

@@ -65,8 +65,6 @@ services:
chill.main.form.choice_loader.postal_code:
class: Chill\MainBundle\Form\ChoiceLoader\PostalCodeChoiceLoader
arguments:
- '@Chill\MainBundle\Repository\PostalCodeRepository'
chill.main.form.type.export:
class: Chill\MainBundle\Form\Type\Export\ExportType
@@ -98,32 +96,10 @@ services:
arguments:
- '@Chill\MainBundle\Export\ExportManager'
chill.main.form.date_type:
class: Chill\MainBundle\Form\Type\ChillDateType
tags:
- { name: form.type }
chill.main.form.pick_user_type:
class: Chill\MainBundle\Form\Type\UserPickerType
arguments:
- "@chill.main.security.authorization.helper"
- "@security.token_storage"
- "@chill.main.user_repository"
tags:
- { name: form.type }
chill.main.form.pick_scope_type:
class: Chill\MainBundle\Form\Type\ScopePickerType
arguments:
- "@chill.main.security.authorization.helper"
- "@security.token_storage"
- "@chill.main.scope_repository"
- "@chill.main.helper.translatable_string"
tags:
- { name: form.type }
chill.main.form.advanced_search_type:
class: Chill\MainBundle\Form\AdvancedSearchType
autowire: true
autoconfigure: true
arguments:
- "@chill_main.search_provider"
tags:

View File

@@ -1,35 +0,0 @@
services:
chill.main.countries_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\Country"
chill.main.user_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\User"
chill.main.scope_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\Scope"
chill.main.postalcode_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\PostalCode"
Chill\MainBundle\Repository\PostalCodeRepository: '@chill.main.postalcode_repository'
chill.main.center_repository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- "Chill\\MainBundle\\Entity\\Center"
Chill\MainBundle\Repository\CenterRepository: '@chill.main.center_repository'

View File

@@ -32,9 +32,8 @@ services:
- { name: twig.extension }
Chill\MainBundle\Templating\Entity\CommentRender:
arguments:
- '@chill.main.user_repository'
- '@Symfony\Component\Templating\EngineInterface'
autoconfigure: true
autowire: true
tags:
- { name: 'chill.render_entity' }

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add table for ChillMain/Notification
*/
final class Version20210610140248 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add table for ChillMain/Notification';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE chill_main_notification_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE chill_main_notification (id INT NOT NULL, sender_id INT NOT NULL, message TEXT NOT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, relatedEntityClass VARCHAR(255) NOT NULL, relatedEntityId INT NOT NULL, read JSONB NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_5BDC8067F624B39D ON chill_main_notification (sender_id)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_5BDC8067567988B4440F6072 ON chill_main_notification (relatedEntityClass, relatedEntityId)');
$this->addSql('COMMENT ON COLUMN chill_main_notification.date IS \'(DC2Type:datetime_immutable)\'');
$this->addSql('CREATE TABLE chill_main_notification_addresses_user (notification_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(notification_id, user_id))');
$this->addSql('CREATE INDEX IDX_E52C5D2BEF1A9D84 ON chill_main_notification_addresses_user (notification_id)');
$this->addSql('CREATE INDEX IDX_E52C5D2BA76ED395 ON chill_main_notification_addresses_user (user_id)');
$this->addSql('ALTER TABLE chill_main_notification ADD CONSTRAINT FK_5BDC8067F624B39D FOREIGN KEY (sender_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_main_notification_addresses_user ADD CONSTRAINT FK_E52C5D2BEF1A9D84 FOREIGN KEY (notification_id) REFERENCES chill_main_notification (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_main_notification_addresses_user ADD CONSTRAINT FK_E52C5D2BA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_notification_addresses_user DROP CONSTRAINT FK_E52C5D2BEF1A9D84');
$this->addSql('DROP SEQUENCE chill_main_notification_id_seq CASCADE');
$this->addSql('DROP TABLE chill_main_notification');
$this->addSql('DROP TABLE chill_main_notification_addresses_user');
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210616134328 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_postal_code ADD origin INT DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_postal_code DROP origin');
}
}