mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'issue23_addresses' into 'master'
Issue23 addresses See merge request Chill-Projet/chill-bundles!12
This commit is contained in:
commit
3f562449e1
63
src/Bundle/ChillMainBundle/Controller/AddressController.php
Normal file
63
src/Bundle/ChillMainBundle/Controller/AddressController.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Controller;
|
||||
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\AddressReference;
|
||||
|
||||
/**
|
||||
* Class AddressController
|
||||
*
|
||||
* @package Chill\MainBundle\Controller
|
||||
*/
|
||||
class AddressController extends AbstractController
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Get API Data for showing endpoint
|
||||
*
|
||||
* @Route(
|
||||
* "/{_locale}/main/api/1.0/address/{address_id}/show.{_format}",
|
||||
* name="chill_main_address_api_show"
|
||||
* )
|
||||
* @ParamConverter("address", options={"id": "address_id"})
|
||||
*/
|
||||
public function showAddress(Address $address, $_format): Response
|
||||
{
|
||||
// TODO check ACL ?
|
||||
switch ($_format) {
|
||||
case 'json':
|
||||
return $this->json($address);
|
||||
default:
|
||||
throw new BadRequestException('Unsupported format');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get API Data for showing endpoint
|
||||
*
|
||||
* @Route(
|
||||
* "/{_locale}/main/api/1.0/address-reference/{address_reference_id}/show.{_format}",
|
||||
* name="chill_main_address_reference_api_show"
|
||||
* )
|
||||
* @ParamConverter("addressReference", options={"id": "address_reference_id"})
|
||||
*/
|
||||
public function showAddressReference(AddressReference $addressReference, $_format): Response
|
||||
{
|
||||
// TODO check ACL ?
|
||||
switch ($_format) {
|
||||
case 'json':
|
||||
return $this->json($addressReference);
|
||||
default:
|
||||
throw new BadRequestException('Unsupported format');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes;
|
||||
use Chill\MainBundle\Entity\AddressReference;
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
|
||||
/**
|
||||
* Load reference addresses into database
|
||||
*
|
||||
* @author Champs Libres
|
||||
*/
|
||||
class LoadAddressReferences extends AbstractFixture implements ContainerAwareInterface, OrderedFixtureInterface {
|
||||
|
||||
|
||||
protected $faker;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->faker = \Faker\Factory::create('fr_FR');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function getOrder() {
|
||||
return 51;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a random point
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
private function getRandomPoint()
|
||||
{
|
||||
$lonBrussels = 4.35243;
|
||||
$latBrussels = 50.84676;
|
||||
$lon = $lonBrussels + 0.01 * rand(-5, 5);
|
||||
$lat = $latBrussels + 0.01 * rand(-5, 5);
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random reference address
|
||||
*
|
||||
* @return AddressReference
|
||||
*/
|
||||
private function getRandomAddressReference()
|
||||
{
|
||||
$ar= new AddressReference();
|
||||
|
||||
$ar->setRefId($this->faker->numerify('ref-id-######'));
|
||||
$ar->setStreet($this->faker->streetName);
|
||||
$ar->setStreetNumber(rand(0,199));
|
||||
$ar ->setPoint($this->getRandomPoint());
|
||||
$ar->setPostcode($this->getReference(
|
||||
LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)]
|
||||
));
|
||||
|
||||
$ar->setMunicipalityCode($ar->getPostcode()->getCode());
|
||||
|
||||
return $ar
|
||||
;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager) {
|
||||
|
||||
echo "loading some reference address... \n";
|
||||
|
||||
for ($i=0; $i<10; $i++) {
|
||||
$ar = $this->getRandomAddressReference();
|
||||
$manager->persist($ar);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -188,7 +188,12 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
|
||||
$container->prependExtensionConfig('doctrine', array(
|
||||
'dbal' => [
|
||||
'types' => [
|
||||
'dateinterval' => \Chill\MainBundle\Doctrine\Type\NativeDateIntervalType::class
|
||||
'dateinterval' => [
|
||||
'class' => \Chill\MainBundle\Doctrine\Type\NativeDateIntervalType::class
|
||||
],
|
||||
'point' => [
|
||||
'class' => \Chill\MainBundle\Doctrine\Type\PointType::class
|
||||
]
|
||||
]
|
||||
]
|
||||
));
|
||||
|
103
src/Bundle/ChillMainBundle/Doctrine/Model/Point.php
Normal file
103
src/Bundle/ChillMainBundle/Doctrine/Model/Point.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Doctrine\Model;
|
||||
|
||||
use \JsonSerializable;
|
||||
|
||||
/**
|
||||
* Description of Point
|
||||
*
|
||||
*/
|
||||
class Point implements JsonSerializable {
|
||||
private float $lat;
|
||||
private float $lon;
|
||||
public static string $SRID = '4326';
|
||||
|
||||
private function __construct(float $lon, float $lat)
|
||||
{
|
||||
$this->lat = $lat;
|
||||
$this->lon = $lon;
|
||||
}
|
||||
|
||||
public function toGeoJson(): string
|
||||
{
|
||||
$array = $this->toArrayGeoJson();
|
||||
return \json_encode($array);
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->toArrayGeoJson();
|
||||
}
|
||||
|
||||
public function toArrayGeoJson(): array
|
||||
{
|
||||
return [
|
||||
"type" => "Point",
|
||||
"coordinates" => [ $this->lon, $this->lat ]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toWKT(): string
|
||||
{
|
||||
return 'SRID='.self::$SRID.';POINT('.$this->lon.' '.$this->lat.')';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $geojson
|
||||
* @return Point
|
||||
*/
|
||||
public static function fromGeoJson(string $geojson): Point
|
||||
{
|
||||
$a = json_decode($geojson);
|
||||
//check if the geojson string is correct
|
||||
if (NULL === $a or !isset($a->type) or !isset($a->coordinates)){
|
||||
throw PointException::badJsonString($geojson);
|
||||
}
|
||||
|
||||
if ($a->type != 'Point'){
|
||||
throw PointException::badGeoType();
|
||||
}
|
||||
|
||||
$lat = $a->coordinates[1];
|
||||
$lon = $a->coordinates[0];
|
||||
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
public static function fromLonLat(float $lon, float $lat): Point
|
||||
{
|
||||
if (($lon > -180 && $lon < 180) && ($lat > -90 && $lat < 90))
|
||||
{
|
||||
return new Point($lon, $lat);
|
||||
} else {
|
||||
throw PointException::badCoordinates($lon, $lat);
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromArrayGeoJson(array $array): Point
|
||||
{
|
||||
if ($array['type'] == 'Point' &&
|
||||
isset($array['coordinates']))
|
||||
{
|
||||
return self::fromLonLat($array['coordinates'][0], $array['coordinates'][1]);
|
||||
}
|
||||
}
|
||||
|
||||
public function getLat(): float
|
||||
{
|
||||
return $this->lat;
|
||||
}
|
||||
|
||||
public function getLon(): float
|
||||
{
|
||||
return $this->lon;
|
||||
}
|
||||
}
|
||||
|
||||
|
27
src/Bundle/ChillMainBundle/Doctrine/Model/PointException.php
Normal file
27
src/Bundle/ChillMainBundle/Doctrine/Model/PointException.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Doctrine\Model;
|
||||
|
||||
use \Exception;
|
||||
|
||||
/**
|
||||
* Description of PointException
|
||||
*
|
||||
*/
|
||||
class PointException extends Exception {
|
||||
|
||||
public static function badCoordinates($lon, $lat): self
|
||||
{
|
||||
return new self("Input coordinates are not valid in the used coordinate system (longitude = $lon , latitude = $lat)");
|
||||
}
|
||||
|
||||
public static function badJsonString($str): self
|
||||
{
|
||||
return new self("The JSON string is not valid: $str");
|
||||
}
|
||||
|
||||
public static function badGeoType(): self
|
||||
{
|
||||
return new self("The geoJSON object type is not valid");
|
||||
}
|
||||
}
|
75
src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php
Normal file
75
src/Bundle/ChillMainBundle/Doctrine/Type/PointType.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Doctrine\Type;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Chill\MainBundle\Doctrine\Model\PointException;
|
||||
|
||||
|
||||
/**
|
||||
* A Type for Doctrine to implement the Geography Point type
|
||||
* implemented by Postgis on postgis+postgresql databases
|
||||
*
|
||||
*/
|
||||
class PointType extends Type {
|
||||
|
||||
const POINT = 'point';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $fieldDeclaration
|
||||
* @param AbstractPlatform $platform
|
||||
* @return type
|
||||
*/
|
||||
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||
{
|
||||
return 'geometry(POINT,'.Point::$SRID.')';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $value
|
||||
* @param AbstractPlatform $platform
|
||||
* @return Point
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
if ($value === NULL){
|
||||
return NULL;
|
||||
} else {
|
||||
return Point::fromGeoJson($value);
|
||||
}
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return self::POINT;
|
||||
}
|
||||
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
if ($value === NULL){
|
||||
return NULL;
|
||||
} else {
|
||||
return $value->toWKT();
|
||||
}
|
||||
}
|
||||
|
||||
public function canRequireSQLConversion()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function convertToPHPValueSQL($sqlExpr, $platform)
|
||||
{
|
||||
return 'ST_AsGeoJSON('.$sqlExpr.') ';
|
||||
}
|
||||
|
||||
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
|
||||
{
|
||||
return $sqlExpr;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ namespace Chill\MainBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
|
||||
/**
|
||||
* Address
|
||||
@ -28,14 +30,14 @@ class Address
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $streetAddress1 = '';
|
||||
private $street = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $streetAddress2 = '';
|
||||
private $streetNumber = '';
|
||||
|
||||
/**
|
||||
* @var PostalCode
|
||||
@ -43,7 +45,56 @@ class Address
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||
*/
|
||||
private $postcode;
|
||||
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=16, nullable=true)
|
||||
*/
|
||||
private $floor;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=16, nullable=true)
|
||||
*/
|
||||
private $corridor;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=16, nullable=true)
|
||||
*/
|
||||
private $steps;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $buildingName;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=16, nullable=true)
|
||||
*/
|
||||
private $flat;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $distribution;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $extra;
|
||||
|
||||
/**
|
||||
* Indicates when the address starts validation. Used to build an history
|
||||
* of address. By default, the current date.
|
||||
@ -53,27 +104,55 @@ class Address
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
private $validFrom;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates when the address ends. Used to build an history
|
||||
* of address.
|
||||
*
|
||||
* @var \DateTime|null
|
||||
*
|
||||
* @ORM\Column(type="date", nullable=true)
|
||||
*/
|
||||
private $validTo;
|
||||
|
||||
/**
|
||||
* True if the address is a "no address", aka homeless person, ...
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isNoAddress = false;
|
||||
|
||||
|
||||
/**
|
||||
* A geospatial field storing the coordinates of the Address
|
||||
*
|
||||
* @var Point|null
|
||||
*
|
||||
* @ORM\Column(type="point", nullable=true)
|
||||
*/
|
||||
private $point;
|
||||
|
||||
/**
|
||||
* A ThirdParty reference for person's addresses that are linked to a third party
|
||||
*
|
||||
* @var ThirdParty|null
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $linkedToThirdParty;
|
||||
|
||||
/**
|
||||
* A list of metadata, added by customizable fields
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $customs = [];
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->validFrom = new \DateTime();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
@ -85,7 +164,7 @@ class Address
|
||||
}
|
||||
|
||||
/**
|
||||
* Set streetAddress1
|
||||
* Set streetAddress1 (legacy function)
|
||||
*
|
||||
* @param string $streetAddress1
|
||||
*
|
||||
@ -93,23 +172,23 @@ class Address
|
||||
*/
|
||||
public function setStreetAddress1($streetAddress1)
|
||||
{
|
||||
$this->streetAddress1 = $streetAddress1 === NULL ? '' : $streetAddress1;
|
||||
$this->street = $streetAddress1 === NULL ? '' : $streetAddress1;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get streetAddress1
|
||||
* Get streetAddress1 (legacy function)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStreetAddress1()
|
||||
{
|
||||
return $this->streetAddress1;
|
||||
return $this->street;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set streetAddress2
|
||||
* Set streetAddress2 (legacy function)
|
||||
*
|
||||
* @param string $streetAddress2
|
||||
*
|
||||
@ -117,19 +196,19 @@ class Address
|
||||
*/
|
||||
public function setStreetAddress2($streetAddress2)
|
||||
{
|
||||
$this->streetAddress2 = $streetAddress2 === NULL ? '' : $streetAddress2;
|
||||
$this->streetNumber = $streetAddress2 === NULL ? '' : $streetAddress2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get streetAddress2
|
||||
* Get streetAddress2 (legacy function)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getStreetAddress2()
|
||||
{
|
||||
return $this->streetAddress2;
|
||||
return $this->streetNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,7 +234,7 @@ class Address
|
||||
{
|
||||
return $this->postcode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
@ -173,19 +252,19 @@ class Address
|
||||
$this->validFrom = $validFrom;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get IsNoAddress
|
||||
*
|
||||
*
|
||||
* Indicate true if the address is a fake address (homeless, ...)
|
||||
*
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsNoAddress(): bool
|
||||
{
|
||||
return $this->isNoAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -196,9 +275,9 @@ class Address
|
||||
|
||||
/**
|
||||
* Set IsNoAddress
|
||||
*
|
||||
*
|
||||
* Indicate true if the address is a fake address (homeless, ...)
|
||||
*
|
||||
*
|
||||
* @param bool $isNoAddress
|
||||
* @return $this
|
||||
*/
|
||||
@ -207,10 +286,10 @@ class Address
|
||||
$this->isNoAddress = $isNoAddress;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get customs informations in the address
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCustoms(): array
|
||||
@ -220,27 +299,27 @@ class Address
|
||||
|
||||
/**
|
||||
* Store custom informations in the address
|
||||
*
|
||||
*
|
||||
* @param array $customs
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustoms(array $customs): self
|
||||
{
|
||||
$this->customs = $customs;
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the address.
|
||||
*
|
||||
*
|
||||
* Check that:
|
||||
*
|
||||
*
|
||||
* * if the address is not home address:
|
||||
* * the postal code is present
|
||||
* * the valid from is not null
|
||||
* * the address street 1 is greater than 2
|
||||
*
|
||||
*
|
||||
* @param ExecutionContextInterface $context
|
||||
* @param array $payload
|
||||
*/
|
||||
@ -252,18 +331,18 @@ class Address
|
||||
->atPath('validFrom')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
|
||||
if ($this->isNoAddress()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (empty($this->getStreetAddress1())) {
|
||||
$context
|
||||
->buildViolation("address.street1-should-be-set")
|
||||
->atPath('streetAddress1')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
|
||||
if (!$this->getPostcode() instanceof PostalCode) {
|
||||
$context
|
||||
->buildViolation("address.postcode-should-be-set")
|
||||
@ -271,7 +350,7 @@ class Address
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Address $original
|
||||
* @return Address
|
||||
@ -286,5 +365,149 @@ class Address
|
||||
;
|
||||
}
|
||||
|
||||
public function getStreet(): ?string
|
||||
{
|
||||
return $this->street;
|
||||
}
|
||||
|
||||
public function setStreet(string $street): self
|
||||
{
|
||||
$this->street = $street;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStreetNumber(): ?string
|
||||
{
|
||||
return $this->streetNumber;
|
||||
}
|
||||
|
||||
public function setStreetNumber(string $streetNumber): self
|
||||
{
|
||||
$this->streetNumber = $streetNumber;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFloor(): ?string
|
||||
{
|
||||
return $this->floor;
|
||||
}
|
||||
|
||||
public function setFloor(?string $floor): self
|
||||
{
|
||||
$this->floor = $floor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCorridor(): ?string
|
||||
{
|
||||
return $this->corridor;
|
||||
}
|
||||
|
||||
public function setCorridor(?string $corridor): self
|
||||
{
|
||||
$this->corridor = $corridor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSteps(): ?string
|
||||
{
|
||||
return $this->steps;
|
||||
}
|
||||
|
||||
public function setSteps(?string $steps): self
|
||||
{
|
||||
$this->steps = $steps;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBuildingName(): ?string
|
||||
{
|
||||
return $this->buildingName;
|
||||
}
|
||||
|
||||
public function setBuildingName(?string $buildingName): self
|
||||
{
|
||||
$this->buildingName = $buildingName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFlat(): ?string
|
||||
{
|
||||
return $this->flat;
|
||||
}
|
||||
|
||||
public function setFlat(?string $flat): self
|
||||
{
|
||||
$this->flat = $flat;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDistribution(): ?string
|
||||
{
|
||||
return $this->distribution;
|
||||
}
|
||||
|
||||
public function setDistribution(?string $distribution): self
|
||||
{
|
||||
$this->distribution = $distribution;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExtra(): ?string
|
||||
{
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
public function setExtra(?string $extra): self
|
||||
{
|
||||
$this->extra = $extra;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValidTo(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->validTo;
|
||||
}
|
||||
|
||||
public function setValidTo(\DateTimeInterface $validTo): self
|
||||
{
|
||||
$this->validTo = $validTo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoint(): ?Point
|
||||
{
|
||||
return $this->point;
|
||||
}
|
||||
|
||||
public function setPoint(?Point $point): self
|
||||
{
|
||||
$this->point = $point;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLinkedToThirdParty()
|
||||
{
|
||||
return $this->linkedToThirdParty;
|
||||
}
|
||||
|
||||
public function setLinkedToThirdParty($linkedToThirdParty): self
|
||||
{
|
||||
$this->linkedToThirdParty = $linkedToThirdParty;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
165
src/Bundle/ChillMainBundle/Entity/AddressReference.php
Normal file
165
src/Bundle/ChillMainBundle/Entity/AddressReference.php
Normal file
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Entity;
|
||||
|
||||
use Chill\MainBundle\Entity\AddressReferenceRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=AddressReferenceRepository::class)
|
||||
* @ORM\Table(name="chill_main_address_reference")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*/
|
||||
class AddressReference
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $refId;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $street;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $streetNumber;
|
||||
|
||||
/**
|
||||
* @var PostalCode
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||
*/
|
||||
private $postcode;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $municipalityCode;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* A geospatial field storing the coordinates of the Address
|
||||
*
|
||||
* @var Point
|
||||
*
|
||||
* @ORM\Column(type="point")
|
||||
*/
|
||||
private $point;
|
||||
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getRefId(): ?string
|
||||
{
|
||||
return $this->refId;
|
||||
}
|
||||
|
||||
public function setRefId(string $refId): self
|
||||
{
|
||||
$this->refId = $refId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStreet(): ?string
|
||||
{
|
||||
return $this->street;
|
||||
}
|
||||
|
||||
public function setStreet(?string $street): self
|
||||
{
|
||||
$this->street = $street;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStreetNumber(): ?string
|
||||
{
|
||||
return $this->streetNumber;
|
||||
}
|
||||
|
||||
public function setStreetNumber(?string $streetNumber): self
|
||||
{
|
||||
$this->streetNumber = $streetNumber;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set postcode
|
||||
*
|
||||
* @param PostalCode $postcode
|
||||
*
|
||||
* @return Address
|
||||
*/
|
||||
public function setPostcode(PostalCode $postcode = null)
|
||||
{
|
||||
$this->postcode = $postcode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get postcode
|
||||
*
|
||||
* @return PostalCode
|
||||
*/
|
||||
public function getPostcode()
|
||||
{
|
||||
return $this->postcode;
|
||||
}
|
||||
|
||||
public function getMunicipalityCode(): ?string
|
||||
{
|
||||
return $this->municipalityCode;
|
||||
}
|
||||
|
||||
public function setMunicipalityCode(?string $municipalityCode): self
|
||||
{
|
||||
$this->municipalityCode = $municipalityCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSource(): ?string
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
public function setSource(?string $source): self
|
||||
{
|
||||
$this->source = $source;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoint(): ?Point
|
||||
{
|
||||
return $this->point;
|
||||
}
|
||||
|
||||
public function setPoint(?Point $point): self
|
||||
{
|
||||
$this->point = $point;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -33,8 +33,8 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
* A type to create/update Address entity
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `has_valid_from` (boolean): show if an entry "has valid from" must be
|
||||
*
|
||||
* - `has_valid_from` (boolean): show if an entry "has valid from" must be
|
||||
* shown.
|
||||
* - `null_if_empty` (boolean): replace the address type by null if the street
|
||||
* or the postCode is empty. This is useful when the address is not required and
|
||||
@ -45,10 +45,10 @@ class AddressType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('streetAddress1', TextType::class, array(
|
||||
->add('street', TextType::class, array(
|
||||
'required' => !$options['has_no_address'] // true if has no address is false
|
||||
))
|
||||
->add('streetAddress2', TextType::class, array(
|
||||
->add('streetNumber', TextType::class, array(
|
||||
'required' => false
|
||||
))
|
||||
->add('postCode', PostalCodeType::class, array(
|
||||
@ -57,7 +57,7 @@ class AddressType extends AbstractType
|
||||
'required' => !$options['has_no_address'] // true if has no address is false
|
||||
))
|
||||
;
|
||||
|
||||
|
||||
if ($options['has_valid_from']) {
|
||||
$builder
|
||||
->add('validFrom', DateType::class, array(
|
||||
@ -67,7 +67,7 @@ class AddressType extends AbstractType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if ($options['has_no_address']) {
|
||||
$builder
|
||||
->add('isNoAddress', ChoiceType::class, [
|
||||
@ -79,12 +79,12 @@ class AddressType extends AbstractType
|
||||
'label' => 'address.address_homeless'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
if ($options['null_if_empty'] === TRUE) {
|
||||
$builder->setDataMapper(new AddressDataMapper());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\AddressReference;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method AddressReference|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method AddressReference|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method AddressReference[] findAll()
|
||||
* @method AddressReference[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class AddressReferenceRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, AddressReference::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return AddressReference[] Returns an array of AddressReference objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('a')
|
||||
->andWhere('a.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('a.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?AddressReference
|
||||
{
|
||||
return $this->createQueryBuilder('a')
|
||||
->andWhere('a.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
@ -6,8 +6,8 @@
|
||||
<div class="chill_address_is_noaddress">{{ 'address.consider homeless'|trans }}</div>
|
||||
{% endif %}
|
||||
<div class="chill_address_address">
|
||||
{% if address.streetAddress1 is not empty %}<p class="street street1">{{ address.streetAddress1 }}</p>{% endif %}
|
||||
{% if address.streetAddress2 is not empty %}<p class="street street2">{{ address.streetAddress2 }}</p>{% endif %}
|
||||
{% if address.street is not empty %}<p class="street street1">{{ address.street }}</p>{% endif %}
|
||||
{% if address.streetNumber is not empty %}<p class="street street2">{{ address.streetNumber }}</p>{% endif %}
|
||||
{% if address.postCode is not empty %}
|
||||
<p class="postalCode"><span class="code">{{ address.postCode.code }}</span> <span class="name">{{ address.postCode.name }}</span></p>
|
||||
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
|
||||
|
119
src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php
Normal file
119
src/Bundle/ChillMainBundle/Tests/Doctrine/Model/PointTest.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Tests\Doctrine\Model;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
|
||||
/**
|
||||
* Test the point model methods
|
||||
*
|
||||
* @author Julien Minet <julien.minet@champs-libres.coop>
|
||||
*/
|
||||
class ExportControllerTest extends KernelTestCase
|
||||
{
|
||||
|
||||
public function testToWKT()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);
|
||||
|
||||
$this->assertEquals($point->toWKT(),'SRID=4326;POINT(4.8634 50.47382)');
|
||||
}
|
||||
|
||||
public function testToGeojson()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);
|
||||
|
||||
$this->assertEquals($point->toGeoJson(),'{"type":"Point","coordinates":[4.8634,50.47382]}');
|
||||
}
|
||||
|
||||
public function testToArrayGeoJson()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);
|
||||
|
||||
$this->assertEquals(
|
||||
$point->toArrayGeoJson(),
|
||||
[
|
||||
'type' => 'Point',
|
||||
'coordinates' => [4.8634, 50.47382]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testJsonSerialize()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);
|
||||
|
||||
$this->assertEquals(
|
||||
$point->jsonSerialize(),
|
||||
[
|
||||
'type' => 'Point',
|
||||
'coordinates' => [4.8634, 50.47382]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromGeoJson()
|
||||
{
|
||||
$geojson = '{"type":"Point","coordinates":[4.8634,50.47382]}';
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);;
|
||||
|
||||
$this->assertEquals($point, Point::fromGeoJson($geojson));
|
||||
}
|
||||
|
||||
public function testFromLonLat()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);;
|
||||
|
||||
$this->assertEquals($point, Point::fromLonLat($lon, $lat));
|
||||
}
|
||||
|
||||
public function testFromArrayGeoJson()
|
||||
{
|
||||
$array = [
|
||||
'type' => 'Point',
|
||||
'coordinates' => [4.8634, 50.47382]
|
||||
];
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);;
|
||||
|
||||
$this->assertEquals($point, Point::fromArrayGeoJson($array));
|
||||
}
|
||||
|
||||
public function testGetLat()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);;
|
||||
|
||||
$this->assertEquals($lat, $point->getLat());
|
||||
}
|
||||
|
||||
public function testGetLon()
|
||||
{
|
||||
$lon = 4.8634;
|
||||
$lat = 50.47382;
|
||||
$point = $this->preparePoint($lon, $lat);;
|
||||
|
||||
$this->assertEquals($lon, $point->getLon());
|
||||
}
|
||||
|
||||
private function preparePoint($lon, $lat)
|
||||
{
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Create the postgis extension
|
||||
*/
|
||||
final class Version20210414091001 extends AbstractMigration
|
||||
{
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
$this->addSql('CREATE EXTENSION IF NOT EXISTS postgis;');
|
||||
|
||||
}
|
||||
|
||||
public function down(Schema $schema) : void
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
$this->addSql('DROP EXTENSION IF NOT EXISTS postgis;');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return "Enable the postgis extension in public schema";
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add new fields to address, including a Point geometry field.
|
||||
*/
|
||||
final class Version20210420115006 extends AbstractMigration
|
||||
{
|
||||
public function getDescription() : string
|
||||
{
|
||||
return 'Add a Point data type and modify the Address entity';
|
||||
}
|
||||
|
||||
public function up(Schema $schema) : void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_address RENAME COLUMN streetaddress1 TO street;');
|
||||
$this->addSql('ALTER TABLE chill_main_address RENAME COLUMN streetaddress2 TO streetNumber;');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD floor VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD corridor VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD steps VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD buildingName VARCHAR(255) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD flat VARCHAR(16) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD distribution VARCHAR(255) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD extra VARCHAR(255) DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD validTo DATE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD point geometry(POINT,4326) DEFAULT NULL');
|
||||
}
|
||||
|
||||
|
||||
public function down(Schema $schema) : void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_address RENAME COLUMN street TO streetaddress1;');
|
||||
$this->addSql('ALTER TABLE chill_main_address RENAME COLUMN streetNumber TO streetaddress2;');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP floor');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP corridor');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP steps');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP buildingName');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP flat');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP distribution');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP extra');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP validTo');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP point');
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add a AddressReference table for storing authoritative address data
|
||||
*/
|
||||
final class Version20210503085107 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add a AddressReference table for storing authoritative address data';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE SEQUENCE chill_main_address_reference_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE chill_main_address_reference (id INT NOT NULL, postcode_id INT DEFAULT NULL, refId VARCHAR(255) NOT NULL, street VARCHAR(255) DEFAULT NULL, streetNumber VARCHAR(255) DEFAULT NULL, municipalityCode VARCHAR(255) DEFAULT NULL, source VARCHAR(255) DEFAULT NULL, point geometry(POINT,4326) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_CA6C1BD7EECBFDF1 ON chill_main_address_reference (postcode_id)');
|
||||
$this->addSql('ALTER TABLE chill_main_address_reference ADD CONSTRAINT FK_CA6C1BD7EECBFDF1 FOREIGN KEY (postcode_id) REFERENCES chill_main_postal_code (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP SEQUENCE chill_main_address_reference_id_seq CASCADE');
|
||||
$this->addSql('DROP TABLE chill_main_address_reference');
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add linkedToThirdParty field to Address
|
||||
*/
|
||||
final class Version20210505153727 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add linkedToThirdParty field to Address';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD linkedToThirdParty_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE chill_main_address ADD CONSTRAINT FK_165051F6114B8DD9 FOREIGN KEY (linkedToThirdParty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_165051F6114B8DD9 ON chill_main_address (linkedToThirdParty_id)');
|
||||
$this->addSql('
|
||||
CREATE TABLE chill_main_address_legacy AS
|
||||
TABLE chill_main_address;
|
||||
');
|
||||
$this->addSql('
|
||||
WITH hydrated_addresses AS (
|
||||
SELECT *, rank() OVER (PARTITION BY pa_a.person_id ORDER BY validfrom)
|
||||
FROM chill_main_address AS aa JOIN chill_person_persons_to_addresses AS pa_a ON aa.id = pa_a.address_id
|
||||
)
|
||||
UPDATE chill_main_address AS b
|
||||
SET validto = (
|
||||
SELECT validfrom - INTERVAL \'1 DAY\'
|
||||
FROM hydrated_addresses
|
||||
WHERE hydrated_addresses.id = (
|
||||
SELECT a1.id
|
||||
FROM hydrated_addresses AS a1 JOIN hydrated_addresses AS a2 ON a2.person_id = a1.person_id AND a2.rank = (a1.rank-1)
|
||||
WHERE a2.id = b.id
|
||||
)
|
||||
);
|
||||
');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP CONSTRAINT FK_165051F6114B8DD9');
|
||||
$this->addSql('DROP INDEX IDX_165051F6114B8DD9');
|
||||
$this->addSql('ALTER TABLE chill_main_address DROP linkedToThirdParty_id');
|
||||
$this->addSql('DROP TABLE IF EXISTS chill_main_address_legacy');
|
||||
$this->addSql('
|
||||
UPDATE chill_main_address
|
||||
SET validto = null;
|
||||
');
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
|
||||
/**
|
||||
* Load people into database
|
||||
@ -37,17 +38,17 @@ use Chill\MainBundle\Entity\Address;
|
||||
* @author Marc Ducobu <marc@champs-libres.coop>
|
||||
*/
|
||||
class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
|
||||
|
||||
protected $faker;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->faker = \Faker\Factory::create('fr_FR');
|
||||
}
|
||||
|
||||
|
||||
public function prepare()
|
||||
{
|
||||
//prepare days, month, years
|
||||
@ -56,57 +57,57 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
$this->years[] = $y;
|
||||
$y = $y +1;
|
||||
} while ($y >= 1990);
|
||||
|
||||
|
||||
$m = 1;
|
||||
do {
|
||||
$this->month[] = $m;
|
||||
$m = $m +1;
|
||||
} while ($m >= 12);
|
||||
|
||||
|
||||
$d = 1;
|
||||
do {
|
||||
$this->day[] = $d;
|
||||
$d = $d + 1;
|
||||
} while ($d <= 28);
|
||||
}
|
||||
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 10000;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$this->loadRandPeople($manager);
|
||||
$this->loadExpectedPeople($manager);
|
||||
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
||||
public function loadExpectedPeople(ObjectManager $manager)
|
||||
{
|
||||
echo "loading expected people...\n";
|
||||
|
||||
|
||||
foreach ($this->peoples as $person) {
|
||||
$this->addAPerson($this->fillWithDefault($person), $manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function loadRandPeople(ObjectManager $manager)
|
||||
{
|
||||
echo "loading rand people...\n";
|
||||
|
||||
|
||||
$this->prepare();
|
||||
|
||||
|
||||
$chooseLastNameOrTri = array('tri', 'tri', 'name', 'tri');
|
||||
|
||||
|
||||
$i = 0;
|
||||
|
||||
|
||||
do {
|
||||
$i++;
|
||||
|
||||
|
||||
$sex = $this->genders[array_rand($this->genders)];
|
||||
|
||||
|
||||
if ($chooseLastNameOrTri[array_rand($chooseLastNameOrTri)] === 'tri' ) {
|
||||
$length = rand(2, 3);
|
||||
$lastName = '';
|
||||
@ -117,13 +118,13 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
} else {
|
||||
$lastName = $this->lastNames[array_rand($this->lastNames)];
|
||||
}
|
||||
|
||||
|
||||
if ($sex === Person::MALE_GENDER) {
|
||||
$firstName = $this->firstNamesMale[array_rand($this->firstNamesMale)];
|
||||
} else {
|
||||
$firstName = $this->firstNamesFemale[array_rand($this->firstNamesFemale)];
|
||||
}
|
||||
|
||||
|
||||
// add an address on 80% of the created people
|
||||
if (rand(0,100) < 80) {
|
||||
$address = $this->getRandomAddress();
|
||||
@ -137,7 +138,7 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
} else {
|
||||
$address = null;
|
||||
}
|
||||
|
||||
|
||||
$person = array(
|
||||
'FirstName' => $firstName,
|
||||
'LastName' => $lastName,
|
||||
@ -147,15 +148,15 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'Address' => $address,
|
||||
'maritalStatus' => $this->maritalStatusRef[array_rand($this->maritalStatusRef)]
|
||||
);
|
||||
|
||||
|
||||
$this->addAPerson($this->fillWithDefault($person), $manager);
|
||||
|
||||
|
||||
} while ($i <= 100);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fill a person array with default value
|
||||
*
|
||||
*
|
||||
* @param string[] $specific
|
||||
*/
|
||||
private function fillWithDefault(array $specific)
|
||||
@ -171,10 +172,10 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'Address' => null
|
||||
), $specific);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a new person from array data
|
||||
*
|
||||
*
|
||||
* @param array $person
|
||||
* @param ObjectManager $manager
|
||||
* @throws \Exception
|
||||
@ -200,35 +201,51 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
$this->addAccompanyingPeriods($p, $value, $manager);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
//try to add the data using the setSomething function,
|
||||
// if not possible, fallback to addSomething function
|
||||
if (method_exists($p, 'set'.$key)) {
|
||||
call_user_func(array($p, 'set'.$key), $value);
|
||||
} elseif (method_exists($p, 'add'.$key)) {
|
||||
// if we have a "addSomething", we may have multiple items to add
|
||||
// so, we set the value in an array if it is not an array, and
|
||||
// so, we set the value in an array if it is not an array, and
|
||||
// will call the function addSomething multiple times
|
||||
if (!is_array($value)) {
|
||||
$value = array($value);
|
||||
}
|
||||
|
||||
|
||||
foreach($value as $v) {
|
||||
if ($v !== NULL) {
|
||||
call_user_func(array($p, 'add'.$key), $v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$manager->persist($p);
|
||||
echo "add person'".$p->__toString()."'\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creata a random address
|
||||
*
|
||||
* Create a random point
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
private function getRandomPoint()
|
||||
{
|
||||
$lonBrussels = 4.35243;
|
||||
$latBrussels = 50.84676;
|
||||
$lon = $lonBrussels + 0.01 * rand(-5, 5);
|
||||
$lat = $latBrussels + 0.01 * rand(-5, 5);
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a random address
|
||||
*
|
||||
* @return Address
|
||||
*/
|
||||
private function getRandomAddress()
|
||||
@ -238,13 +255,16 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
->setStreetAddress2(
|
||||
rand(0,9) > 5 ? $this->faker->streetAddress : ''
|
||||
)
|
||||
->setPoint(
|
||||
rand(0,9) > 5 ? $this->getRandomPoint() : NULL
|
||||
)
|
||||
->setPostcode($this->getReference(
|
||||
LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)]
|
||||
))
|
||||
->setValidFrom($this->faker->dateTimeBetween('-5 years'))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
private function getCountry($countryCode)
|
||||
{
|
||||
if ($countryCode === NULL) {
|
||||
@ -257,30 +277,30 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
|
||||
private $maritalStatusRef = ['ms_single', 'ms_married', 'ms_widow', 'ms_separat',
|
||||
'ms_divorce', 'ms_legalco', 'ms_unknown'];
|
||||
|
||||
|
||||
private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert", "Justin", "Brian",
|
||||
"Compère", "Jean-de-Dieu", "Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric",
|
||||
"Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou", "Vursuv", "Youssef" );
|
||||
|
||||
|
||||
private $firstNamesFemale = array("Svedana", "Sevlatina", "Irène", "Marcelle",
|
||||
"Corentine", "Alfonsine", "Caroline", "Solange", "Gostine", "Fatoumata", "Nicole",
|
||||
"Groseille", "Chana", "Oxana", "Ivana", "Julie", "Tina", "Adèle" );
|
||||
|
||||
|
||||
private $lastNames = array("Diallo", "Bah", "Gaillot", "Martin");
|
||||
|
||||
|
||||
private $lastNamesTrigrams = array("fas", "tré", "hu", 'blart', 'van', 'der', 'lin', 'den',
|
||||
'ta', 'mi', 'net', 'gna', 'bol', 'sac', 'ré', 'jo', 'du', 'pont', 'cas', 'tor', 'rob', 'al',
|
||||
'ma', 'gone', 'car',"fu", "ka", "lot", "no", "va", "du", "bu", "su", "jau", "tte", 'sir',
|
||||
"lo", 'to', "cho", "car", 'mo','zu', 'qi', 'mu');
|
||||
|
||||
|
||||
private $genders = array(Person::MALE_GENDER, Person::FEMALE_GENDER);
|
||||
|
||||
|
||||
private $years = array();
|
||||
|
||||
|
||||
private $month = array();
|
||||
|
||||
|
||||
private $day = array();
|
||||
|
||||
|
||||
private $peoples = array(
|
||||
array(
|
||||
'LastName' => "Depardieu",
|
||||
@ -362,21 +382,21 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'maritalStatus' => 'ms_legalco'
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
private function addAccompanyingPeriods(Person $person, array $periods, ObjectManager $manager)
|
||||
{
|
||||
foreach ($periods as $period) {
|
||||
|
||||
|
||||
echo "adding new past Accompanying Period..\n";
|
||||
|
||||
|
||||
/** @var AccompanyingPeriod $accompanyingPeriod */
|
||||
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime($period['from']));
|
||||
$accompanyingPeriod
|
||||
->setClosingDate(new \DateTime($period['to']))
|
||||
->setRemark($period['remark'])
|
||||
;
|
||||
|
||||
|
||||
$person->addAccompanyingPeriod($accompanyingPeriod);
|
||||
}
|
||||
}
|
||||
|
70
src/Bundle/ChillPersonBundle/Entity/Household/Household.php
Normal file
70
src/Bundle/ChillPersonBundle/Entity/Household/Household.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Entity\Household;
|
||||
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=HouseholdRepository::class)
|
||||
*/
|
||||
class Household
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Addresses
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\ManyToMany(
|
||||
* targetEntity="Chill\MainBundle\Entity\Address",
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\JoinTable(name="chill_person_household_to_addresses")
|
||||
* @ORM\OrderBy({"validFrom" = "DESC"})
|
||||
*/
|
||||
private $addresses;
|
||||
|
||||
|
||||
/**
|
||||
* @param Address $address
|
||||
* @return $this
|
||||
*/
|
||||
public function addAddress(Address $address)
|
||||
{
|
||||
$this->addresses[] = $address;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Address $address
|
||||
*/
|
||||
public function removeAddress(Address $address)
|
||||
{
|
||||
$this->addresses->removeElement($address);
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, the addresses are ordered by date, descending (the most
|
||||
* recent first)
|
||||
*
|
||||
* @return \Chill\MainBundle\Entity\Address[]
|
||||
*/
|
||||
public function getAddresses()
|
||||
{
|
||||
return $this->addresses;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Entity\Household;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdMembersRepository;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=HouseholdMembersRepository::class)
|
||||
*/
|
||||
class HouseholdMembers
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $position;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
private $startDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
private $endDate;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $comment;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $sharedHousehold;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Person
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="\Chill\PersonBundle\Entity\Person"
|
||||
* )
|
||||
*/
|
||||
private $person;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Household
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="\Chill\PersonBundle\Entity\Household\Household"
|
||||
* )
|
||||
*/
|
||||
private $household;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPosition(): ?string
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function setPosition(?string $position): self
|
||||
{
|
||||
$this->position = $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setStartDate(\DateTimeInterface $startDate): self
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEndDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
public function setEndDate(\DateTimeInterface $endDate): self
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getComment(): ?string
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
public function setComment(?string $comment): self
|
||||
{
|
||||
$this->comment = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSharedHousehold(): ?bool
|
||||
{
|
||||
return $this->sharedHousehold;
|
||||
}
|
||||
|
||||
public function setSharedHousehold(bool $sharedHousehold): self
|
||||
{
|
||||
$this->sharedHousehold = $sharedHousehold;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPerson(): ?Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
public function setPerson(?Person $person): self
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHousehold(): ?Household
|
||||
{
|
||||
return $this->household;
|
||||
}
|
||||
|
||||
public function setHousehold(?Household $household): self
|
||||
{
|
||||
$this->household = $household;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Repository\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMembers;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method HouseholdMembers|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method HouseholdMembers|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method HouseholdMembers[] findAll()
|
||||
* @method HouseholdMembers[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class HouseholdMembersRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, HouseholdMembers::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return HouseholdMembers[] Returns an array of HouseholdMembers objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('h')
|
||||
->andWhere('h.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('h.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?HouseholdMembers
|
||||
{
|
||||
return $this->createQueryBuilder('h')
|
||||
->andWhere('h.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Repository\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Household|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Household|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Household[] findAll()
|
||||
* @method Household[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class HouseholdRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Household::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Household[] Returns an array of Household objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('h')
|
||||
->andWhere('h.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('h.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Household
|
||||
{
|
||||
return $this->createQueryBuilder('h')
|
||||
->andWhere('h.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
@ -21,17 +21,17 @@
|
||||
{% block title 'Update address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
|
||||
<h1>{{ 'Update address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1>
|
||||
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
|
||||
{{ form_row(form.isNoAddress) }}
|
||||
{{ form_row(form.streetAddress1) }}
|
||||
{{ form_row(form.streetAddress2) }}
|
||||
{{ form_row(form.street) }}
|
||||
{{ form_row(form.streetNumber) }}
|
||||
{{ form_row(form.postCode) }}
|
||||
{{ form_row(form.validFrom) }}
|
||||
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_person_address_list', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel">
|
||||
@ -42,7 +42,7 @@
|
||||
{{ form_row(form.submit, { 'attr' : { 'class': 'sc-button bt-save' }, 'label': 'Save' } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
@ -23,9 +23,9 @@
|
||||
{% block title %}{{ 'Addresses\'history for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}{% endblock %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
|
||||
<h1>{{ 'Addresses\'history for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1>
|
||||
|
||||
|
||||
<table class="records_list">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -48,11 +48,11 @@
|
||||
{% for address in person.addresses %}
|
||||
<tr>
|
||||
<td><strong>{{ 'Since %date%'|trans( { '%date%' : address.validFrom|format_date('long') } ) }}</strong></td>
|
||||
|
||||
|
||||
<td>
|
||||
{{ address_macros._render(address, { 'with_valid_from' : false, 'has_no_address': true } ) }}
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
@ -61,11 +61,17 @@
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_person_view', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel">
|
||||
@ -73,10 +79,11 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
<a href="{{ path('chill_person_address_new', { 'person_id' : person.id } ) }}" class="sc-button bt-create">
|
||||
{{ 'Add an address'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
@ -21,21 +21,21 @@
|
||||
{% block title %}{{ 'New address for %name%'|trans({ '%name%': person.firstName|capitalize ~ ' ' ~ person.lastName } )|capitalize }}{% endblock %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
|
||||
<h1>{{ 'New address for %name%'|trans({ '%name%': person.firstName ~ ' ' ~ person.lastName } ) }}</h1>
|
||||
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
|
||||
{{ form_row(form.isNoAddress) }}
|
||||
{{ form_row(form.streetAddress1) }}
|
||||
{{ form_errors(form.streetAddress1) }}
|
||||
{{ form_row(form.streetAddress2) }}
|
||||
{{ form_errors(form.streetAddress2) }}
|
||||
{{ form_row(form.street) }}
|
||||
{{ form_errors(form.street) }}
|
||||
{{ form_row(form.streetNumber) }}
|
||||
{{ form_errors(form.streetNumber) }}
|
||||
{{ form_row(form.postCode) }}
|
||||
{{ form_errors(form.postCode) }}
|
||||
{{ form_row(form.validFrom) }}
|
||||
{{ form_errors(form.validFrom) }}
|
||||
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_person_address_list', { 'person_id' : person.id } ) }}" class="sc-button bt-cancel">
|
||||
@ -46,7 +46,7 @@
|
||||
{{ form_row(form.submit, { 'attr' : { 'class': 'sc-button bt-create' }, 'label': 'Create' } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
||||
{% endblock personcontent %}
|
||||
|
@ -7,6 +7,6 @@ module.exports = function(encore, entries)
|
||||
encore.addAliases({
|
||||
ChillPersonAssets: __dirname + '/Resources/public'
|
||||
});
|
||||
|
||||
|
||||
encore.addEntry('accompanying_course', __dirname + '/Resources/public/js/AccompanyingCourse/index.js');
|
||||
};
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Create Household and HouseholdMembers tables
|
||||
*/
|
||||
final class Version20210505093408 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create Household and HouseholdMembers tables';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE SEQUENCE Household_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE SEQUENCE HouseholdMembers_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE Household (id INT NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE TABLE HouseholdMembers (id INT NOT NULL, person_id INT DEFAULT NULL, household_id INT DEFAULT NULL, position VARCHAR(255) DEFAULT NULL, startDate DATE NOT NULL, endDate DATE NOT NULL, comment VARCHAR(255) DEFAULT NULL, sharedHousehold BOOLEAN NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_4D1FB288217BBB47 ON HouseholdMembers (person_id)');
|
||||
$this->addSql('CREATE INDEX IDX_4D1FB288E79FF843 ON HouseholdMembers (household_id)');
|
||||
$this->addSql('ALTER TABLE HouseholdMembers ADD CONSTRAINT FK_4D1FB288217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE HouseholdMembers ADD CONSTRAINT FK_4D1FB288E79FF843 FOREIGN KEY (household_id) REFERENCES Household (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE HouseholdMembers DROP CONSTRAINT FK_4D1FB288E79FF843');
|
||||
$this->addSql('ALTER TABLE HouseholdMembers DROP CONSTRAINT FK_4D1FB288217BBB47');
|
||||
$this->addSql('DROP SEQUENCE Household_id_seq CASCADE');
|
||||
$this->addSql('DROP SEQUENCE HouseholdMembers_id_seq CASCADE');
|
||||
$this->addSql('DROP TABLE Household');
|
||||
$this->addSql('DROP TABLE HouseholdMembers');
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add a household_to_address table
|
||||
*/
|
||||
final class Version20210505154316 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add a household_to_addresses table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE chill_person_household_to_addresses (household_id INT NOT NULL, address_id INT NOT NULL, PRIMARY KEY(household_id, address_id))');
|
||||
$this->addSql('CREATE INDEX IDX_7109483E79FF843 ON chill_person_household_to_addresses (household_id)');
|
||||
$this->addSql('CREATE INDEX IDX_7109483F5B7AF75 ON chill_person_household_to_addresses (address_id)');
|
||||
$this->addSql('ALTER TABLE chill_person_household_to_addresses ADD CONSTRAINT FK_7109483E79FF843 FOREIGN KEY (household_id) REFERENCES Household (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_household_to_addresses ADD CONSTRAINT FK_7109483F5B7AF75 FOREIGN KEY (address_id) REFERENCES chill_main_address (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE chill_person_household_to_addresses');
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user