mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 13:24:25 +00:00
Merge branch 'track-address-reference-update' into 'master'
Feature: Track address reference update See merge request Chill-Projet/chill-bundles!500
This commit is contained in:
commit
796608b399
@ -41,6 +41,7 @@
|
|||||||
"@fullcalendar/timegrid": "^6.1.4",
|
"@fullcalendar/timegrid": "^6.1.4",
|
||||||
"@fullcalendar/vue3": "^6.1.4",
|
"@fullcalendar/vue3": "^6.1.4",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
|
"@types/leaflet": "^1.9.3",
|
||||||
"dropzone": "^5.7.6",
|
"dropzone": "^5.7.6",
|
||||||
"es6-promise": "^4.2.8",
|
"es6-promise": "^4.2.8",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
class AddressToReferenceMatcherController
|
||||||
|
{
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private SerializerInterface $serializer;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Security $security,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
SerializerInterface $serializer
|
||||||
|
) {
|
||||||
|
$this->security = $security;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->serializer = $serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/set/reviewed", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function markAddressAsReviewed(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_REVIEWED);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an address back to "to review". Only if the address is in "reviewed" state.
|
||||||
|
*
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/set/to_review", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function markAddressAsToReview(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Address::ADDR_REFERENCE_STATUS_REVIEWED !== $address->getRefStatus()) {
|
||||||
|
throw new AccessDeniedHttpException("forbidden to mark a matching address to 'to review'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/sync-with-reference", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function syncAddressWithReference(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (null === $address->getAddressReference()) {
|
||||||
|
throw new BadRequestHttpException('this address does not have any address reference');
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->syncWithReference($address->getAddressReference());
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
|
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Serializer\Model\Collection;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
class GeographicalUnitByAddressApiController
|
||||||
|
{
|
||||||
|
private PaginatorFactory $paginatorFactory;
|
||||||
|
|
||||||
|
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
|
||||||
|
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
private SerializerInterface $serializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PaginatorFactory $paginatorFactory
|
||||||
|
* @param GeographicalUnitRepositoryInterface $geographicalUnitRepository
|
||||||
|
* @param Security $security
|
||||||
|
* @param SerializerInterface $serializer
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
PaginatorFactory $paginatorFactory,
|
||||||
|
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
|
||||||
|
Security $security,
|
||||||
|
SerializerInterface $serializer
|
||||||
|
) {
|
||||||
|
$this->paginatorFactory = $paginatorFactory;
|
||||||
|
$this->geographicalUnitRepository = $geographicalUnitRepository;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->serializer = $serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/geographical-unit/by-address/{id}.{_format}", requirements={"_format": "json"})
|
||||||
|
*/
|
||||||
|
public function getGeographicalUnitCoveringAddress(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $this->geographicalUnitRepository->countGeographicalUnitContainingAddress($address);
|
||||||
|
$pagination = $this->paginatorFactory->create($count);
|
||||||
|
$units = $this->geographicalUnitRepository->findGeographicalUnitContainingAddress($address, $pagination->getCurrentPageFirstItemNumber(), $pagination->getItemsPerPage());
|
||||||
|
|
||||||
|
$collection = new Collection($units, $pagination);
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($collection, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -46,6 +46,7 @@ use Chill\MainBundle\Doctrine\Type\NativeDateIntervalType;
|
|||||||
use Chill\MainBundle\Doctrine\Type\PointType;
|
use Chill\MainBundle\Doctrine\Type\PointType;
|
||||||
use Chill\MainBundle\Entity\Civility;
|
use Chill\MainBundle\Entity\Civility;
|
||||||
use Chill\MainBundle\Entity\Country;
|
use Chill\MainBundle\Entity\Country;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||||
use Chill\MainBundle\Entity\Language;
|
use Chill\MainBundle\Entity\Language;
|
||||||
use Chill\MainBundle\Entity\Location;
|
use Chill\MainBundle\Entity\Location;
|
||||||
use Chill\MainBundle\Entity\LocationType;
|
use Chill\MainBundle\Entity\LocationType;
|
||||||
@ -732,6 +733,20 @@ class ChillMainExtension extends Extension implements
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'class' => GeographicalUnitLayer::class,
|
||||||
|
'name' => 'geographical-unit-layer',
|
||||||
|
'base_path' => '/api/1.0/main/geographical-unit-layer',
|
||||||
|
'base_role' => 'ROLE_USER',
|
||||||
|
'actions' => [
|
||||||
|
'_index' => [
|
||||||
|
'methods' => [
|
||||||
|
Request::METHOD_GET => true,
|
||||||
|
Request::METHOD_HEAD => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,10 @@ declare(strict_types=1);
|
|||||||
namespace Chill\MainBundle\Entity;
|
namespace Chill\MainBundle\Entity;
|
||||||
|
|
||||||
use Chill\MainBundle\Doctrine\Model\Point;
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
@ -28,8 +32,28 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||||||
* @ORM\Table(name="chill_main_address")
|
* @ORM\Table(name="chill_main_address")
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
class Address
|
class Address implements TrackCreationInterface, TrackUpdateInterface
|
||||||
{
|
{
|
||||||
|
use TrackCreationTrait;
|
||||||
|
use TrackUpdateTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does match with the AddressReference
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_MATCH = 'match';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does not match with the AddressReference, and
|
||||||
|
* is pending for a review
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_TO_REVIEW = 'to_review';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does not match with the AddressReference, but
|
||||||
|
* is reviewed
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_REVIEWED = 'reviewed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=AddressReference::class)
|
* @ORM\ManyToOne(targetEntity=AddressReference::class)
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
@ -37,67 +61,48 @@ class Address
|
|||||||
private ?AddressReference $addressReference = null;
|
private ?AddressReference $addressReference = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $buildingName;
|
private string $buildingName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean", options={"default": false})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private bool $confidential = false;
|
private bool $confidential = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $corridor;
|
private string $corridor = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of metadata, added by customizable fields.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $customs = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null
|
|
||||||
*
|
|
||||||
* used for the CEDEX information
|
* used for the CEDEX information
|
||||||
*
|
*
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $distribution;
|
private string $distribution = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $extra;
|
private string $extra = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $flat;
|
private string $flat = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $floor;
|
private string $floor = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of geographical units and addresses.
|
* List of geographical units and addresses.
|
||||||
@ -131,11 +136,9 @@ class Address
|
|||||||
* True if the address is a "no address", aka homeless person, ...
|
* True if the address is a "no address", aka homeless person, ...
|
||||||
*
|
*
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean", options={"default": false})
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
*/
|
||||||
private $isNoAddress = false;
|
private bool $isNoAddress = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ThirdParty reference for person's addresses that are linked to a third party.
|
* A ThirdParty reference for person's addresses that are linked to a third party.
|
||||||
@ -146,7 +149,7 @@ class Address
|
|||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||||
*/
|
*/
|
||||||
private $linkedToThirdParty;
|
private ?ThirdParty $linkedToThirdParty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A geospatial field storing the coordinates of the Address.
|
* A geospatial field storing the coordinates of the Address.
|
||||||
@ -156,7 +159,7 @@ class Address
|
|||||||
* @ORM\Column(type="point", nullable=true)
|
* @ORM\Column(type="point", nullable=true)
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $point;
|
private ?Point $point = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||||
@ -166,28 +169,36 @@ class Address
|
|||||||
private ?PostalCode $postcode = null;
|
private ?PostalCode $postcode = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @var self::ADDR_REFERENCE_STATUS_*
|
||||||
*
|
* @ORM\Column(type="text", nullable=false, options={"default": self::ADDR_REFERENCE_STATUS_MATCH})
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
|
||||||
*/
|
*/
|
||||||
private $steps;
|
private string $refStatus = self::ADDR_REFERENCE_STATUS_MATCH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @ORM\Column(type="datetime_immutable", nullable=false, options={"default": "CURRENT_TIMESTAMP"})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255)
|
|
||||||
* @Groups({"write"})
|
|
||||||
*/
|
*/
|
||||||
private $street = '';
|
private \DateTimeImmutable $refStatusLastUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
|
||||||
*
|
*
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $streetNumber = '';
|
private string $steps = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Groups({"write"})
|
||||||
|
*/
|
||||||
|
private string $street = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Groups({"write"})
|
||||||
|
*/
|
||||||
|
private string $streetNumber = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates when the address starts validation. Used to build an history
|
* Indicates when the address starts validation. Used to build an history
|
||||||
@ -210,6 +221,7 @@ class Address
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->validFrom = new DateTime();
|
$this->validFrom = new DateTime();
|
||||||
|
$this->refStatusLastUpdate = new \DateTimeImmutable('now');
|
||||||
$this->geographicalUnits = new ArrayCollection();
|
$this->geographicalUnits = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +232,6 @@ class Address
|
|||||||
->setBuildingName($original->getBuildingName())
|
->setBuildingName($original->getBuildingName())
|
||||||
->setConfidential($original->getConfidential())
|
->setConfidential($original->getConfidential())
|
||||||
->setCorridor($original->getCorridor())
|
->setCorridor($original->getCorridor())
|
||||||
->setCustoms($original->getCustoms())
|
|
||||||
->setDistribution($original->getDistribution())
|
->setDistribution($original->getDistribution())
|
||||||
->setExtra($original->getExtra())
|
->setExtra($original->getExtra())
|
||||||
->setFlat($original->getFlat())
|
->setFlat($original->getFlat())
|
||||||
@ -239,11 +250,20 @@ class Address
|
|||||||
public static function createFromAddressReference(AddressReference $original): Address
|
public static function createFromAddressReference(AddressReference $original): Address
|
||||||
{
|
{
|
||||||
return (new Address())
|
return (new Address())
|
||||||
->setPoint($original->getPoint())
|
->syncWithReference($original);
|
||||||
->setPostcode($original->getPostcode())
|
}
|
||||||
->setStreet($original->getStreet())
|
|
||||||
->setStreetNumber($original->getStreetNumber())
|
public function syncWithReference(AddressReference $addressReference): Address
|
||||||
->setAddressReference($original);
|
{
|
||||||
|
$this
|
||||||
|
->setPoint($addressReference->getPoint())
|
||||||
|
->setPostcode($addressReference->getPostcode())
|
||||||
|
->setStreet($addressReference->getStreet())
|
||||||
|
->setStreetNumber($addressReference->getStreetNumber())
|
||||||
|
->setRefStatus(self::ADDR_REFERENCE_STATUS_MATCH)
|
||||||
|
->setAddressReference($addressReference);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAddressReference(): ?AddressReference
|
public function getAddressReference(): ?AddressReference
|
||||||
@ -251,7 +271,7 @@ class Address
|
|||||||
return $this->addressReference;
|
return $this->addressReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBuildingName(): ?string
|
public function getBuildingName(): string
|
||||||
{
|
{
|
||||||
return $this->buildingName;
|
return $this->buildingName;
|
||||||
}
|
}
|
||||||
@ -261,35 +281,27 @@ class Address
|
|||||||
return $this->confidential;
|
return $this->confidential;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCorridor(): ?string
|
public function getCorridor(): string
|
||||||
{
|
{
|
||||||
return $this->corridor;
|
return $this->corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getDistribution(): string
|
||||||
* Get customs informations in the address.
|
|
||||||
*/
|
|
||||||
public function getCustoms(): array
|
|
||||||
{
|
|
||||||
return $this->customs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDistribution(): ?string
|
|
||||||
{
|
{
|
||||||
return $this->distribution;
|
return $this->distribution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtra(): ?string
|
public function getExtra(): string
|
||||||
{
|
{
|
||||||
return $this->extra;
|
return $this->extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFlat(): ?string
|
public function getFlat(): string
|
||||||
{
|
{
|
||||||
return $this->flat;
|
return $this->flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFloor(): ?string
|
public function getFloor(): string
|
||||||
{
|
{
|
||||||
return $this->floor;
|
return $this->floor;
|
||||||
}
|
}
|
||||||
@ -340,12 +352,22 @@ class Address
|
|||||||
return $this->postcode;
|
return $this->postcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSteps(): ?string
|
public function getRefStatus(): string
|
||||||
|
{
|
||||||
|
return $this->refStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRefStatusLastUpdate(): \DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->refStatusLastUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSteps(): string
|
||||||
{
|
{
|
||||||
return $this->steps;
|
return $this->steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreet(): ?string
|
public function getStreet(): string
|
||||||
{
|
{
|
||||||
return $this->street;
|
return $this->street;
|
||||||
}
|
}
|
||||||
@ -354,6 +376,7 @@ class Address
|
|||||||
* Get streetAddress1 (legacy function).
|
* Get streetAddress1 (legacy function).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getStreetAddress1()
|
public function getStreetAddress1()
|
||||||
{
|
{
|
||||||
@ -364,13 +387,14 @@ class Address
|
|||||||
* Get streetAddress2 (legacy function).
|
* Get streetAddress2 (legacy function).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getStreetAddress2()
|
public function getStreetAddress2()
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreetNumber(): ?string
|
public function getStreetNumber(): string
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
@ -378,7 +402,7 @@ class Address
|
|||||||
/**
|
/**
|
||||||
* @return DateTime
|
* @return DateTime
|
||||||
*/
|
*/
|
||||||
public function getValidFrom()
|
public function getValidFrom(): DateTime
|
||||||
{
|
{
|
||||||
return $this->validFrom;
|
return $this->validFrom;
|
||||||
}
|
}
|
||||||
@ -407,7 +431,7 @@ class Address
|
|||||||
|
|
||||||
public function setBuildingName(?string $buildingName): self
|
public function setBuildingName(?string $buildingName): self
|
||||||
{
|
{
|
||||||
$this->buildingName = $buildingName;
|
$this->buildingName = (string) $buildingName;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -421,47 +445,35 @@ class Address
|
|||||||
|
|
||||||
public function setCorridor(?string $corridor): self
|
public function setCorridor(?string $corridor): self
|
||||||
{
|
{
|
||||||
$this->corridor = $corridor;
|
$this->corridor = (string) $corridor;
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store custom informations in the address.
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setCustoms(array $customs): self
|
|
||||||
{
|
|
||||||
$this->customs = $customs;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDistribution(?string $distribution): self
|
public function setDistribution(?string $distribution): self
|
||||||
{
|
{
|
||||||
$this->distribution = $distribution;
|
$this->distribution = (string) $distribution;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setExtra(?string $extra): self
|
public function setExtra(?string $extra): self
|
||||||
{
|
{
|
||||||
$this->extra = $extra;
|
$this->extra = (string) $extra;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFlat(?string $flat): self
|
public function setFlat(?string $flat): self
|
||||||
{
|
{
|
||||||
$this->flat = $flat;
|
$this->flat = (string) $flat;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFloor(?string $floor): self
|
public function setFloor(?string $floor): self
|
||||||
{
|
{
|
||||||
$this->floor = $floor;
|
$this->floor = (string) $floor;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -508,19 +520,44 @@ class Address
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the ref status
|
||||||
|
*
|
||||||
|
* <<<<<<< HEAD
|
||||||
|
* @param Address::ADDR_REFERENCE_STATUS_* $refStatus
|
||||||
|
* @param bool|null $updateLastUpdate Also update the "refStatusLastUpdate"
|
||||||
|
* =======
|
||||||
|
* The refstatuslast update is also updated
|
||||||
|
* >>>>>>> 31152616d (Feature: Provide api endpoint for reviewing addresses)
|
||||||
|
*/
|
||||||
|
public function setRefStatus(string $refStatus, ?bool $updateLastUpdate = true): self
|
||||||
|
{
|
||||||
|
$this->refStatus = $refStatus;
|
||||||
|
|
||||||
|
if ($updateLastUpdate) {
|
||||||
|
$this->setRefStatusLastUpdate(new \DateTimeImmutable('now'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRefStatusLastUpdate(\DateTimeImmutable $refStatusLastUpdate): self
|
||||||
|
{
|
||||||
|
$this->refStatusLastUpdate = $refStatusLastUpdate;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setSteps(?string $steps): self
|
public function setSteps(?string $steps): self
|
||||||
{
|
{
|
||||||
$this->steps = $steps;
|
$this->steps = (string) $steps;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreet(?string $street): self
|
public function setStreet(?string $street): self
|
||||||
{
|
{
|
||||||
if (null === $street) {
|
$this->street = (string) $street;
|
||||||
$street = '';
|
|
||||||
}
|
|
||||||
$this->street = $street;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -531,6 +568,7 @@ class Address
|
|||||||
* @param string $streetAddress1
|
* @param string $streetAddress1
|
||||||
*
|
*
|
||||||
* @return Address
|
* @return Address
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function setStreetAddress1($streetAddress1)
|
public function setStreetAddress1($streetAddress1)
|
||||||
{
|
{
|
||||||
@ -543,7 +581,7 @@ class Address
|
|||||||
* Set streetAddress2 (legacy function).
|
* Set streetAddress2 (legacy function).
|
||||||
*
|
*
|
||||||
* @param string $streetAddress2
|
* @param string $streetAddress2
|
||||||
*
|
* @deprecated
|
||||||
* @return Address
|
* @return Address
|
||||||
*/
|
*/
|
||||||
public function setStreetAddress2($streetAddress2)
|
public function setStreetAddress2($streetAddress2)
|
||||||
@ -555,10 +593,7 @@ class Address
|
|||||||
|
|
||||||
public function setStreetNumber(?string $streetNumber): self
|
public function setStreetNumber(?string $streetNumber): self
|
||||||
{
|
{
|
||||||
if (null === $streetNumber) {
|
$this->streetNumber = (string) $streetNumber;
|
||||||
$streetNumber = '';
|
|
||||||
}
|
|
||||||
$this->streetNumber = $streetNumber;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -605,7 +640,7 @@ class Address
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($this->getStreetAddress1())) {
|
if ('' === $this->getStreet()) {
|
||||||
$context
|
$context
|
||||||
->buildViolation('address.street1-should-be-set')
|
->buildViolation('address.street1-should-be-set')
|
||||||
->atPath('streetAddress1')
|
->atPath('streetAddress1')
|
||||||
|
@ -55,13 +55,13 @@ class AddressReference
|
|||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $id;
|
private ?int $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $municipalityCode;
|
private string $municipalityCode = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A geospatial field storing the coordinates of the Address.
|
* A geospatial field storing the coordinates of the Address.
|
||||||
@ -71,7 +71,7 @@ class AddressReference
|
|||||||
* @ORM\Column(type="point")
|
* @ORM\Column(type="point")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $point;
|
private ?Point $point = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var PostalCode
|
* @var PostalCode
|
||||||
@ -79,31 +79,31 @@ class AddressReference
|
|||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $postcode;
|
private ?PostalCode $postcode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $refId;
|
private string $refId = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $source;
|
private string $source = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $street;
|
private string $street = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $streetNumber;
|
private string $streetNumber = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="datetime_immutable", nullable=true)
|
* @ORM\Column(type="datetime_immutable", nullable=true)
|
||||||
@ -126,7 +126,7 @@ class AddressReference
|
|||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMunicipalityCode(): ?string
|
public function getMunicipalityCode(): string
|
||||||
{
|
{
|
||||||
return $this->municipalityCode;
|
return $this->municipalityCode;
|
||||||
}
|
}
|
||||||
@ -141,27 +141,27 @@ class AddressReference
|
|||||||
*
|
*
|
||||||
* @return PostalCode
|
* @return PostalCode
|
||||||
*/
|
*/
|
||||||
public function getPostcode()
|
public function getPostcode(): ?PostalCode
|
||||||
{
|
{
|
||||||
return $this->postcode;
|
return $this->postcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRefId(): ?string
|
public function getRefId(): string
|
||||||
{
|
{
|
||||||
return $this->refId;
|
return $this->refId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSource(): ?string
|
public function getSource(): string
|
||||||
{
|
{
|
||||||
return $this->source;
|
return $this->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreet(): ?string
|
public function getStreet(): string
|
||||||
{
|
{
|
||||||
return $this->street;
|
return $this->street;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreetNumber(): ?string
|
public function getStreetNumber(): string
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ class AddressReference
|
|||||||
|
|
||||||
public function setMunicipalityCode(?string $municipalityCode): self
|
public function setMunicipalityCode(?string $municipalityCode): self
|
||||||
{
|
{
|
||||||
$this->municipalityCode = $municipalityCode;
|
$this->municipalityCode = (string) $municipalityCode;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -227,21 +227,21 @@ class AddressReference
|
|||||||
|
|
||||||
public function setSource(?string $source): self
|
public function setSource(?string $source): self
|
||||||
{
|
{
|
||||||
$this->source = $source;
|
$this->source = (string) $source;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreet(?string $street): self
|
public function setStreet(?string $street): self
|
||||||
{
|
{
|
||||||
$this->street = $street;
|
$this->street = (string) $street;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreetNumber(?string $streetNumber): self
|
public function setStreetNumber(?string $streetNumber): self
|
||||||
{
|
{
|
||||||
$this->streetNumber = $streetNumber;
|
$this->streetNumber = (string) $streetNumber;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Entity\GeographicalUnit;
|
namespace Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
|
|
||||||
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple GeographialUnit Data Transfer Object.
|
* Simple GeographialUnit Data Transfer Object.
|
||||||
*
|
*
|
||||||
@ -21,24 +23,28 @@ class SimpleGeographicalUnitDTO
|
|||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public int $id;
|
public int $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public int $layerId;
|
public int $layerId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public string $unitName;
|
public string $unitName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public string $unitRefId;
|
public string $unitRefId;
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ namespace Chill\MainBundle\Entity;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Table(name="chill_main_geographical_unit_layer", uniqueConstraints={
|
* @ORM\Table(name="chill_main_geographical_unit_layer", uniqueConstraints={
|
||||||
@ -27,16 +28,19 @@ class GeographicalUnitLayer
|
|||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private ?int $id = null;
|
private ?int $id = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="json", nullable=false, options={"default": "[]"})
|
* @ORM\Column(type="json", nullable=false, options={"default": "[]"})
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private array $name = [];
|
private array $name = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private string $refId = '';
|
private string $refId = '';
|
||||||
|
|
||||||
|
@ -43,11 +43,13 @@ class AddressDataMapper implements DataMapperInterface
|
|||||||
/** @var FormInterface $form */
|
/** @var FormInterface $form */
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'streetAddress1':
|
case 'streetAddress1':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$form->setData($address->getStreetAddress1());
|
$form->setData($address->getStreetAddress1());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'streetAddress2':
|
case 'streetAddress2':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$form->setData($address->getStreetAddress2());
|
$form->setData($address->getStreetAddress2());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -110,11 +112,13 @@ class AddressDataMapper implements DataMapperInterface
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$address->setStreetAddress1($form->getData());
|
$address->setStreetAddress1($form->getData());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'streetAddress2':
|
case 'streetAddress2':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$address->setStreetAddress2($form->getData());
|
$address->setStreetAddress2($form->getData());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -38,7 +38,7 @@ class RollingDateDataMapper implements DataMapperInterface
|
|||||||
$forms = iterator_to_array($forms);
|
$forms = iterator_to_array($forms);
|
||||||
|
|
||||||
$viewData = new RollingDate(
|
$viewData = new RollingDate(
|
||||||
$forms['roll']->getData(),
|
($forms['roll']->getData() ?? RollingDate::T_TODAY),
|
||||||
$forms['fixedDate']->getData()
|
$forms['fixedDate']->getData()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,20 +11,58 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Repository;
|
namespace Chill\MainBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\MainBundle\Entity\GeographicalUnit;
|
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\ORM\Query\Expr\Join;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
|
final class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $em;
|
|
||||||
|
|
||||||
private EntityRepository $repository;
|
private EntityRepository $repository;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $em)
|
public function __construct(EntityManagerInterface $em)
|
||||||
{
|
{
|
||||||
$this->repository = $em->getRepository($this->getClassName());
|
$this->repository = $em->getRepository($this->getClassName());
|
||||||
$this->em = $em;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function countGeographicalUnitContainingAddress(Address $address): int
|
||||||
|
{
|
||||||
|
$qb = $this->buildQueryGeographicalUnitContainingAddress($address);
|
||||||
|
|
||||||
|
return $qb
|
||||||
|
->select('COUNT(gu)')
|
||||||
|
->getQuery()
|
||||||
|
->getSingleScalarResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findGeographicalUnitContainingAddress(Address $address, int $offset = 0, int $limit = 50): array
|
||||||
|
{
|
||||||
|
$qb = $this->buildQueryGeographicalUnitContainingAddress($address);
|
||||||
|
|
||||||
|
return $qb
|
||||||
|
->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
|
||||||
|
->addOrderBy('IDENTITY(gu.layer)')
|
||||||
|
->addOrderBy(('gu.unitName'))
|
||||||
|
->getQuery()
|
||||||
|
->setFirstResult($offset)
|
||||||
|
->setMaxResults($limit)
|
||||||
|
->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildQueryGeographicalUnitContainingAddress(Address $address): QueryBuilder
|
||||||
|
{
|
||||||
|
$qb = $this->repository
|
||||||
|
->createQueryBuilder('gu')
|
||||||
|
;
|
||||||
|
return $qb
|
||||||
|
->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
|
||||||
|
->innerJoin(Address::class, 'address', Join::WITH, 'ST_CONTAINS(gu.geom, address.point) = TRUE')
|
||||||
|
->where($qb->expr()->eq('address', ':address'))
|
||||||
|
->setParameter('address', $address)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find($id): ?GeographicalUnit
|
public function find($id): ?GeographicalUnit
|
||||||
|
@ -11,8 +11,23 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Repository;
|
namespace Chill\MainBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO;
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
interface GeographicalUnitRepositoryInterface extends ObjectRepository
|
interface GeographicalUnitRepositoryInterface extends ObjectRepository
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Return the geographical units as @link{SimpleGeographicalUnitDTO} whithin the address is contained.
|
||||||
|
*
|
||||||
|
* This query is executed in real time (without the refresh of the materialized view which load the addresses).
|
||||||
|
*
|
||||||
|
* @param Address $address
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $limit
|
||||||
|
* @return SimpleGeographicalUnitDTO[]
|
||||||
|
*/
|
||||||
|
public function findGeographicalUnitContainingAddress(Address $address, int $offset = 0, int $limit = 50): array;
|
||||||
|
|
||||||
|
public function countGeographicalUnitContainingAddress(Address $address): int;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import {Address, GeographicalUnitLayer, SimpleGeographicalUnit} from "../../types";
|
||||||
|
import {fetchResults, makeFetch} from "./apiMethods";
|
||||||
|
|
||||||
|
export const getAddressById = async (address_id: number): Promise<Address> =>
|
||||||
|
{
|
||||||
|
const url = `/api/1.0/main/address/${address_id}.json`;
|
||||||
|
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Error('Error with request resource response');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getGeographicalUnitsByAddress = async (address: Address): Promise<SimpleGeographicalUnit[]> => {
|
||||||
|
return fetchResults<SimpleGeographicalUnit>(`/api/1.0/main/geographical-unit/by-address/${address.address_id}.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAllGeographicalUnitLayers = async (): Promise<GeographicalUnitLayer[]> => {
|
||||||
|
return fetchResults<GeographicalUnitLayer>(`/api/1.0/main/geographical-unit-layer.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const syncAddressWithReference = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/sync-with-reference`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const markAddressReviewed = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/set/reviewed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const markAddressToReview = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/set/to_review`);
|
||||||
|
}
|
@ -67,9 +67,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('for url '+url, body);
|
|
||||||
console.log('for url '+url, body !== null);
|
|
||||||
|
|
||||||
if (body !== null && typeof body !== 'undefined') {
|
if (body !== null && typeof body !== 'undefined') {
|
||||||
Object.assign(opts, {body: JSON.stringify(body)})
|
Object.assign(opts, {body: JSON.stringify(body)})
|
||||||
}
|
}
|
||||||
@ -77,9 +74,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
if (typeof options !== 'undefined') {
|
if (typeof options !== 'undefined') {
|
||||||
opts = Object.assign(opts, options);
|
opts = Object.assign(opts, options);
|
||||||
}
|
}
|
||||||
console.log('will fetch', url);
|
|
||||||
console.log('content for ' + url, opts);
|
|
||||||
|
|
||||||
return fetch(url, opts)
|
return fetch(url, opts)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
import AddressDetailsButton from "../../vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
import {createApp} from "vue";
|
||||||
|
import {createI18n} from "vue-i18n";
|
||||||
|
import {_createI18n} from "../../vuejs/_js/i18n";
|
||||||
|
import {Address} from "../../types";
|
||||||
|
|
||||||
|
const i18n = _createI18n({});
|
||||||
|
|
||||||
|
document.querySelectorAll<HTMLSpanElement>('span[data-address-details]').forEach((el) => {
|
||||||
|
const dataset = el.dataset as {
|
||||||
|
addressId: string,
|
||||||
|
addressRefStatus: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
components: {AddressDetailsButton},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addressId: Number.parseInt(dataset.addressId),
|
||||||
|
addressRefStatus: dataset.addressRefStatus,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: '<address-details-button :address_id="addressId" :address_ref_status="addressRefStatus" @update-address="onUpdateAddress"></address-details-button>',
|
||||||
|
methods: {
|
||||||
|
onUpdateAddress: (address: Address): void => {
|
||||||
|
if (address.refStatus === 'to_review' || address.refStatus === 'reviewed') {
|
||||||
|
// in this two case, the address content do not change
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (window.confirm("L'adresse a été modifiée. Vous pouvez continuer votre travail. Cependant, pour afficher les données immédiatement, veuillez recharger la page. \n\n Voulez-vous recharger la page immédiatement ?")) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(i18n);
|
||||||
|
app.mount(el);
|
||||||
|
});
|
@ -70,6 +70,8 @@ export interface Country {
|
|||||||
code: string;
|
code: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AddressRefStatus = 'match'|'to_review'|'reviewed';
|
||||||
|
|
||||||
export interface Address {
|
export interface Address {
|
||||||
type: "address";
|
type: "address";
|
||||||
address_id: number;
|
address_id: number;
|
||||||
@ -90,6 +92,13 @@ export interface Address {
|
|||||||
addressReference: AddressReference | null;
|
addressReference: AddressReference | null;
|
||||||
validFrom: DateTime;
|
validFrom: DateTime;
|
||||||
validTo: DateTime | null;
|
validTo: DateTime | null;
|
||||||
|
point: Point | null;
|
||||||
|
refStatus: AddressRefStatus;
|
||||||
|
isNoAddress: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddressWithPoint extends Address {
|
||||||
|
point: Point
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddressReference {
|
export interface AddressReference {
|
||||||
@ -106,6 +115,19 @@ export interface AddressReference {
|
|||||||
updatedAt: DateTime | null;
|
updatedAt: DateTime | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SimpleGeographicalUnit {
|
||||||
|
id: number;
|
||||||
|
layerId: number;
|
||||||
|
unitName: string;
|
||||||
|
unitRefId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GeographicalUnitLayer {
|
||||||
|
id: number;
|
||||||
|
name: TranslatableString;
|
||||||
|
refId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Location {
|
export interface Location {
|
||||||
type: "location";
|
type: "location";
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import {getAddressById} from 'ChillMainAssets/lib/api/address';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint chill_api_single_country__index
|
* Endpoint chill_api_single_country__index
|
||||||
* method GET, get Country Object
|
* method GET, get Country Object
|
||||||
@ -188,13 +190,7 @@ const postPostalCode = (postalCode) => { //<--
|
|||||||
* @returns {Promise} a promise containing a Address object
|
* @returns {Promise} a promise containing a Address object
|
||||||
*/
|
*/
|
||||||
const getAddress = (id) => {
|
const getAddress = (id) => {
|
||||||
//console.log('<< get address');
|
return getAddressById(id);
|
||||||
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 {
|
export {
|
||||||
|
@ -580,15 +580,15 @@ export default {
|
|||||||
this.entity.selected.city = this.context.edit ? this.entity.address.postcode : {};
|
this.entity.selected.city = this.context.edit ? this.entity.address.postcode : {};
|
||||||
|
|
||||||
this.entity.selected.address = {};
|
this.entity.selected.address = {};
|
||||||
this.entity.selected.address.street = this.context.edit ? this.entity.address.street: null;
|
this.entity.selected.address.street = this.context.edit ? this.entity.address.street: '';
|
||||||
this.entity.selected.address.streetNumber = this.context.edit ? this.entity.address.streetNumber: null;
|
this.entity.selected.address.streetNumber = this.context.edit ? this.entity.address.streetNumber: '';
|
||||||
this.entity.selected.address.floor = this.context.edit ? this.entity.address.floor: null;
|
this.entity.selected.address.floor = this.context.edit ? this.entity.address.floor: '';
|
||||||
this.entity.selected.address.corridor = this.context.edit ? this.entity.address.corridor: null;
|
this.entity.selected.address.corridor = this.context.edit ? this.entity.address.corridor: '';
|
||||||
this.entity.selected.address.steps = this.context.edit ? this.entity.address.steps: null;
|
this.entity.selected.address.steps = this.context.edit ? this.entity.address.steps: '';
|
||||||
this.entity.selected.address.flat = this.context.edit ? this.entity.address.flat: null;
|
this.entity.selected.address.flat = this.context.edit ? this.entity.address.flat: '';
|
||||||
this.entity.selected.address.buildingName = this.context.edit ? this.entity.address.buildingName: null;
|
this.entity.selected.address.buildingName = this.context.edit ? this.entity.address.buildingName: '';
|
||||||
this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: null;
|
this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: '';
|
||||||
this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: null;
|
this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: '';
|
||||||
|
|
||||||
this.entity.selected.writeNew.address = this.context.edit && this.entity.address.addressReference === null && this.entity.address.street.length > 0
|
this.entity.selected.writeNew.address = this.context.edit && this.entity.address.addressReference === null && this.entity.address.street.length > 0
|
||||||
this.entity.selected.writeNew.postcode = false // NB: this used to be this.context.edit, but think it was erroneous;
|
this.entity.selected.writeNew.postcode = false // NB: this used to be this.context.edit, but think it was erroneous;
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<span v-if="data.working_ref_status === 'to_review'" class="badge bg-danger address-details-button-warning">L'adresse de référence a été modifiée</span>
|
||||||
|
<a v-if="data.loading === false" @click.prevent="clickOrOpen" class="btn btn-sm btn-misc">
|
||||||
|
<span class="fa fa-map address-details-button"></span>
|
||||||
|
</a>
|
||||||
|
<span v-if="data.loading" class="fa fa-spin fa-spinner "></span>
|
||||||
|
<AddressModal :address="data.working_address" @update-address="onUpdateAddress" ref="address_modal"></AddressModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {Address, AddressRefStatus} from "../../../types";
|
||||||
|
import {onMounted, reactive, ref} from "vue";
|
||||||
|
import {getAddressById} from "../../../lib/api/address";
|
||||||
|
import AddressModal from "./AddressModal.vue";
|
||||||
|
|
||||||
|
export interface AddressModalContentProps {
|
||||||
|
address_id: number;
|
||||||
|
address_ref_status: AddressRefStatus | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = reactive<{
|
||||||
|
loading: boolean,
|
||||||
|
working_address: Address | null,
|
||||||
|
working_ref_status: AddressRefStatus | null,
|
||||||
|
}>({
|
||||||
|
loading: false,
|
||||||
|
working_address: null,
|
||||||
|
working_ref_status: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const address_modal = ref<InstanceType<typeof AddressModal> | null>(null);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
data.working_ref_status = props.address_ref_status;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function clickOrOpen(): Promise<void> {
|
||||||
|
if (data.working_address === null) {
|
||||||
|
data.loading = true;
|
||||||
|
data.working_address = await getAddressById(props.address_id);
|
||||||
|
data.working_ref_status = data.working_address.refStatus;
|
||||||
|
data.loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the modal
|
||||||
|
address_modal.value?.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
data.working_address = address;
|
||||||
|
data.working_ref_status = address.refStatus;
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.address-details-button-warning {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<address-render-box :address="props.address" :show-button-details="false"></address-render-box>
|
||||||
|
<address-details-ref-matching :address="props.address" @update-address="onUpdateAddress"></address-details-ref-matching>
|
||||||
|
<address-details-map :address="props.address"></address-details-map>
|
||||||
|
<address-details-geographical-layers :address="props.address"></address-details-geographical-layers>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {Address} from "../../../types";
|
||||||
|
import AddressDetailsMap from "./Parts/AddressDetailsMap.vue";
|
||||||
|
import AddressRenderBox from "../Entity/AddressRenderBox.vue";
|
||||||
|
import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue";
|
||||||
|
import AddressDetailsRefMatching from "./Parts/AddressDetailsRefMatching.vue";
|
||||||
|
|
||||||
|
interface AddressModalContentProps {
|
||||||
|
address: Address,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<teleport to="body">
|
||||||
|
<modal v-if="state.show_modal" @close="close">
|
||||||
|
<template v-slot:header>
|
||||||
|
<h2>Détails d'une adresse</h2>
|
||||||
|
</template>
|
||||||
|
<template v-slot:body>
|
||||||
|
<address-details-content :address="props.address" @update-address="onUpdateAddress"></address-details-content>
|
||||||
|
</template>
|
||||||
|
</modal>
|
||||||
|
</teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {reactive, ref} from "vue";
|
||||||
|
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
|
||||||
|
import {Address} from "../../../types";
|
||||||
|
import AddressDetailsContent from "./AddressDetailsContent.vue";
|
||||||
|
|
||||||
|
interface AddressModalProps {
|
||||||
|
address: Address
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddressModalState {
|
||||||
|
show_modal: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const state: AddressModalState = reactive({show_modal: false});
|
||||||
|
|
||||||
|
const open = (): void => {
|
||||||
|
state.show_modal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = (): void => {
|
||||||
|
state.show_modal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
close,
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<template v-for="container in data.containers">
|
||||||
|
<h4>{{ container.layer.name.fr }}</h4>
|
||||||
|
<ul>
|
||||||
|
<li v-for="unit in container.units">{{ unit.unitName }} ({{ unit.unitRefId }})</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {Address, GeographicalUnitLayer, SimpleGeographicalUnit} from "../../../../types";
|
||||||
|
import {getGeographicalUnitsByAddress, getAllGeographicalUnitLayers} from "../../../../lib/api/address";
|
||||||
|
import {onMounted, reactive} from "vue";
|
||||||
|
|
||||||
|
export interface AddressDetailsGeographicalLayersProp {
|
||||||
|
address: Address
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GeographicalUnitContainer {
|
||||||
|
layer: GeographicalUnitLayer;
|
||||||
|
units: SimpleGeographicalUnit[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressDetailsGeographicalLayersProp>();
|
||||||
|
|
||||||
|
const data: {
|
||||||
|
containers: GeographicalUnitContainer[]
|
||||||
|
} = reactive({
|
||||||
|
containers: []
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const [units, layers] = await Promise.all([
|
||||||
|
getGeographicalUnitsByAddress(props.address),
|
||||||
|
getAllGeographicalUnitLayers()
|
||||||
|
]) as [SimpleGeographicalUnit[], GeographicalUnitLayer[]];
|
||||||
|
|
||||||
|
for (let layer of layers) {
|
||||||
|
let us = units.filter((u) => u.layerId === layer.id);
|
||||||
|
if (us.length > 0) {
|
||||||
|
data.containers.push({
|
||||||
|
layer,
|
||||||
|
units: us
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="props.address.isNoAddress" class="alert alert-info">
|
||||||
|
Cette adresse est incomplète. La position géographique est approximative.
|
||||||
|
</div>
|
||||||
|
<div v-if="props.address.point !== null" class="address_details_map" ref="map_div"></div>
|
||||||
|
<p>Voir sur <a :href="makeUrlGoogleMap(props.address)" target="_blank">Google Maps</a> <a :href="makeUrlOsm(props.address)" target="_blank">OSM</a></p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
import markerIconPng from "leaflet/dist/images/marker-icon.png";
|
||||||
|
import L, {LatLngExpression, LatLngTuple} from "leaflet";
|
||||||
|
import {Address, Point} from "../../../../types";
|
||||||
|
|
||||||
|
const lonLatForLeaflet = (point: Point): LatLngTuple => {
|
||||||
|
return [point.coordinates[1], point.coordinates[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MapProps {
|
||||||
|
address: Address,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<MapProps>();
|
||||||
|
|
||||||
|
const map_div = ref<HTMLDivElement | null>(null)
|
||||||
|
let map: L.Map|null = null;
|
||||||
|
let marker: L.Marker|null = null;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (map_div.value === null) {
|
||||||
|
// there is no map div when the address does not have any Point
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.address.point !== null) {
|
||||||
|
map = L.map(map_div.value);
|
||||||
|
map.setView(lonLatForLeaflet(props.address.point), 18);
|
||||||
|
|
||||||
|
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
|
||||||
|
const markerIcon = L.icon({
|
||||||
|
iconUrl: markerIconPng,
|
||||||
|
iconAnchor: [12, 41],
|
||||||
|
});
|
||||||
|
|
||||||
|
marker = L.marker(lonLatForLeaflet(props.address.point), {icon: markerIcon});
|
||||||
|
marker.addTo(map);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const makeUrlGoogleMap = (address: Address): string => {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('api', '1');
|
||||||
|
if (address.point !== null && address.addressReference !== null) {
|
||||||
|
params.append('query', `${address.point.coordinates[1]} ${address.point.coordinates[0]}`);
|
||||||
|
} else {
|
||||||
|
params.append('query', address.lines.join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
|
return `https://www.google.com/maps/search/?${params.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeUrlOsm = (address: Address): string => {
|
||||||
|
if (address.point !== null && address.addressReference !== null) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('mlat', `${address.point.coordinates[1]}`);
|
||||||
|
params.append('mlon', `${address.point.coordinates[0]}`);
|
||||||
|
const hashParams = new URLSearchParams();
|
||||||
|
hashParams.append('map', `18/${address.point.coordinates[1]}/${address.point.coordinates[0]}`);
|
||||||
|
|
||||||
|
return `https://www.openstreetmap.org/?${params.toString()}#${hashParams.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('query', address.lines.join(', '));
|
||||||
|
|
||||||
|
return `https://www.openstreetmap.org/search?${params.toString()}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
div.address_details_map {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<template v-if="props.address.refStatus !== 'match'">
|
||||||
|
<div v-if="props.address.refStatus === 'to_review' || props.address.refStatus === 'reviewed'" :class="{alert: true, 'alert-danger': props.address.refStatus === 'to_review', 'alert-warning': props.address.refStatus === 'reviewed'}">
|
||||||
|
<p v-if="props.address.refStatus === 'to_review'"><i class="fa fa-warning"></i> L'adresse de référence a été modifiée.</p>
|
||||||
|
<p v-if="props.address.refStatus === 'reviewed'">L'adresse est conservée, mais diffère de l'adresse de référence.</p>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.street !== props.address.street || props.address.addressReference.streetNumber !== props.address.streetNumber">
|
||||||
|
<template v-if="props.address.country.code === 'BE'">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.street }} {{props.address.streetNumber}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.street }} {{ props.address.addressReference.streetNumber }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{props.address.streetNumber}} {{ props.address.street }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.streetNumber }} {{ props.address.addressReference.street }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.postcode.id !== props.address.postcode.id">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.postcode.code }} {{props.address.postcode.name }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.postcode.code }} {{ props.address.addressReference.postcode.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.point !== null && (props.address.point.coordinates[0] !== props.address.addressReference.point.coordinates[0] || props.address.point.coordinates[1] !== props.address.addressReference.point.coordinates[1])">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.point.coordinates[0] }} {{ props.address.point.coordinates[1]}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.point.coordinates[0] }} {{ props.address.addressReference.point.coordinates[1]}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li v-if="props.address.refStatus === 'to_review'"><button class="btn btn-sm btn-update" @click="applyUpdate">Appliquer les modifications</button></li>
|
||||||
|
<li v-if="props.address.refStatus === 'to_review'"><button class="btn btn-sm btn-primary" @click="keepCurrentAddress">Conserver</button></li>
|
||||||
|
<li v-if="props.address.refStatus === 'reviewed'"><button class="btn btn-sm btn-primary" @click="backToReview">Ré-examiner</button></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {Address} from "../../../../types";
|
||||||
|
import {markAddressReviewed, markAddressToReview, syncAddressWithReference} from "../../../../lib/api/address";
|
||||||
|
|
||||||
|
export interface AddressDetailsRefMatchingProps {
|
||||||
|
address: Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressDetailsRefMatchingProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const applyUpdate = async () => {
|
||||||
|
const new_address = await syncAddressWithReference(props.address);
|
||||||
|
|
||||||
|
emit('update-address', new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keepCurrentAddress = async () => {
|
||||||
|
const new_address = await markAddressReviewed(props.address);
|
||||||
|
|
||||||
|
emit("update-address", new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const backToReview = async () => {
|
||||||
|
const new_address = await markAddressToReview(props.address);
|
||||||
|
|
||||||
|
emit("update-address", new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.difference {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.old {
|
||||||
|
text-decoration: red line-through;
|
||||||
|
}
|
||||||
|
.new {
|
||||||
|
font-weight: bold;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -11,17 +11,18 @@
|
|||||||
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
||||||
{{ l }}
|
{{ l }}
|
||||||
</p>
|
</p>
|
||||||
|
<p v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p v-if="address.text"
|
<p v-if="'' !== address.text"
|
||||||
class="street">
|
class="street">
|
||||||
{{ address.text }}
|
{{ address.text }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="address.postcode"
|
<p v-if="null !== address.postcode"
|
||||||
class="postcode">
|
class="postcode">
|
||||||
{{ address.postcode.code }} {{ address.postcode.name }}
|
{{ address.postcode.code }} {{ address.postcode.name }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="address.country"
|
<p v-if="null !== address.country"
|
||||||
class="country">
|
class="country">
|
||||||
{{ address.country.name.fr }}
|
{{ address.country.name.fr }}
|
||||||
</p>
|
</p>
|
||||||
@ -35,11 +36,12 @@
|
|||||||
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
||||||
{{ l }}
|
{{ l }}
|
||||||
</p>
|
</p>
|
||||||
|
<p v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p v-if="address.text"
|
<p v-if="address.text"
|
||||||
class="street">
|
class="street">
|
||||||
{{ address.text }}
|
{{ address.text }} <template v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></template>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -65,11 +67,13 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
||||||
|
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AddressRenderBox',
|
name: 'AddressRenderBox',
|
||||||
components: {
|
components: {
|
||||||
Confidential
|
Confidential,
|
||||||
|
AddressDetailsButton,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
address: {
|
address: {
|
||||||
@ -82,6 +86,10 @@ export default {
|
|||||||
useDatePane: {
|
useDatePane: {
|
||||||
default: false,
|
default: false,
|
||||||
type: Boolean
|
type: Boolean
|
||||||
|
},
|
||||||
|
showButtonDetails: {
|
||||||
|
default: true,
|
||||||
|
type: Boolean
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span>
|
||||||
</li>
|
</li>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -78,6 +79,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span>
|
||||||
</span>
|
</span>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -102,6 +104,7 @@
|
|||||||
<div class="noaddress">
|
<div class="noaddress">
|
||||||
{{ 'address.consider homeless'|trans }}
|
{{ 'address.consider homeless'|trans }}
|
||||||
</div>
|
</div>
|
||||||
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span></p>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
||||||
@ -109,6 +112,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.raw(lines) }}
|
{{ _self.raw(lines) }}
|
||||||
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span></p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.validity(address, options) }}
|
{{ _self.validity(address, options) }}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
{{ encore_entry_link_tags('chill') }}
|
{{ encore_entry_link_tags('chill') }}
|
||||||
{{ encore_entry_link_tags('mod_blur') }}
|
{{ encore_entry_link_tags('mod_blur') }}
|
||||||
{{ encore_entry_link_tags('vue_onthefly') }}
|
{{ encore_entry_link_tags('vue_onthefly') }}
|
||||||
|
{{ encore_entry_link_tags('mod_address_details') }}
|
||||||
{% block css %}<!-- nothing added to css -->{% endblock %}
|
{% block css %}<!-- nothing added to css -->{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -112,6 +113,7 @@
|
|||||||
{{ encore_entry_script_tags('mod_blur') }}
|
{{ encore_entry_script_tags('mod_blur') }}
|
||||||
{{ encore_entry_script_tags('chill') }}
|
{{ encore_entry_script_tags('chill') }}
|
||||||
{{ encore_entry_script_tags('vue_onthefly') }}
|
{{ encore_entry_script_tags('vue_onthefly') }}
|
||||||
|
{{ encore_entry_script_tags('mod_address_details') }}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.addEventListener('DOMContentLoaded', function(e) {
|
window.addEventListener('DOMContentLoaded', function(e) {
|
||||||
|
@ -97,6 +97,13 @@ class AddressNormalizer implements ContextAwareNormalizerInterface, NormalizerAw
|
|||||||
);
|
);
|
||||||
$data['validFrom'] = $address->getValidFrom();
|
$data['validFrom'] = $address->getValidFrom();
|
||||||
$data['validTo'] = $address->getValidTo();
|
$data['validTo'] = $address->getValidTo();
|
||||||
|
$data['refStatus'] = $address->getRefStatus();
|
||||||
|
$data['point'] = $this->normalizer->normalize(
|
||||||
|
$address->getPoint(),
|
||||||
|
$format,
|
||||||
|
[AbstractNormalizer::GROUPS => ['read']]
|
||||||
|
);
|
||||||
|
$data['isNoAddress'] = $address->isNoAddress();
|
||||||
} elseif ('docgen' === $format) {
|
} elseif ('docgen' === $format) {
|
||||||
$dateContext = array_merge($context, ['docgen:expects' => DateTimeInterface::class]);
|
$dateContext = array_merge($context, ['docgen:expects' => DateTimeInterface::class]);
|
||||||
$data['validFrom'] = $this->normalizer->normalize($address->getValidFrom(), $format, $dateContext);
|
$data['validFrom'] = $this->normalizer->normalize($address->getValidFrom(), $format, $dateContext);
|
||||||
|
@ -24,12 +24,18 @@ class AddressReferenceBEFromBestAddress
|
|||||||
|
|
||||||
private AddressReferenceBaseImporter $baseImporter;
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private AddressToReferenceMatcher $addressToReferenceMatcher;
|
||||||
|
|
||||||
private HttpClientInterface $client;
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
public function __construct(
|
||||||
{
|
HttpClientInterface $client,
|
||||||
|
AddressReferenceBaseImporter $baseImporter,
|
||||||
|
AddressToReferenceMatcher $addressToReferenceMatcher
|
||||||
|
) {
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
$this->baseImporter = $baseImporter;
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->addressToReferenceMatcher = $addressToReferenceMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import(string $lang, array $lists): void
|
public function import(string $lang, array $lists): void
|
||||||
@ -89,16 +95,18 @@ class AddressReferenceBEFromBestAddress
|
|||||||
$record['municipality_objectid'],
|
$record['municipality_objectid'],
|
||||||
$record['postal_info_objectid'],
|
$record['postal_info_objectid'],
|
||||||
$record['streetname'],
|
$record['streetname'],
|
||||||
$record['housenumber'] . $record['boxnumber'],
|
$record['housenumber'] .($record['boxnumber'] !== '' ? ' bte '. $record['boxnumber'] : ''),
|
||||||
'bestaddress.' . $list,
|
'bestaddress.' . $list,
|
||||||
(float) $record['X'],
|
|
||||||
(float) $record['Y'],
|
(float) $record['Y'],
|
||||||
|
(float) $record['X'],
|
||||||
3812
|
3812
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->baseImporter->finalize();
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
gzclose($uncompressedStream);
|
gzclose($uncompressedStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,15 @@ class AddressReferenceFromBano
|
|||||||
{
|
{
|
||||||
private AddressReferenceBaseImporter $baseImporter;
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private AddressToReferenceMatcher $addressToReferenceMatcher;
|
||||||
|
|
||||||
private HttpClientInterface $client;
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter, AddressToReferenceMatcher $addressToReferenceMatcher)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
$this->baseImporter = $baseImporter;
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->addressToReferenceMatcher = $addressToReferenceMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import(string $departementNo): void
|
public function import(string $departementNo): void
|
||||||
@ -82,6 +85,8 @@ class AddressReferenceFromBano
|
|||||||
|
|
||||||
$this->baseImporter->finalize();
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
fclose($file);
|
fclose($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark existing addresses as to be reviewed regarding the
|
||||||
|
* address reference
|
||||||
|
*/
|
||||||
|
final class AddressToReferenceMatcher
|
||||||
|
{
|
||||||
|
private Connection $connection;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
private const LOG_PREFIX = '[address_to_reference_matcher] ';
|
||||||
|
|
||||||
|
private const SQL_MARK_TO_REVIEW_ADDRESS_UNMATCHING = <<<'SQL'
|
||||||
|
UPDATE chill_main_address a SET refstatus = '{{ to_review }}', refstatuslastupdate = NOW()
|
||||||
|
FROM chill_main_address_reference ar
|
||||||
|
WHERE
|
||||||
|
a.addressreference_id = ar.id
|
||||||
|
-- restrict only on active addresses
|
||||||
|
AND (a.validto IS NULL OR a.validto >= NOW())
|
||||||
|
-- only addresses that are marked matching or "to review", but before the update
|
||||||
|
AND
|
||||||
|
(a.refstatus LIKE '{{ matching }}'
|
||||||
|
OR (a.refstatus LIKE '{{ reviewed }}' AND a.refstatuslastupdate < ar.updatedat))
|
||||||
|
AND (
|
||||||
|
a.postcode_id != ar.postcode_id
|
||||||
|
OR a.street != ar.street
|
||||||
|
OR a.streetnumber != ar.streetnumber
|
||||||
|
OR ROUND(ST_X(a.point) * 1000000) <> ROUND(ST_X(ar.point) * 1000000)
|
||||||
|
OR ROUND(ST_Y(a.point) * 1000000) <> ROUND(ST_Y(ar.point) * 1000000)
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const SQL_MARK_MATCHING_ADDRESSES_REVIEWED_OR_TO_REVIEW = <<<'SQL'
|
||||||
|
UPDATE chill_main_address a SET refstatus = '{{ matching }}', refstatuslastupdate = NOW()
|
||||||
|
FROM chill_main_address_reference ar
|
||||||
|
WHERE
|
||||||
|
a.addressreference_id = ar.id
|
||||||
|
-- restrict only on active addresses
|
||||||
|
AND (a.validto IS NULL OR a.validto >= NOW())
|
||||||
|
AND a.refstatus IN ('{{ to_review }}', '{{ reviewed }}')
|
||||||
|
AND a.postcode_id = ar.postcode_id
|
||||||
|
AND a.street = ar.street
|
||||||
|
AND a.streetnumber = ar.streetnumber
|
||||||
|
AND ROUND(ST_X(a.point) * 1000000) = ROUND(ST_X(ar.point) * 1000000)
|
||||||
|
AND ROUND(ST_Y(a.point) * 1000000) = ROUND(ST_Y(ar.point) * 1000000)
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const SUBSTITUTES = [
|
||||||
|
'{{ to_review }}' => Address::ADDR_REFERENCE_STATUS_TO_REVIEW,
|
||||||
|
'{{ matching }}' => Address::ADDR_REFERENCE_STATUS_MATCH,
|
||||||
|
'{{ reviewed }}' => Address::ADDR_REFERENCE_STATUS_REVIEWED
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(Connection $connection, LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkAddressesMatchingReferences(): void
|
||||||
|
{
|
||||||
|
$this->logger->notice(self::LOG_PREFIX.'Starting addresses matching');
|
||||||
|
|
||||||
|
$this->connection->transactional(function () {
|
||||||
|
$markedAsMatching = $this->connection->executeStatement(
|
||||||
|
strtr(self::SQL_MARK_MATCHING_ADDRESSES_REVIEWED_OR_TO_REVIEW, self::SUBSTITUTES)
|
||||||
|
);
|
||||||
|
|
||||||
|
$markedAsToReview = $this->connection->executeStatement(
|
||||||
|
strtr(self::SQL_MARK_TO_REVIEW_ADDRESS_UNMATCHING, self::SUBSTITUTES)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->logger->info(self::LOG_PREFIX.'Executed address matching', [
|
||||||
|
'marked_as_matching' => $markedAsMatching,
|
||||||
|
'marked_as_to_review' => $markedAsToReview,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,8 @@ namespace Chill\MainBundle\Templating\Entity;
|
|||||||
|
|
||||||
use Chill\MainBundle\Entity\Address;
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
use Symfony\Component\Templating\EngineInterface;
|
use Symfony\Component\Templating\EngineInterface;
|
||||||
|
|
||||||
use function array_merge;
|
use function array_merge;
|
||||||
@ -38,8 +40,10 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
|
|
||||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||||
|
|
||||||
public function __construct(EngineInterface $templating, TranslatableStringHelperInterface $translatableStringHelper)
|
public function __construct(
|
||||||
{
|
EngineInterface $templating,
|
||||||
|
TranslatableStringHelperInterface $translatableStringHelper
|
||||||
|
) {
|
||||||
$this->templating = $templating;
|
$this->templating = $templating;
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
$this->translatableStringHelper = $translatableStringHelper;
|
||||||
}
|
}
|
||||||
@ -58,6 +62,9 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
public function renderLines(Address $addr, bool $includeCityLine = true, bool $includeCountry = true): array
|
public function renderLines(Address $addr, bool $includeCityLine = true, bool $includeCountry = true): array
|
||||||
{
|
{
|
||||||
$lines = [];
|
$lines = [];
|
||||||
@ -91,18 +98,18 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_values(array_filter($lines, static fn ($l) => null !== $l));
|
return array_values(array_filter($lines, static fn ($l) => '' !== (string) $l));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderStreetLine(Address $addr): ?string
|
public function renderStreetLine(Address $addr): ?string
|
||||||
{
|
{
|
||||||
if (null !== $addr->getStreet() && $addr->getStreet() !== '') {
|
if ('' !== $addr->getStreet()) {
|
||||||
$street = $addr->getStreet();
|
$street = $addr->getStreet();
|
||||||
} else {
|
} else {
|
||||||
$street = '';
|
$street = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $addr->getStreetNumber() && $addr->getStreetNumber() !== '') {
|
if ('' !== $addr->getStreetNumber()) {
|
||||||
$streetNumber = $addr->getStreetNumber();
|
$streetNumber = $addr->getStreetNumber();
|
||||||
} else {
|
} else {
|
||||||
$streetNumber = '';
|
$streetNumber = '';
|
||||||
@ -133,7 +140,7 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
|
|
||||||
private function renderBuildingLine(Address $addr): ?string
|
private function renderBuildingLine(Address $addr): ?string
|
||||||
{
|
{
|
||||||
if (null !== $addr->getBuildingName() && $addr->getBuildingName() !== '') {
|
if ($addr->getBuildingName() !== '') {
|
||||||
$building = $addr->getBuildingName();
|
$building = $addr->getBuildingName();
|
||||||
} else {
|
} else {
|
||||||
$building = '';
|
$building = '';
|
||||||
@ -157,7 +164,7 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderCityLine($addr): string
|
private function renderCityLine(Address $addr): string
|
||||||
{
|
{
|
||||||
if (null !== $addr->getPostcode()) {
|
if (null !== $addr->getPostcode()) {
|
||||||
$res = strtr('{postcode} {label}', [
|
$res = strtr('{postcode} {label}', [
|
||||||
@ -165,11 +172,9 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
'{label}' => $addr->getPostcode()->getName(),
|
'{label}' => $addr->getPostcode()->getName(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (null !== $addr->getPostCode()->getCountry()->getCountryCode()) {
|
if ($addr->getPostcode()->getCountry()->getCountryCode() === 'FR') {
|
||||||
if ($addr->getPostCode()->getCountry()->getCountryCode() === 'FR') {
|
if ('' !== $addr->getDistribution()) {
|
||||||
if ($addr->getDistribution()) {
|
$res = $res . ' ' . $addr->getDistribution();
|
||||||
$res = $res . ' ' . $addr->getDistribution();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,35 +182,35 @@ class AddressRender implements ChillEntityRenderInterface
|
|||||||
return $res ?? '';
|
return $res ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderCountryLine($addr): ?string
|
private function renderCountryLine(Address $addr): ?string
|
||||||
{
|
{
|
||||||
return $this->translatableStringHelper->localize(
|
return $this->translatableStringHelper->localize(
|
||||||
$addr->getPostCode()->getCountry()->getName()
|
$addr->getPostcode()->getCountry()->getName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderDeliveryLine($addr): ?string
|
private function renderDeliveryLine(Address $addr): string
|
||||||
{
|
{
|
||||||
return $addr->getExtra();
|
return $addr->getExtra();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderIntraBuildingLine($addr): ?string
|
private function renderIntraBuildingLine(Address $addr): ?string
|
||||||
{
|
{
|
||||||
$arr = [];
|
$arr = [];
|
||||||
|
|
||||||
if ($addr->getFlat()) {
|
if ('' !== $addr->getFlat()) {
|
||||||
$arr[] = 'appart ' . $addr->getFlat();
|
$arr[] = 'appart ' . $addr->getFlat();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addr->getFloor()) {
|
if ('' !== $addr->getFloor()) {
|
||||||
$arr[] = 'ét ' . $addr->getFloor();
|
$arr[] = 'ét ' . $addr->getFloor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addr->getCorridor()) {
|
if ('' !== $addr->getCorridor()) {
|
||||||
$arr[] = 'coul ' . $addr->getCorridor();
|
$arr[] = 'coul ' . $addr->getCorridor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($addr->getSteps()) {
|
if ('' !== $addr->getSteps()) {
|
||||||
$arr[] = 'esc ' . $addr->getSteps();
|
$arr[] = 'esc ' . $addr->getSteps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\AddressReference;
|
||||||
|
use Chill\MainBundle\Repository\AddressRepository;
|
||||||
|
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class AddressToReferenceMatcherControllerTest extends WebTestCase
|
||||||
|
{
|
||||||
|
use PrepareClientTrait;
|
||||||
|
|
||||||
|
private AddressRepository $addressRepository;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$this->addressRepository = self::$container->get(AddressRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider addressToReviewProvider
|
||||||
|
*/
|
||||||
|
public function testMarkAddressAsReviewed(int $addressId): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientAuthenticated();
|
||||||
|
|
||||||
|
$client->request('POST', "/api/1.0/main/address/reference-match/${addressId}/set/reviewed");
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$address = $this->addressRepository->find($addressId);
|
||||||
|
|
||||||
|
$this->assertEquals(Address::ADDR_REFERENCE_STATUS_REVIEWED, $address->getRefStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider addressUnsyncedProvider
|
||||||
|
*/
|
||||||
|
public function testSyncAddressWithReference(int $addressId): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientAuthenticated();
|
||||||
|
|
||||||
|
$client->request('POST', "/api/1.0/main/address/reference-match/${addressId}/sync-with-reference");
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$address = $this->addressRepository->find($addressId);
|
||||||
|
|
||||||
|
$this->assertEquals(Address::ADDR_REFERENCE_STATUS_MATCH, $address->getRefStatus());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getStreet(), $address->getStreet());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getStreetNumber(), $address->getStreetNumber());
|
||||||
|
$this->assertEquals($address->getAddressReference()->getPoint()->toWKT(), $address->getPoint()->toWKT());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addressToReviewProvider(): iterable
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$nb = $em->createQuery('SELECT count(a) FROM '.Address::class.' a')
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
if (0 === $nb) {
|
||||||
|
throw new \RuntimeException("There aren't any address with a ref status 'matched'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Address $address */
|
||||||
|
$address = $em->createQuery('SELECT a FROM '.Address::class.' a')
|
||||||
|
->setFirstResult(rand(0, $nb))
|
||||||
|
->setMaxResults(1)
|
||||||
|
->getSingleResult();
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
yield [$address->getId()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addressUnsyncedProvider(): iterable
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$nb = $em->createQuery('SELECT count(a) FROM '.AddressReference::class.' a')
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
if (0 === $nb) {
|
||||||
|
throw new \RuntimeException("There isn't any address reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref = $em->createQuery('SELECT a FROM '.AddressReference::class.' a')
|
||||||
|
->setMaxResults(1)
|
||||||
|
->setFirstResult(rand(0, $nb))
|
||||||
|
->getSingleResult();
|
||||||
|
|
||||||
|
$address = Address::createFromAddressReference($ref);
|
||||||
|
|
||||||
|
// make the address dirty
|
||||||
|
$address->setStreet('tagada')
|
||||||
|
->setStreetNumber('-250')
|
||||||
|
->setPoint(Point::fromLonLat(0, 0))
|
||||||
|
->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
|
||||||
|
$em->persist($address);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
yield [$address->getId()];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Test\PrepareClientTrait;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class GeographicalUnitByAddressApiControllerTest extends WebTestCase
|
||||||
|
{
|
||||||
|
use PrepareClientTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider generateRandomAddress
|
||||||
|
*/
|
||||||
|
public function testGetGeographicalUnitCoveringAddress(int $addressId): void
|
||||||
|
{
|
||||||
|
$client = $this->getClientAuthenticated();
|
||||||
|
|
||||||
|
$client->request('GET', '/api/1.0/main/geographical-unit/by-address/'.$addressId.'.json');
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateRandomAddress(): iterable
|
||||||
|
{
|
||||||
|
self::bootKernel();
|
||||||
|
$em = self::$container->get(EntityManagerInterface::class);
|
||||||
|
|
||||||
|
$nb = $em->createQuery('SELECT COUNT(a) FROM '.Address::class.' a')->getSingleScalarResult();
|
||||||
|
/** @var \Chill\MainBundle\Entity\Address $random */
|
||||||
|
$random = $em->createQuery('SELECT a FROM '.Address::class.' a')
|
||||||
|
->setFirstResult(rand(0, $nb))
|
||||||
|
->setMaxResults(1)
|
||||||
|
->getSingleResult();
|
||||||
|
|
||||||
|
yield [$random->getId()];
|
||||||
|
}
|
||||||
|
}
|
@ -99,7 +99,7 @@ final class AddressReferenceBaseImporterTest extends KernelTestCase
|
|||||||
'abcc guessed fixed'
|
'abcc guessed fixed'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertCount('1', $addresses);
|
$this->assertCount(1, $addresses);
|
||||||
$this->assertEquals('Rue test abccc guessed fixed', $addresses[0]->getStreet());
|
$this->assertEquals('Rue test abccc guessed fixed', $addresses[0]->getStreet());
|
||||||
$this->assertEquals($previousAddressId, $addresses[0]->getId());
|
$this->assertEquals($previousAddressId, $addresses[0]->getId());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Services\Import;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\AddressReference;
|
||||||
|
use Chill\MainBundle\Entity\PostalCode;
|
||||||
|
use Chill\MainBundle\Repository\AddressReferenceRepository;
|
||||||
|
use Chill\MainBundle\Repository\CountryRepository;
|
||||||
|
use Chill\MainBundle\Service\Import\AddressReferenceBaseImporter;
|
||||||
|
use Chill\MainBundle\Service\Import\AddressToReferenceMatcher;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class AddressToReferenceMatcherTest extends KernelTestCase
|
||||||
|
{
|
||||||
|
private AddressToReferenceMatcher $addressToReferenceMatcher;
|
||||||
|
|
||||||
|
private AddressReferenceRepository $addressReferenceRepository;
|
||||||
|
|
||||||
|
private CountryRepository $countryRepository;
|
||||||
|
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private AddressReferenceBaseImporter $addressReferenceBaseImporter;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
self::bootKernel();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher = self::$container->get(AddressToReferenceMatcher::class);
|
||||||
|
$this->addressReferenceRepository = self::$container->get(AddressReferenceRepository::class);
|
||||||
|
$this->countryRepository = self::$container->get(CountryRepository::class);
|
||||||
|
$this->addressReferenceBaseImporter = self::$container->get(AddressReferenceBaseImporter::class);
|
||||||
|
$this->entityManager = self::$container->get(EntityManagerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCheckAddressesMatchingReferences(): void
|
||||||
|
{
|
||||||
|
if (null === $belgium = $this->countryRepository->findOneBy(['countryCode' => 'BE'])) {
|
||||||
|
throw new \RuntimeException('Belgium not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$postalCode = (new PostalCode())
|
||||||
|
->setName('test for matcher')
|
||||||
|
->setPostalCodeSource('test for matcher')
|
||||||
|
->setCode('78910')
|
||||||
|
->setRefPostalCodeId($refPostalCodeId = '78910'.uniqid())
|
||||||
|
->setCountry($belgium)
|
||||||
|
;
|
||||||
|
$this->entityManager->persist($postalCode);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->addressReferenceBaseImporter->importAddress(
|
||||||
|
$refAddress = '010203_test'.uniqid(),
|
||||||
|
$refPostalCodeId,
|
||||||
|
'78910',
|
||||||
|
$street = 'Rue Poulet',
|
||||||
|
$streetNumber = '14',
|
||||||
|
'test_matcher',
|
||||||
|
$lat = 50.0123456789,
|
||||||
|
$lon = 5.0123456789,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
$this->addressReferenceBaseImporter->finalize();
|
||||||
|
|
||||||
|
if (null === $addressReference = $this->addressReferenceRepository->findOneBy(['refId' => $refAddress])) {
|
||||||
|
throw new \RuntimeException('address reference not created');
|
||||||
|
}
|
||||||
|
|
||||||
|
$address = Address::createFromAddressReference($addressReference);
|
||||||
|
|
||||||
|
$this->assertEquals('Rue Poulet', $address->getStreet());
|
||||||
|
|
||||||
|
$this->entityManager->persist($address);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
// we update the address
|
||||||
|
$this->addressReferenceBaseImporter->importAddress(
|
||||||
|
$refAddress,
|
||||||
|
$refPostalCodeId,
|
||||||
|
'78910',
|
||||||
|
'Rue Poulet aux amandes',
|
||||||
|
'14',
|
||||||
|
'test_matcher',
|
||||||
|
50.01234456789,
|
||||||
|
5.0123456789,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
$this->addressReferenceBaseImporter->finalize();
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
|
$this->entityManager->refresh($address);
|
||||||
|
|
||||||
|
$this->assertEquals('to_review', $address->getRefStatus());
|
||||||
|
|
||||||
|
// we update the address
|
||||||
|
$this->addressReferenceBaseImporter->importAddress(
|
||||||
|
$refAddress,
|
||||||
|
$refPostalCodeId,
|
||||||
|
'78910',
|
||||||
|
$street,
|
||||||
|
$streetNumber,
|
||||||
|
'test_matcher',
|
||||||
|
$lat,
|
||||||
|
$lon,
|
||||||
|
4326
|
||||||
|
);
|
||||||
|
$this->addressReferenceBaseImporter->finalize();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
|
$this->entityManager->refresh($address);
|
||||||
|
|
||||||
|
$this->assertEquals('Rue Poulet', $address->getStreet());
|
||||||
|
$this->assertEquals('match', $address->getRefStatus());
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ use Chill\MainBundle\Templating\Entity\AddressRender;
|
|||||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
use Iterator;
|
use Iterator;
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
use Symfony\Component\Templating\EngineInterface;
|
use Symfony\Component\Templating\EngineInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +75,7 @@ module.exports = function(encore, entries)
|
|||||||
encore.addEntry('mod_wopi_link', __dirname + '/Resources/public/module/wopi-link/index.js');
|
encore.addEntry('mod_wopi_link', __dirname + '/Resources/public/module/wopi-link/index.js');
|
||||||
encore.addEntry('mod_pick_postal_code', __dirname + '/Resources/public/module/pick-postal-code/index.js');
|
encore.addEntry('mod_pick_postal_code', __dirname + '/Resources/public/module/pick-postal-code/index.js');
|
||||||
encore.addEntry('mod_pick_rolling_date', __dirname + '/Resources/public/module/pick-rolling-date/index.js');
|
encore.addEntry('mod_pick_rolling_date', __dirname + '/Resources/public/module/pick-rolling-date/index.js');
|
||||||
|
encore.addEntry('mod_address_details', __dirname + '/Resources/public/module/address-details/index');
|
||||||
|
|
||||||
// Vue entrypoints
|
// Vue entrypoints
|
||||||
encore.addEntry('vue_address', __dirname + '/Resources/public/vuejs/Address/index.js');
|
encore.addEntry('vue_address', __dirname + '/Resources/public/vuejs/Address/index.js');
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20230306142148 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add columns refStatus and refStatusLastUpdate to Address';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD refStatus TEXT DEFAULT \'match\' NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD refStatusLastUpdate TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL');
|
||||||
|
|
||||||
|
// we must set the last status update to the address reference date to avoid inconsistencies
|
||||||
|
$this->addSql('UPDATE chill_main_address a SET refStatusLastUpdate = COALESCE(r.updatedat, r.createdat, \'1970-01-01\'::timestamp) FROM chill_main_address_reference r WHERE a.addressreference_id = r.id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP refStatus');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP refStatusLastUpdate');
|
||||||
|
}
|
||||||
|
}
|
116
src/Bundle/ChillMainBundle/migrations/Version20230306145728.php
Normal file
116
src/Bundle/ChillMainBundle/migrations/Version20230306145728.php
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20230306145728 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'fix inconsistencies in chill_main_address table';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD createdBy_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD updatedBy_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER street TYPE TEXT');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET street=\'\' WHERE street IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER street SET DEFAULT \'\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER streetnumber TYPE TEXT');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET streetnumber=\'\' WHERE streetnumber IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER streetnumber SET DEFAULT \'\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER floor SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET floor=\'\' WHERE floor IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER floor SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER corridor SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET corridor=\'\' WHERE corridor IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER corridor SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER steps SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET steps=\'\' WHERE steps IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER steps SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingname TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingname SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET buildingname=\'\' WHERE buildingname IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingname SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER flat SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET flat=\'\' WHERE flat IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER flat SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET distribution=\'\' WHERE distribution IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET extra=\'\' WHERE extra IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra SET NOT NULL');
|
||||||
|
$this->addSql('UPDATE chill_main_address SET confidential=FALSE WHERE confidential IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER confidential SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER refstatuslastupdate TYPE TIMESTAMP(0) WITHOUT TIME ZONE');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address.point IS \'(DC2Type:point)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address.createdAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address.updatedAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address.refStatusLastUpdate IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD CONSTRAINT FK_165051F63174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD CONSTRAINT FK_165051F665FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('CREATE INDEX IDX_165051F63174800F ON chill_main_address (createdBy_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_165051F665FF1AEC ON chill_main_address (updatedBy_id)');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.point IS \'(DC2Type:point)\'');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->throwIrreversibleMigrationException('down method is not double-checked');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP CONSTRAINT FK_165051F63174800F');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP CONSTRAINT FK_165051F665FF1AEC');
|
||||||
|
$this->addSql('DROP INDEX IDX_165051F63174800F');
|
||||||
|
$this->addSql('DROP INDEX IDX_165051F665FF1AEC');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ADD customs JSONB DEFAULT \'[]\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP createdAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP updatedAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP createdBy_id');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address DROP updatedBy_id');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingName TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingName DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER buildingName DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER confidential SET DEFAULT false');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER confidential DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER corridor DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER corridor DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER distribution DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER extra DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER flat DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER flat DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER floor DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER floor DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER isNoAddress SET DEFAULT false');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER point TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER refStatusLastUpdate TYPE TIMESTAMP(0) WITHOUT TIME ZONE');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER steps DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER steps DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER street TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER street DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER streetNumber TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address ALTER streetNumber DROP DEFAULT');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address.refstatuslastupdate IS NULL');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20230306151218 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'fix inconsistencies in chill_main_address_reference table';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER refid TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER refid SET DEFAULT \'\'');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address_reference SET street = \'\' WHERE street IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetnumber TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetnumber SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address_reference SET streetnumber = \'\' WHERE streetnumber IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetnumber SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalitycode TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalitycode SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address_reference SET municipalitycode = \'\' WHERE municipalitycode IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalitycode SET NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source TYPE TEXT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source SET DEFAULT \'\'');
|
||||||
|
$this->addSql('UPDATE chill_main_address_reference SET source = \'\' WHERE source IS NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source SET NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->throwIrreversibleMigrationException('not double-checked');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalityCode TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalityCode DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER municipalityCode DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER refId TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER refId DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER source DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER street DROP NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetNumber TYPE VARCHAR(255)');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetNumber DROP DEFAULT');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ALTER streetNumber DROP NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Export\Filter\PersonFilters;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||||
|
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||||
|
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
|
||||||
|
use Chill\PersonBundle\Export\Declarations;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
class AddressRefStatusFilter implements \Chill\MainBundle\Export\FilterInterface
|
||||||
|
{
|
||||||
|
private RollingDateConverterInterface $rollingDateConverter;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
RollingDateConverterInterface $rollingDateConverter
|
||||||
|
) {
|
||||||
|
$this->rollingDateConverter = $rollingDateConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRole(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
|
{
|
||||||
|
$subQuery =
|
||||||
|
'SELECT 1
|
||||||
|
FROM ' . PersonHouseholdAddress::class . ' person_filter_having_address_to_review_person_household_address
|
||||||
|
JOIN person_filter_having_address_to_review_person_household_address.address person_filter_having_address_to_review_address
|
||||||
|
WHERE
|
||||||
|
person_filter_having_address_to_review_person_household_address.validFrom <= :person_filter_having_address_to_review_date
|
||||||
|
AND
|
||||||
|
(person_filter_having_address_to_review_person_household_address.validTo IS NULL
|
||||||
|
OR person_filter_having_address_to_review_person_household_address.validTo > :person_filter_having_address_to_review_date)
|
||||||
|
AND
|
||||||
|
person_filter_having_address_to_review_person_household_address.person = person
|
||||||
|
AND person_filter_having_address_to_review_address.refStatus IN (:person_filter_having_address_to_review_ref_statuses)
|
||||||
|
';
|
||||||
|
|
||||||
|
$qb
|
||||||
|
->andWhere(
|
||||||
|
$qb->expr()->exists($subQuery)
|
||||||
|
)
|
||||||
|
->setParameter(
|
||||||
|
'person_filter_having_address_to_review_date',
|
||||||
|
$this->rollingDateConverter->convert($data['date_calc'] ?? RollingDate::T_TODAY)
|
||||||
|
)
|
||||||
|
->setParameter('person_filter_having_address_to_review_ref_statuses', $data['ref_statuses'] ?? [Address::ADDR_REFERENCE_STATUS_TO_REVIEW]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyOn()
|
||||||
|
{
|
||||||
|
return Declarations::PERSON_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder)
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('date_calc', PickRollingDateType::class, [
|
||||||
|
'label' => 'Compute address at date',
|
||||||
|
'required' => true,
|
||||||
|
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||||
|
])
|
||||||
|
->add('ref_statuses', ChoiceType::class, [
|
||||||
|
'label' => 'export.filter.person.by_address_ref_status.Status',
|
||||||
|
'choices' => [Address::ADDR_REFERENCE_STATUS_TO_REVIEW, Address::ADDR_REFERENCE_STATUS_REVIEWED, Address::ADDR_REFERENCE_STATUS_MATCH],
|
||||||
|
'choice_label' => function (string $item) {
|
||||||
|
return 'export.filter.person.by_address_ref_status.'.$item;
|
||||||
|
},
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
'data' => [Address::ADDR_REFERENCE_STATUS_TO_REVIEW]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeAction($data, $format = 'string')
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'export.filter.person.by_address_ref_status.Filtered by person\'s address status computed at %datecalc%, only %statuses%',
|
||||||
|
[
|
||||||
|
'%datecalc%' => $this->rollingDateConverter->convert($data['date_calc'])->format('Y-m-d'),
|
||||||
|
'%statuses%' => implode(
|
||||||
|
', ',
|
||||||
|
array_map(
|
||||||
|
function (string $item) {
|
||||||
|
return 'export.filter.person.by_address_ref_status.'.$item;
|
||||||
|
},
|
||||||
|
$data['ref_statuses'] ?? RollingDate::T_TODAY
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return 'export.filter.person.by_address_ref_status.Filter by person\'s address ref status';
|
||||||
|
}
|
||||||
|
}
|
@ -15,33 +15,36 @@
|
|||||||
:person="participation.person"
|
:person="participation.person"
|
||||||
:returnPath="getAccompanyingCourseReturnPath">
|
:returnPath="getAccompanyingCourseReturnPath">
|
||||||
|
|
||||||
<template v-slot:record-actions>
|
<template v-slot:end-bloc>
|
||||||
<ul class="record_actions">
|
<div class="item-row separator">
|
||||||
|
<ul class="record_actions">
|
||||||
<button-location
|
<button-location
|
||||||
v-if="hasCurrentHouseholdAddress"
|
v-if="hasCurrentHouseholdAddress && !isPersonLocatingCourse(participation.person)"
|
||||||
v-bind:person="participation.person">
|
v-bind:person="participation.person">
|
||||||
</button-location>
|
</button-location>
|
||||||
<li v-if="participation.person.current_household_id">
|
<li v-if="participation.person.current_household_id">
|
||||||
<a class="btn btn-sm btn-chill-beige"
|
<a class="btn btn-sm btn-chill-beige"
|
||||||
:href="getCurrentHouseholdUrl"
|
:href="getCurrentHouseholdUrl"
|
||||||
:title="$t('persons_associated.show_household_number', { id: participation.person.current_household_id })">
|
:title="$t('persons_associated.show_household_number', { id: participation.person.current_household_id })">
|
||||||
<i class="fa fa-fw fa-home"></i>
|
<i class="fa fa-fw fa-home"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="show"></on-the-fly></li>
|
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="show"></on-the-fly></li>
|
||||||
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
|
<li><on-the-fly :type="participation.person.type" :id="participation.person.id" action="edit" @saveFormOnTheFly="saveFormOnTheFly" ref="onTheFly"></on-the-fly></li>
|
||||||
<li>
|
<li>
|
||||||
<button v-if="!participation.endDate"
|
<button v-if="!participation.endDate"
|
||||||
class="btn btn-sm btn-remove"
|
class="btn btn-sm btn-remove"
|
||||||
v-bind:title="$t('persons_associated.leave_course')"
|
v-bind:title="$t('persons_associated.leave_course')"
|
||||||
@click="modal.showModal = true">
|
@click="modal.showModal = true">
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</person-render-box>
|
</person-render-box>
|
||||||
|
|
||||||
|
|
||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<modal v-if="modal.showModal" :modalDialogClass="modal.modalDialogClass" @close="modal.showModal = false">
|
<modal v-if="modal.showModal" :modalDialogClass="modal.modalDialogClass" @close="modal.showModal = false">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
@ -106,9 +109,12 @@ export default {
|
|||||||
},
|
},
|
||||||
getCurrentHouseholdUrl() {
|
getCurrentHouseholdUrl() {
|
||||||
return `/fr/person/household/${this.participation.person.current_household_id}/summary?returnPath=${this.getAccompanyingCourseReturnPath}`
|
return `/fr/person/household/${this.participation.person.current_household_id}/summary?returnPath=${this.getAccompanyingCourseReturnPath}`
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
isPersonLocatingCourse(person) {
|
||||||
|
return this.$store.getters.isPersonLocatingCourse(person);
|
||||||
|
},
|
||||||
saveFormOnTheFly(payload) {
|
saveFormOnTheFly(payload) {
|
||||||
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
|
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
|
||||||
payload.target = 'participation';
|
payload.target = 'participation';
|
||||||
|
@ -12,40 +12,42 @@
|
|||||||
hLevel : 3,
|
hLevel : 3,
|
||||||
isConfidential : true
|
isConfidential : true
|
||||||
}">
|
}">
|
||||||
<template v-slot:record-actions>
|
<template v-slot:end-bloc>
|
||||||
<ul class="record_actions">
|
<div class="item-row separator">
|
||||||
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<write-comment
|
<write-comment
|
||||||
:resource="resource"
|
:resource="resource"
|
||||||
@updateComment="updateComment"
|
@updateComment="updateComment"
|
||||||
></write-comment>
|
></write-comment>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:parent="parent"
|
:parent="parent"
|
||||||
:type="resource.resource.type"
|
:type="resource.resource.type"
|
||||||
:id="resource.resource.id"
|
:id="resource.resource.id"
|
||||||
action="show">
|
action="show">
|
||||||
</on-the-fly>
|
</on-the-fly>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:parent="parent"
|
:parent="parent"
|
||||||
:type="resource.resource.type"
|
:type="resource.resource.type"
|
||||||
:id="resource.resource.id"
|
:id="resource.resource.id"
|
||||||
action="edit"
|
action="edit"
|
||||||
@saveFormOnTheFly="saveFormOnTheFly"
|
@saveFormOnTheFly="saveFormOnTheFly"
|
||||||
ref="onTheFly">
|
ref="onTheFly">
|
||||||
</on-the-fly>
|
</on-the-fly>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-remove"
|
class="btn btn-sm btn-remove"
|
||||||
:title="$t('action.remove')"
|
:title="$t('action.remove')"
|
||||||
@click.prevent="$emit('remove', resource)">
|
@click.prevent="$emit('remove', resource)">
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</person-render-box>
|
</person-render-box>
|
||||||
|
|
||||||
@ -59,40 +61,42 @@
|
|||||||
addInfo: false,
|
addInfo: false,
|
||||||
hLevel: 3
|
hLevel: 3
|
||||||
}">
|
}">
|
||||||
<template v-slot:record-actions>
|
<template v-slot:end-bloc>
|
||||||
<ul class="record_actions">
|
<div class="item-row separator">
|
||||||
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<write-comment
|
<write-comment
|
||||||
:resource="resource"
|
:resource="resource"
|
||||||
@updateComment="updateComment"
|
@updateComment="updateComment"
|
||||||
></write-comment>
|
></write-comment>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:parent="parent"
|
:parent="parent"
|
||||||
:type="resource.resource.type"
|
:type="resource.resource.type"
|
||||||
:id="resource.resource.id"
|
:id="resource.resource.id"
|
||||||
action="show">
|
action="show">
|
||||||
</on-the-fly>
|
</on-the-fly>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:parent="parent"
|
:parent="parent"
|
||||||
:type="resource.resource.type"
|
:type="resource.resource.type"
|
||||||
:id="resource.resource.id"
|
:id="resource.resource.id"
|
||||||
action="edit"
|
action="edit"
|
||||||
@saveFormOnTheFly="saveFormOnTheFly"
|
@saveFormOnTheFly="saveFormOnTheFly"
|
||||||
ref="onTheFly">
|
ref="onTheFly">
|
||||||
</on-the-fly>
|
</on-the-fly>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-remove"
|
class="btn btn-sm btn-remove"
|
||||||
:title="$t('action.remove')"
|
:title="$t('action.remove')"
|
||||||
@click.prevent="$emit('remove', resource)">
|
@click.prevent="$emit('remove', resource)">
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</third-party-render-box>
|
</third-party-render-box>
|
||||||
</template>
|
</template>
|
||||||
|
@ -49,6 +49,13 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou
|
|||||||
postFirstPinnedCommentResponse: null,
|
postFirstPinnedCommentResponse: null,
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
isPersonLocatingCourse: (state) => (person) => {
|
||||||
|
if (state.accompanyingCourse.locationStatus !== 'person') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.accompanyingCourse.personLocation.id === person.id;
|
||||||
|
},
|
||||||
isParticipationValid(state) {
|
isParticipationValid(state) {
|
||||||
return state.accompanyingCourse.participations.length > 0;
|
return state.accompanyingCourse.participations.length > 0;
|
||||||
},
|
},
|
||||||
|
@ -1,184 +1,191 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="render === 'bloc'" class="item-bloc">
|
<div v-if="render === 'bloc'" class="item-bloc">
|
||||||
<section class="chill-entity entity-person">
|
<section class="chill-entity entity-person">
|
||||||
<div class="item-row entity-bloc">
|
<div class="item-row entity-bloc">
|
||||||
|
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<div class="entity-label">
|
<div class="entity-label">
|
||||||
|
|
||||||
<div :class="'denomination h' + options.hLevel">
|
<div :class="'denomination h' + options.hLevel">
|
||||||
|
|
||||||
<a v-if="options.addLink === true" :href="getUrl">
|
<a v-if="options.addLink === true" :href="getUrl">
|
||||||
<!-- use person-text here to avoid code duplication ? TODO -->
|
<!-- use person-text here to avoid code duplication ? TODO -->
|
||||||
<span class="firstname">{{ person.firstName }}</span>
|
<span class="firstname">{{ person.firstName }}</span>
|
||||||
<span class="lastname">{{ person.lastName }}</span>
|
<span class="lastname">{{ person.lastName }}</span>
|
||||||
<span v-if="person.suffixText" class="suffixtext"> {{ person.suffixText }}</span>
|
<span v-if="person.suffixText" class="suffixtext"> {{ person.suffixText }}</span>
|
||||||
<span v-if="person.altNames && options.addAltNames == true" class="altnames">
|
<span v-if="person.altNames && options.addAltNames == true" class="altnames">
|
||||||
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
|
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- use person-text here to avoid code duplication ? TODO -->
|
<!-- use person-text here to avoid code duplication ? TODO -->
|
||||||
<span class="firstname">{{ person.firstName }}</span>
|
<span class="firstname">{{ person.firstName }}</span>
|
||||||
<span class="lastname">{{ person.lastName }}</span>
|
<span class="lastname">{{ person.lastName }}</span>
|
||||||
<span v-if="person.suffixText" class="suffixtext"> {{ person.suffixText }}</span>
|
<span v-if="person.suffixText" class="suffixtext"> {{ person.suffixText }}</span>
|
||||||
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
||||||
<span v-if="person.altNames && options.addAltNames == true" class="altnames">
|
<span v-if="person.altNames && options.addAltNames == true" class="altnames">
|
||||||
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
|
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="options.addId == true" class="id-number" :title="'n° ' + person.id">{{ person.id }}</span>
|
<span v-if="options.addId == true" class="id-number" :title="'n° ' + person.id">{{ person.id }}</span>
|
||||||
|
|
||||||
<badge-entity v-if="options.addEntity === true"
|
<badge-entity v-if="options.addEntity === true"
|
||||||
:entity="person"
|
:entity="person"
|
||||||
:options="{ displayLong: options.entityDisplayLong }">
|
:options="{ displayLong: options.entityDisplayLong }">
|
||||||
</badge-entity>
|
</badge-entity>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p v-if="options.addInfo === true" class="moreinfo">
|
|
||||||
<i :class="'fa fa-fw ' + getGenderIcon" :title="$t(getGender)"></i>
|
|
||||||
|
|
||||||
<time v-if="person.birthdate && !person.deathdate" :datetime="person.birthdate" :title="birthdate">
|
|
||||||
{{ $t(getGenderTranslation) + ' ' + $d(birthdate, 'text') }}
|
|
||||||
</time>
|
|
||||||
|
|
||||||
<time v-else-if="person.birthdate && person.deathdate" :datetime="person.deathdate" :title="person.deathdate">
|
|
||||||
{{ $d(birthdate) }} - {{ $d(deathdate) }}
|
|
||||||
</time>
|
|
||||||
|
|
||||||
<time v-else-if="person.deathdate" :datetime="person.deathdate" :title="person.deathdate">
|
|
||||||
{{ $t('renderbox.deathdate') + ' ' + deathdate }}
|
|
||||||
</time>
|
|
||||||
|
|
||||||
<span v-if="options.addAge && person.birthdate" class="age">{{ $tc('renderbox.years_old', person.age) }}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p v-if="options.addInfo === true" class="moreinfo">
|
||||||
|
<i :class="'fa fa-fw ' + getGenderIcon" :title="$t(getGender)"></i>
|
||||||
|
|
||||||
|
<time v-if="person.birthdate && !person.deathdate" :datetime="person.birthdate" :title="birthdate">
|
||||||
|
{{ $t(getGenderTranslation) + ' ' + $d(birthdate, 'text') }}
|
||||||
|
</time>
|
||||||
|
|
||||||
|
<time v-else-if="person.birthdate && person.deathdate" :datetime="person.deathdate"
|
||||||
|
:title="person.deathdate">
|
||||||
|
{{ $d(birthdate) }} - {{ $d(deathdate) }}
|
||||||
|
</time>
|
||||||
|
|
||||||
|
<time v-else-if="person.deathdate" :datetime="person.deathdate" :title="person.deathdate">
|
||||||
|
{{ $t('renderbox.deathdate') + ' ' + deathdate }}
|
||||||
|
</time>
|
||||||
|
|
||||||
|
<span v-if="options.addAge && person.birthdate" class="age">{{
|
||||||
|
$tc('renderbox.years_old', person.age)
|
||||||
|
}}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<div class="float-button bottom">
|
<div class="float-button bottom">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<slot name="record-actions"></slot>
|
<slot name="record-actions"></slot>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-content fa-ul">
|
<ul class="list-content fa-ul">
|
||||||
<li v-if="person.current_household_id">
|
<li v-if="person.current_household_id">
|
||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
<address-render-box v-if="person.current_household_address"
|
<address-render-box v-if="person.current_household_address"
|
||||||
:address="person.current_household_address"
|
:address="person.current_household_address"
|
||||||
:isMultiline="isMultiline">
|
:isMultiline="isMultiline">
|
||||||
</address-render-box>
|
</address-render-box>
|
||||||
<p v-else class="chill-no-data-statement">
|
<p v-else class="chill-no-data-statement">
|
||||||
{{ $t('renderbox.household_without_address') }}
|
{{ $t('renderbox.household_without_address') }}
|
||||||
</p>
|
</p>
|
||||||
<a v-if="options.addHouseholdLink === true"
|
<a v-if="options.addHouseholdLink === true"
|
||||||
:href="getCurrentHouseholdUrl"
|
:href="getCurrentHouseholdUrl"
|
||||||
:title="$t('persons_associated.show_household_number', {id: person.current_household_id})">
|
:title="$t('persons_associated.show_household_number', {id: person.current_household_id})">
|
||||||
<span class="badge rounded-pill bg-chill-beige">
|
<span class="badge rounded-pill bg-chill-beige">
|
||||||
<i class="fa fa-fw fa-home"></i><!--{{ $t('persons_associated.show_household') }}-->
|
<i class="fa fa-fw fa-home"></i><!--{{ $t('persons_associated.show_household') }}-->
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
<p class="chill-no-data-statement">
|
<p class="chill-no-data-statement">
|
||||||
{{ $t('renderbox.no_data') }}
|
{{ $t('renderbox.no_data') }}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="person.email">
|
<li v-if="person.email">
|
||||||
<i class="fa fa-li fa-envelope-o"></i>
|
<i class="fa fa-li fa-envelope-o"></i>
|
||||||
<a :href="'mailto: ' + person.email">{{ person.email }}</a>
|
<a :href="'mailto: ' + person.email">{{ person.email }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-envelope-o"></i>
|
<i class="fa fa-li fa-envelope-o"></i>
|
||||||
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="person.mobilenumber">
|
<li v-if="person.mobilenumber">
|
||||||
<i class="fa fa-li fa-mobile"></i>
|
<i class="fa fa-li fa-mobile"></i>
|
||||||
<a :href="'tel: ' + person.mobilenumber">{{ person.mobilenumber }}</a>
|
<a :href="'tel: ' + person.mobilenumber">{{ person.mobilenumber }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-mobile"></i>
|
<i class="fa fa-li fa-mobile"></i>
|
||||||
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="person.phonenumber">
|
<li v-if="person.phonenumber">
|
||||||
<i class="fa fa-li fa-phone"></i>
|
<i class="fa fa-li fa-phone"></i>
|
||||||
<a :href="'tel: ' + person.phonenumber">{{ person.phonenumber }}</a>
|
<a :href="'tel: ' + person.phonenumber">{{ person.phonenumber }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-phone"></i>
|
<i class="fa fa-li fa-phone"></i>
|
||||||
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="person.centers !== undefined && person.centers.length > 0 && options.addCenter">
|
<li v-if="person.centers !== undefined && person.centers.length > 0 && options.addCenter">
|
||||||
<i class="fa fa-li fa-long-arrow-right"></i>
|
<i class="fa fa-li fa-long-arrow-right"></i>
|
||||||
<template v-for="c in person.centers">{{ c.name }}</template>
|
<template v-for="c in person.centers">{{ c.name }}</template>
|
||||||
</li>
|
</li>
|
||||||
<li v-else-if="options.addNoData">
|
<li v-else-if="options.addNoData">
|
||||||
<i class="fa fa-li fa-long-arrow-right"></i>
|
<i class="fa fa-li fa-long-arrow-right"></i>
|
||||||
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
|
||||||
</li>
|
</li>
|
||||||
<slot name="custom-zone"></slot>
|
<slot name="custom-zone"></slot>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item-col mx-3" v-if="this.showResidentialAddresses && (person.current_residential_addresses || []).length > 0">
|
<div class="item-col mx-3"
|
||||||
<div class="float-button bottom">
|
v-if="this.showResidentialAddresses && (person.current_residential_addresses || []).length > 0">
|
||||||
<div class="box" >
|
<div class="float-button bottom">
|
||||||
<ul class="list-content fa-ul">
|
<div class="box">
|
||||||
<li v-for="(addr, i) in person.current_residential_addresses" :key="i">
|
<ul class="list-content fa-ul">
|
||||||
<i class="fa fa-li fa-map-marker"></i>
|
<li v-for="(addr, i) in person.current_residential_addresses" :key="i">
|
||||||
<div v-if="addr.address">
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
<address-render-box
|
<div v-if="addr.address">
|
||||||
:address="addr.address"
|
<address-render-box
|
||||||
:isMultiline="isMultiline">
|
:address="addr.address"
|
||||||
</address-render-box>
|
:isMultiline="isMultiline">
|
||||||
<p>({{ $t('renderbox.residential_address') }})</p>
|
</address-render-box>
|
||||||
</div>
|
<p>({{ $t('renderbox.residential_address') }})</p>
|
||||||
<div v-else-if="addr.hostPerson" class="mt-3">
|
</div>
|
||||||
<p>{{ $t('renderbox.located_at') }}:</p>
|
<div v-else-if="addr.hostPerson" class="mt-3">
|
||||||
<span class="chill-entity entity-person badge-person">
|
<p>{{ $t('renderbox.located_at') }}:</p>
|
||||||
|
<span class="chill-entity entity-person badge-person">
|
||||||
<person-text
|
<person-text
|
||||||
v-if="addr.hostPerson"
|
v-if="addr.hostPerson"
|
||||||
:person="addr.hostPerson"
|
:person="addr.hostPerson"
|
||||||
></person-text>
|
></person-text>
|
||||||
</span>
|
</span>
|
||||||
<address-render-box v-if="addr.hostPerson.address"
|
<address-render-box v-if="addr.hostPerson.address"
|
||||||
:address="addr.hostPerson.address"
|
:address="addr.hostPerson.address"
|
||||||
:isMultiline="isMultiline">
|
:isMultiline="isMultiline">
|
||||||
</address-render-box>
|
</address-render-box>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="addr.hostThirdParty" class="mt-3">
|
<div v-else-if="addr.hostThirdParty" class="mt-3">
|
||||||
<p>{{ $t('renderbox.located_at') }}:</p>
|
<p>{{ $t('renderbox.located_at') }}:</p>
|
||||||
<span class="chill-entity entity-person badge-thirdparty">
|
<span class="chill-entity entity-person badge-thirdparty">
|
||||||
<third-party-text
|
<third-party-text
|
||||||
v-if="addr.hostThirdParty"
|
v-if="addr.hostThirdParty"
|
||||||
:thirdparty="addr.hostThirdParty"
|
:thirdparty="addr.hostThirdParty"
|
||||||
></third-party-text>
|
></third-party-text>
|
||||||
</span>
|
</span>
|
||||||
<address-render-box v-if="addr.hostThirdParty.address"
|
<address-render-box v-if="addr.hostThirdParty.address"
|
||||||
:address="addr.hostThirdParty.address"
|
:address="addr.hostThirdParty.address"
|
||||||
:isMultiline="isMultiline">
|
:isMultiline="isMultiline">
|
||||||
</address-render-box>
|
</address-render-box>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<slot name="end-bloc"></slot>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span v-if="render === 'badge'" class="chill-entity entity-person badge-person">
|
<span v-if="render === 'badge'" class="chill-entity entity-person badge-person">
|
||||||
<a v-if="options.addLink === true" :href="getUrl">
|
<a v-if="options.addLink === true" :href="getUrl">
|
||||||
<span v-if="options.isHolder" class="fa-stack fa-holder" :title="$t('renderbox.holder')">
|
<span v-if="options.isHolder" class="fa-stack fa-holder" :title="$t('renderbox.holder')">
|
||||||
<i class="fa fa-circle fa-stack-1x text-success"></i>
|
<i class="fa fa-circle fa-stack-1x text-success"></i>
|
||||||
@ -206,111 +213,119 @@ import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
|||||||
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
||||||
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
|
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
|
||||||
import ThirdPartyText from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyText.vue';
|
import ThirdPartyText from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyText.vue';
|
||||||
|
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PersonRenderBox",
|
name: "PersonRenderBox",
|
||||||
components: {
|
components: {
|
||||||
AddressRenderBox,
|
AddressRenderBox,
|
||||||
Confidential,
|
Confidential,
|
||||||
BadgeEntity,
|
BadgeEntity,
|
||||||
PersonText,
|
PersonText,
|
||||||
ThirdPartyText
|
ThirdPartyText
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
person: {
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
props: {
|
options: {
|
||||||
person: {
|
type: Object,
|
||||||
required: true,
|
required: false,
|
||||||
},
|
},
|
||||||
options: {
|
render: {
|
||||||
type: Object,
|
type: String,
|
||||||
required: false,
|
},
|
||||||
},
|
returnPath: {
|
||||||
render: {
|
type: String,
|
||||||
type: String,
|
},
|
||||||
},
|
showResidentialAddresses: {
|
||||||
returnPath: {
|
type: Boolean,
|
||||||
type: String,
|
default: false,
|
||||||
},
|
}
|
||||||
showResidentialAddresses: {
|
},
|
||||||
type: Boolean,
|
computed: {
|
||||||
default: false,
|
isMultiline: function () {
|
||||||
|
if (this.options.isMultiline) {
|
||||||
|
return this.options.isMultiline
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
getGenderIcon: function () {
|
||||||
isMultiline: function() {
|
return this.person.gender === 'woman' ? 'fa-venus' : this.person.gender === 'man' ? 'fa-mars' : this.person.gender === 'neuter' ? 'fa-neuter' : 'fa-genderless';
|
||||||
if(this.options.isMultiline){
|
},
|
||||||
return this.options.isMultiline
|
getGenderTranslation: function () {
|
||||||
} else {
|
return this.person.gender === 'woman' ? 'renderbox.birthday.woman' : 'renderbox.birthday.man';
|
||||||
return false
|
},
|
||||||
}
|
getGender() {
|
||||||
},
|
return this.person.gender === 'woman' ? 'person.gender.woman' : this.person.gender === 'man' ? 'person.gender.man' : this.person.gender === 'neuter' ? 'person.gender.neuter' : 'person.gender.undefined';
|
||||||
getGenderIcon: function() {
|
},
|
||||||
return this.person.gender === 'woman' ? 'fa-venus' : this.person.gender === 'man' ? 'fa-mars' : this.person.gender === 'neuter' ? 'fa-neuter' : 'fa-genderless';
|
birthdate: function () {
|
||||||
},
|
if (this.person.birthdate !== null || this.person.birthdate === "undefined") {
|
||||||
getGenderTranslation: function() {
|
return new Date(this.person.birthdate.datetime);
|
||||||
return this.person.gender === 'woman' ? 'renderbox.birthday.woman' : 'renderbox.birthday.man';
|
} else {
|
||||||
},
|
return "";
|
||||||
getGender() {
|
}
|
||||||
return this.person.gender === 'woman' ? 'person.gender.woman' : this.person.gender === 'man' ? 'person.gender.man' : this.person.gender === 'neuter' ? 'person.gender.neuter' : 'person.gender.undefined';
|
},
|
||||||
},
|
deathdate: function () {
|
||||||
birthdate: function(){
|
if (this.person.deathdate !== null || this.person.birthdate === "undefined") {
|
||||||
if(this.person.birthdate !== null || this.person.birthdate === "undefined"){
|
return new Date(this.person.deathdate.datetime);
|
||||||
return new Date(this.person.birthdate.datetime);
|
} else {
|
||||||
} else {
|
return "";
|
||||||
return "";
|
}
|
||||||
}
|
},
|
||||||
},
|
altNameLabel: function () {
|
||||||
deathdate: function(){
|
for (let i = 0; i < this.person.altNames.length; i++) {
|
||||||
if(this.person.deathdate !== null || this.person.birthdate === "undefined"){
|
return this.person.altNames[i].label
|
||||||
return new Date(this.person.deathdate.datetime);
|
}
|
||||||
} else {
|
},
|
||||||
return "";
|
altNameKey: function () {
|
||||||
}
|
for (let i = 0; i < this.person.altNames.length; i++) {
|
||||||
},
|
return this.person.altNames[i].key
|
||||||
altNameLabel: function() {
|
}
|
||||||
for(let i = 0; i < this.person.altNames.length; i++){
|
},
|
||||||
return this.person.altNames[i].label
|
getUrl: function () {
|
||||||
}
|
return `/fr/person/${this.person.id}/general`;
|
||||||
},
|
},
|
||||||
altNameKey: function() {
|
getCurrentHouseholdUrl: function () {
|
||||||
for(let i = 0; i < this.person.altNames.length; i++){
|
let returnPath = this.returnPath ? `?returnPath=${this.returnPath}` : ``;
|
||||||
return this.person.altNames[i].key
|
return `/fr/person/household/${this.person.current_household_id}/summary${returnPath}`
|
||||||
}
|
|
||||||
},
|
|
||||||
getUrl: function() {
|
|
||||||
return `/fr/person/${this.person.id}/general`;
|
|
||||||
},
|
|
||||||
getCurrentHouseholdUrl: function() {
|
|
||||||
let returnPath = this.returnPath ? `?returnPath=${this.returnPath}` : ``;
|
|
||||||
return `/fr/person/household/${this.person.current_household_id}/summary${returnPath}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='scss'>
|
<style lang='scss'>
|
||||||
|
|
||||||
.lastname:before{
|
.lastname:before {
|
||||||
content: " "
|
content: " "
|
||||||
}
|
}
|
||||||
|
|
||||||
div.flex-table {
|
div.flex-table {
|
||||||
div.item-bloc {
|
div.item-bloc {
|
||||||
div.item-row {
|
div.item-row {
|
||||||
div.item-col:first-child {
|
div.item-col:first-child {
|
||||||
width: 33%;
|
width: 33%;
|
||||||
}
|
|
||||||
div.item-col:last-child {
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
div.item-col:last-child {
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.age{
|
.age {
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
&:before { content: '('; }
|
|
||||||
&:after { content: ')'; }
|
&:before {
|
||||||
|
content: '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -110,6 +110,12 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: chill.export_filter, alias: person_geog_filter }
|
- { name: chill.export_filter, alias: person_geog_filter }
|
||||||
|
|
||||||
|
Chill\PersonBundle\Export\Filter\PersonFilters\AddressRefStatusFilter:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
tags:
|
||||||
|
- { name: chill.export_filter, alias: person_address_ref_status_filter }
|
||||||
|
|
||||||
Chill\PersonBundle\Export\Filter\PersonFilters\ByHouseholdCompositionFilter:
|
Chill\PersonBundle\Export\Filter\PersonFilters\ByHouseholdCompositionFilter:
|
||||||
tags:
|
tags:
|
||||||
- { name: chill.export_filter, alias: person_by_household_composition_filter }
|
- { name: chill.export_filter, alias: person_by_household_composition_filter }
|
||||||
|
@ -1062,6 +1062,13 @@ export:
|
|||||||
Filter persons without household composition: Filtrer les usagers sans composition de ménage (ni ménage)
|
Filter persons without household composition: Filtrer les usagers sans composition de ménage (ni ménage)
|
||||||
Persons filtered by no composition at %date%: Uniquement les usagers sans composition de ménage à la date du %date%
|
Persons filtered by no composition at %date%: Uniquement les usagers sans composition de ménage à la date du %date%
|
||||||
Date calc: Date de calcul
|
Date calc: Date de calcul
|
||||||
|
by_address_ref_status:
|
||||||
|
Filter by person's address ref status: Filtrer par comparaison avec l'adresse de référence
|
||||||
|
to_review: Diffère de l'adresse de référence
|
||||||
|
reviewed: Diffère de l'adresse de référence mais conservé par l'utilisateur
|
||||||
|
match: Identique à l'adresse de référence
|
||||||
|
Filtered by person\'s address status computed at %datecalc%, only %statuses%: Filtré par comparaison à l'adresse de référence, calculé à %datecalc%, seulement %statuses%
|
||||||
|
Status: Statut
|
||||||
|
|
||||||
course:
|
course:
|
||||||
by_user_scope:
|
by_user_scope:
|
||||||
|
@ -1,100 +1,100 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="item-bloc col">
|
<div class="item-bloc col">
|
||||||
<section class="chill-entity entity-thirdparty">
|
<section class="chill-entity entity-thirdparty">
|
||||||
<div class="item-row entity-bloc">
|
<div class="item-row entity-bloc">
|
||||||
|
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<div class="entity-label">
|
<div class="entity-label">
|
||||||
<div :class="'denomination h' + options.hLevel">
|
<div :class="'denomination h' + options.hLevel">
|
||||||
|
|
||||||
<a v-if="this.options.addLink === true" href="#">
|
<a v-if="this.options.addLink === true" href="#">
|
||||||
<span class="name">{{ thirdparty.text }}</span>
|
<span class="name">{{ thirdparty.text }}</span>
|
||||||
</a>
|
</a>
|
||||||
<span class="name" v-else>{{ thirdparty.text }}</span>
|
<span class="name" v-else>{{ thirdparty.text }}</span>
|
||||||
|
|
||||||
<span v-if="options.addId === true" class="id-number" :title="'n° ' + thirdparty.id">
|
<span v-if="options.addId === true" class="id-number" :title="'n° ' + thirdparty.id">
|
||||||
{{ thirdparty.id }}
|
{{ thirdparty.id }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<badge-entity v-if="options.addEntity === true"
|
<badge-entity v-if="options.addEntity === true"
|
||||||
:entity="thirdparty"
|
:entity="thirdparty"
|
||||||
:options="{ displayLong: options.entityDisplayLong }">
|
:options="{ displayLong: options.entityDisplayLong }">
|
||||||
</badge-entity>
|
</badge-entity>
|
||||||
</div>
|
|
||||||
|
|
||||||
<p v-if="this.options.addInfo === true" class="moreinfo">
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p v-if="this.options.addInfo === true" class="moreinfo">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<div class="float-button bottom">
|
<div class="float-button bottom">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<slot name="record-actions"></slot>
|
<slot name="record-actions"></slot>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-content fa-ul">
|
<ul class="list-content fa-ul">
|
||||||
<li v-if="getProfession.length > 0">
|
<li v-if="getProfession.length > 0">
|
||||||
<i class="fa fa-li fa-id-card"></i>
|
<i class="fa fa-li fa-id-card"></i>
|
||||||
<p><span>{{ getProfession[0] }}</span></p>
|
<p><span>{{ getProfession[0] }}</span></p>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="hasParent">
|
<li v-if="hasParent">
|
||||||
<i class="fa fa-li fa-hand-o-right"></i>
|
<i class="fa fa-li fa-hand-o-right"></i>
|
||||||
<b class="me-2">{{ $t('child_of') }}</b>
|
<b class="me-2">{{ $t('child_of') }}</b>
|
||||||
<on-the-fly
|
<on-the-fly
|
||||||
:type="thirdparty.parent.type"
|
:type="thirdparty.parent.type"
|
||||||
:id="thirdparty.parent.id"
|
:id="thirdparty.parent.id"
|
||||||
:buttonText="thirdparty.parent.text"
|
:buttonText="thirdparty.parent.text"
|
||||||
:displayBadge="'true' === 'true'"
|
:displayBadge="'true' === 'true'"
|
||||||
action="show">
|
action="show">
|
||||||
</on-the-fly>
|
</on-the-fly>
|
||||||
</li>
|
</li>
|
||||||
<!-- TODO hasChildren
|
<!-- TODO hasChildren
|
||||||
NB: we cannot call on-the-fly from RenderBox. See error message in previous version of this file.
|
NB: we cannot call on-the-fly from RenderBox. See error message in previous version of this file.
|
||||||
-->
|
-->
|
||||||
</ul>
|
</ul>
|
||||||
<div v-if="thirdparty.contactDataAnonymous">
|
<div v-if="thirdparty.contactDataAnonymous">
|
||||||
<confidential :positionBtnFar="false">
|
<confidential :positionBtnFar="false">
|
||||||
<template v-slot:confidential-content>
|
<template v-slot:confidential-content>
|
||||||
<ul class="list-content fa-ul">
|
<ul class="list-content fa-ul">
|
||||||
<li v-if="thirdparty.address">
|
<li v-if="thirdparty.address">
|
||||||
<i class="fa fa-li fa-map-marker"></i>
|
|
||||||
<address-render-box :address="thirdparty.address" :isMultiline="isMultiline"></address-render-box>
|
|
||||||
</li>
|
|
||||||
<li v-if="thirdparty.telephone">
|
|
||||||
<i class="fa fa-li fa-mobile"></i>
|
|
||||||
<a :href="'tel: ' + thirdparty.telephone">{{ thirdparty.telephone }}</a>
|
|
||||||
</li>
|
|
||||||
<li v-if="thirdparty.email">
|
|
||||||
<i class="fa fa-li fa-envelope-o"></i>
|
|
||||||
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</confidential>
|
|
||||||
</div>
|
|
||||||
<ul v-else class="list-content fa-ul">
|
|
||||||
<li v-if="thirdparty.address">
|
|
||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
<address-render-box :address="thirdparty.address" :isMultiline="isMultiline"></address-render-box>
|
<address-render-box :address="thirdparty.address"
|
||||||
</li>
|
:isMultiline="isMultiline"></address-render-box>
|
||||||
<li v-if="thirdparty.telephone">
|
</li>
|
||||||
|
<li v-if="thirdparty.telephone">
|
||||||
<i class="fa fa-li fa-mobile"></i>
|
<i class="fa fa-li fa-mobile"></i>
|
||||||
<a :href="'tel: ' + thirdparty.telephone">{{ thirdparty.telephone }}</a>
|
<a :href="'tel: ' + thirdparty.telephone">{{ thirdparty.telephone }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="thirdparty.email">
|
<li v-if="thirdparty.email">
|
||||||
<i class="fa fa-li fa-envelope-o"></i>
|
<i class="fa fa-li fa-envelope-o"></i>
|
||||||
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
|
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</template>
|
||||||
|
</confidential>
|
||||||
|
</div>
|
||||||
|
<ul v-else class="list-content fa-ul">
|
||||||
|
<li v-if="thirdparty.address">
|
||||||
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
|
<address-render-box :address="thirdparty.address" :isMultiline="isMultiline"></address-render-box>
|
||||||
|
</li>
|
||||||
|
<li v-if="thirdparty.telephone">
|
||||||
|
<i class="fa fa-li fa-mobile"></i>
|
||||||
|
<a :href="'tel: ' + thirdparty.telephone">{{ thirdparty.telephone }}</a>
|
||||||
|
</li>
|
||||||
|
<li v-if="thirdparty.email">
|
||||||
|
<i class="fa fa-li fa-envelope-o"></i>
|
||||||
|
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<slot name="end-bloc"></slot>
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -104,75 +104,78 @@ import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
|||||||
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ThirdPartyRenderBox",
|
name: "ThirdPartyRenderBox",
|
||||||
components: {
|
components: {
|
||||||
AddressRenderBox,
|
AddressRenderBox,
|
||||||
Confidential,
|
Confidential,
|
||||||
BadgeEntity,
|
BadgeEntity,
|
||||||
},
|
},
|
||||||
// To avoid components recursively invoking eachother resolve OnTheFly component here
|
// To avoid components recursively invoking eachother resolve OnTheFly component here
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
this.$options.components.OnTheFly = require('ChillMainAssets/vuejs/OnTheFly/components/OnTheFly').default;
|
this.$options.components.OnTheFly = require('ChillMainAssets/vuejs/OnTheFly/components/OnTheFly').default;
|
||||||
},
|
},
|
||||||
i18n: {
|
i18n: {
|
||||||
messages: {
|
messages: {
|
||||||
fr: {
|
fr: {
|
||||||
children: "Personnes de contact: ",
|
children: "Personnes de contact: ",
|
||||||
child_of: "Contact de: ",
|
child_of: "Contact de: ",
|
||||||
}}
|
}
|
||||||
},
|
|
||||||
props: ['thirdparty', 'options'],
|
|
||||||
computed: {
|
|
||||||
isMultiline: function() {
|
|
||||||
if (this.options.isMultiline){
|
|
||||||
return this.options.isMultiline
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasParent() {
|
|
||||||
return !(this.thirdparty.parent === null || this.thirdparty.parent === undefined);
|
|
||||||
},
|
|
||||||
getProfession() {
|
|
||||||
let profession = []
|
|
||||||
if (this.hasParent && this.thirdparty.profession) {
|
|
||||||
profession.push(this.thirdparty.profession)
|
|
||||||
return profession;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.hasParent && this.thirdparty.category) {
|
|
||||||
profession = this.thirdparty.category.map((category) => category.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return profession;
|
|
||||||
}
|
|
||||||
/* TODO need backend normalizer to serve children without circular reference
|
|
||||||
hasChildren() {
|
|
||||||
//console.log(this.thirdparty.activeChildren.length > 0)
|
|
||||||
return false
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
props: ['thirdparty', 'options'],
|
||||||
|
computed: {
|
||||||
|
isMultiline: function () {
|
||||||
|
if (this.options.isMultiline) {
|
||||||
|
return this.options.isMultiline
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hasParent() {
|
||||||
|
return !(this.thirdparty.parent === null || this.thirdparty.parent === undefined);
|
||||||
|
},
|
||||||
|
getProfession() {
|
||||||
|
let profession = []
|
||||||
|
if (this.hasParent && this.thirdparty.profession) {
|
||||||
|
profession.push(this.thirdparty.profession)
|
||||||
|
return profession;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hasParent && this.thirdparty.category) {
|
||||||
|
profession = this.thirdparty.category.map((category) => category.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return profession;
|
||||||
|
}
|
||||||
|
/* TODO need backend normalizer to serve children without circular reference
|
||||||
|
hasChildren() {
|
||||||
|
//console.log(this.thirdparty.activeChildren.length > 0)
|
||||||
|
return false
|
||||||
|
} */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.name{
|
.name {
|
||||||
&:before{
|
&:before {
|
||||||
content: " "
|
content: " "
|
||||||
}
|
}
|
||||||
&.tparty-parent {
|
|
||||||
font-weight: bold;
|
&.tparty-parent {
|
||||||
font-variant: all-small-caps;
|
font-weight: bold;
|
||||||
}
|
font-variant: all-small-caps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-professions {
|
.list-professions {
|
||||||
&::after {
|
&::after {
|
||||||
content: " | ";
|
content: " | ";
|
||||||
}
|
}
|
||||||
&:last-child::after {
|
|
||||||
content: ""
|
&:last-child::after {
|
||||||
}
|
content: ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
4
src/Bundle/import-png.d.ts
vendored
Normal file
4
src/Bundle/import-png.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module "*.png" {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user