diff --git a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php
index 437f0930c..8e679b228 100644
--- a/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php
+++ b/src/Bundle/ChillMainBundle/Controller/PostalCodeAPIController.php
@@ -14,7 +14,7 @@ namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\CountryRepository;
-use Chill\MainBundle\Repository\PostalCodeRepository;
+use Chill\MainBundle\Repository\PostalCodeRepositoryInterface;
use Chill\MainBundle\Serializer\Model\Collection;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -30,11 +30,11 @@ final class PostalCodeAPIController extends ApiController
private PaginatorFactory $paginatorFactory;
- private PostalCodeRepository $postalCodeRepository;
+ private PostalCodeRepositoryInterface $postalCodeRepository;
public function __construct(
CountryRepository $countryRepository,
- PostalCodeRepository $postalCodeRepository,
+ PostalCodeRepositoryInterface $postalCodeRepository,
PaginatorFactory $paginatorFactory
) {
$this->countryRepository = $countryRepository;
diff --git a/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php
new file mode 100644
index 000000000..ca488fe1a
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Form/Type/DataTransformer/PostalCodeToIdTransformer.php
@@ -0,0 +1,55 @@
+postalCodeRepository = $postalCodeRepository;
+ }
+
+ public function reverseTransform($value)
+ {
+ if (null === $value || trim('') === $value) {
+ return null;
+ }
+
+ if (!is_int((int) $value)) {
+ throw new TransformationFailedException('Cannot transform ' . gettype($value));
+ }
+
+ return $this->postalCodeRepository->find((int) $value);
+ }
+
+ public function transform($value)
+ {
+ if (null === $value) {
+ return null;
+ }
+
+ if ($value instanceof PostalCode) {
+ return $value->getId();
+ }
+
+ throw new TransformationFailedException('Could not reverseTransform ' . gettype($value));
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php b/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php
new file mode 100644
index 000000000..d1feacd6a
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Form/Type/PickPostalCodeType.php
@@ -0,0 +1,49 @@
+postalCodeToIdTransformer = $postalCodeToIdTransformer;
+ }
+
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder->addViewTransformer($this->postalCodeToIdTransformer);
+ }
+
+ public function buildView(FormView $view, FormInterface $form, array $options)
+ {
+ $view->vars['uniqid'] = $view->vars['attr']['data-input-postal-code'] = uniqid('input_pick_postal_code_');
+ }
+
+ public function configureOptions(OptionsResolver $resolver)
+ {
+ $resolver
+ ->setDefault('class', PostalCode::class)
+ ->setDefault('multiple', false)
+ ->setAllowedTypes('multiple', ['bool'])
+ ->setDefault('compound', false);
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php
index c53df01df..32c1322be 100644
--- a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php
+++ b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepository.php
@@ -18,10 +18,9 @@ use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
-use Doctrine\Persistence\ObjectRepository;
use RuntimeException;
-final class PostalCodeRepository implements ObjectRepository
+final class PostalCodeRepository implements PostalCodeRepositoryInterface
{
private EntityManagerInterface $entityManager;
@@ -29,7 +28,7 @@ final class PostalCodeRepository implements ObjectRepository
public function __construct(EntityManagerInterface $entityManager)
{
- $this->repository = $entityManager->getRepository(PostalCode::class);
+ $this->repository = $entityManager->getRepository($this->getClassName());
$this->entityManager = $entityManager;
}
@@ -51,20 +50,11 @@ final class PostalCodeRepository implements ObjectRepository
return $this->repository->find($id, $lockMode, $lockVersion);
}
- /**
- * @return PostalCode[]
- */
public function findAll(): array
{
return $this->repository->findAll();
}
- /**
- * @param mixed|null $limit
- * @param mixed|null $offset
- *
- * @return PostalCode[]
- */
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
@@ -95,7 +85,7 @@ final class PostalCodeRepository implements ObjectRepository
return $this->repository->findOneBy($criteria, $orderBy);
}
- public function getClassName()
+ public function getClassName(): string
{
return PostalCode::class;
}
diff --git a/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php
new file mode 100644
index 000000000..fe3dee195
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Repository/PostalCodeRepositoryInterface.php
@@ -0,0 +1,42 @@
+',
+ components: {
+ PickPostalCode,
+ },
+ data() {
+ return {
+ city: city,
+ }
+ },
+ methods: {
+ onCitySelected(city) {
+ this.city = city;
+ input.value = city.id;
+ },
+ onCityRemoved(city) {
+ this.city = null;
+ input.value = '';
+ }
+ }
+ })
+ .use(i18n)
+ .mount(el);
+}
+
+function loadDynamicPickers(element) {
+
+ let apps = element.querySelectorAll('[data-module="pick-postal-code"]');
+
+ apps.forEach(function(el) {
+
+ console.log('el', el);
+ const
+ uniqId = el.dataset.uniqid,
+ input = document.querySelector(`input[data-input-uniqid="${uniqId}"]`),
+ cityIdValue = input.value === '' ? null : input.value
+ ;
+
+ console.log('uniqid', uniqId);
+ console.log('input', input);
+ console.log('input value', input.value);
+ console.log('cityIdValue', cityIdValue);
+
+ if (cityIdValue !== null) {
+ makeFetch('GET', `/api/1.0/main/postal-code/${cityIdValue}.json`).then(city => {
+ loadOnePicker(el, input, uniqId, city);
+ })
+ } else {
+ loadOnePicker(el, input, uniqId, null);
+ }
+ });
+}
+
+document.addEventListener('DOMContentLoaded', function(e) {
+ loadDynamicPickers(document)
+})
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md
new file mode 100644
index 000000000..93dcf1816
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.md
@@ -0,0 +1,4 @@
+# Pickpostalcode
+
+## Usage
+
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue
new file mode 100644
index 000000000..3c191b8c4
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/PickPostalCode.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss
new file mode 100644
index 000000000..09f5fd539
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/_PickPostalCode.scss
@@ -0,0 +1,3 @@
+.PickPostalCode {
+
+}
diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js
new file mode 100644
index 000000000..d31dcc3f4
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/PickPostalCode/api.js
@@ -0,0 +1,43 @@
+import {makeFetch, fetchResults} from 'ChillMainAssets/lib/api/apiMethods';
+
+/**
+ * Endpoint chill_api_single_postal_code__index
+ * method GET, get Cities Object
+ * @params {object} a country object
+ * @returns {Promise} a promise containing all Postal Code objects filtered with country
+ */
+const fetchCities = (country) => {
+ // warning: do not use fetchResults (in apiMethods): we need only a **part** of the results in the db
+ const params = new URLSearchParams({item_per_page: 100});
+
+ if (country !== null) {
+ params.append('country', country.id);
+ }
+
+ return makeFetch('GET', `/api/1.0/main/postal-code.json?${params.toString()}`).then(r => Promise.resolve(r.results));
+};
+
+/**
+ * Endpoint chill_main_postalcodeapi_search
+ * method GET, get Cities Object
+ * @params {string} search a search string
+ * @params {object} country a country object
+ * @params {AbortController} an abort controller
+ * @returns {Promise} a promise containing all Postal Code objects filtered with country and a search string
+ */
+const searchCities = (search, country, controller) => {
+ const url = '/api/1.0/main/postal-code/search.json?';
+ const params = new URLSearchParams({q: search});
+
+ if (country !== null) {
+ Object.assign('country', country.id);
+ }
+
+ return makeFetch('GET', url + params, null, {signal: controller.signal})
+ .then(result => Promise.resolve(result.results));
+};
+
+export {
+ fetchCities,
+ searchCities,
+};
diff --git a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
index 586b900aa..7ab8a4c85 100644
--- a/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
+++ b/src/Bundle/ChillMainBundle/Resources/views/Form/fields.html.twig
@@ -238,3 +238,9 @@
{% endblock %}
+
+{% block pick_postal_code_widget %}
+ {{ form_help(form)}}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillMainBundle/Tests/Form/Type/PickPostalCodeTypeTest.php b/src/Bundle/ChillMainBundle/Tests/Form/Type/PickPostalCodeTypeTest.php
new file mode 100644
index 000000000..9c0174754
--- /dev/null
+++ b/src/Bundle/ChillMainBundle/Tests/Form/Type/PickPostalCodeTypeTest.php
@@ -0,0 +1,67 @@
+factory->create(PickPostalCodeType::class, null);
+
+ $form->submit(['1']);
+
+ $this->assertTrue($form->isSynchronized());
+
+ $this->assertEquals(1, $form->getData()->getId());
+ }
+
+ protected function getExtensions()
+ {
+ $postalCodeRepository = $this->prophesize(PostalCodeRepositoryInterface::class);
+ $postalCodeRepository->find(Argument::type('string'))
+ ->will(static function ($args) {
+ $postalCode = new PostalCode();
+ $reflectionClass = new ReflectionClass($postalCode);
+ $id = $reflectionClass->getProperty('id');
+ $id->setAccessible(true);
+ $id->setValue($postalCode, (int) $args[0]);
+
+ return $postalCode;
+ });
+
+ $type = new PickPostalCodeType(
+ new PostalCodeToIdTransformer(
+ $postalCodeRepository->reveal()
+ )
+ );
+
+ return [
+ new PreloadedExtension([$type], []),
+ ];
+ }
+}
diff --git a/src/Bundle/ChillMainBundle/chill.webpack.config.js b/src/Bundle/ChillMainBundle/chill.webpack.config.js
index 628f04ba5..73f539739 100644
--- a/src/Bundle/ChillMainBundle/chill.webpack.config.js
+++ b/src/Bundle/ChillMainBundle/chill.webpack.config.js
@@ -70,6 +70,7 @@ module.exports = function(encore, entries)
encore.addEntry('mod_entity_workflow_subscribe', __dirname + '/Resources/public/module/entity-workflow-subscribe/index.js');
encore.addEntry('mod_entity_workflow_pick', __dirname + '/Resources/public/module/entity-workflow-pick/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');
// Vue entrypoints
encore.addEntry('vue_address', __dirname + '/Resources/public/vuejs/Address/index.js');
diff --git a/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php
index 181677709..c27362e17 100644
--- a/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php
+++ b/src/Bundle/ChillPersonBundle/Controller/ReassignAccompanyingPeriodController.php
@@ -11,7 +11,9 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Controller;
+use Chill\MainBundle\Entity\PostalCode;
use Chill\MainBundle\Entity\User;
+use Chill\MainBundle\Form\Type\PickPostalCodeType;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\UserRepository;
@@ -92,12 +94,14 @@ class ReassignAccompanyingPeriodController extends AbstractController
$form->handleRequest($request);
$userFrom = $form['user']->getData();
+ $postalCodes = $form['postal_code']->getData() instanceof PostalCode ? [$form['postal_code']->getData()] : [];
$total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod($userFrom);
$paginator = $this->paginatorFactory->create($total);
$periods = $this->accompanyingPeriodACLAwareRepository
- ->findByUserOpenedAccompanyingPeriod(
+ ->findByUserAndPostalCodesOpenedAccompanyingPeriod(
$userFrom,
+ $postalCodes,
['openingDate' => 'ASC'],
$paginator->getItemsPerPage(),
$paginator->getCurrentPageFirstItemNumber()
@@ -148,7 +152,9 @@ class ReassignAccompanyingPeriodController extends AbstractController
{
$data = [
'user' => null,
+ 'postal_code' => null,
];
+
$builder = $this->formFactory->createBuilder(FormType::class, $data, [
'method' => 'get', 'csrf_protection' => false, ]);
@@ -158,12 +164,17 @@ class ReassignAccompanyingPeriodController extends AbstractController
'label' => 'reassign.Current user',
'required' => false,
'help' => 'reassign.Choose a user and click on "Filter" to apply',
+ ])
+ ->add('postal_code', PickPostalCodeType::class, [
+ 'label' => 'reassign.Filter by postal code',
+ 'required' => false,
+ 'help' => 'reassign.Filter course which are located inside a postal code',
]);
return $builder->getForm();
}
- private function buildReassignForm(array $periodIds, ?User $userFrom): FormInterface
+ private function buildReassignForm(array $periodIds, ?User $userFrom = null): FormInterface
{
$defaultData = [
'userFrom' => $userFrom,
diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
index f5217bfa7..071f7b3eb 100644
--- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
+++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
@@ -11,7 +11,9 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Repository;
+use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Location;
+use Chill\MainBundle\Entity\PostalCode;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserJob;
@@ -19,10 +21,14 @@ use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
+use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
use DateTime;
+use DateTimeImmutable;
+use Doctrine\DBAL\Types\Types;
+use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Security\Core\Security;
use function count;
@@ -49,7 +55,12 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
$this->centerResolverDispatcher = $centerResolverDispatcher;
}
- public function buildQueryOpenedAccompanyingCourseByUser(?User $user)
+ /**
+ * @param array|PostalCode[]
+ *
+ * @return QueryBuilder
+ */
+ public function buildQueryOpenedAccompanyingCourseByUser(?User $user, array $postalCodes = [])
{
$qb = $this->accompanyingPeriodRepository->createQueryBuilder('ap');
@@ -65,6 +76,37 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
->setParameter('now', new DateTime('now'))
->setParameter('draft', AccompanyingPeriod::STEP_DRAFT);
+ if ([] !== $postalCodes) {
+ $qb->join('ap.locationHistories', 'location_history')
+ ->leftJoin(PersonHouseholdAddress::class, 'person_address', Join::WITH, 'IDENTITY(location_history.personLocation) = IDENTITY(person_address.person)')
+ ->join(
+ Address::class,
+ 'address',
+ Join::WITH,
+ 'COALESCE(IDENTITY(location_history.addressLocation), IDENTITY(person_address.address)) = address.id'
+ )
+ ->andWhere(
+ $qb->expr()->orX(
+ $qb->expr()->isNull('person_address'),
+ $qb->expr()->andX(
+ $qb->expr()->lte('person_address.validFrom', ':now'),
+ $qb->expr()->orX(
+ $qb->expr()->isNull('person_address.validTo'),
+ $qb->expr()->lt('person_address.validTo', ':now')
+ )
+ )
+ )
+ )
+ ->andWhere(
+ $qb->expr()->isNull('location_history.endDate')
+ )
+ ->andWhere(
+ $qb->expr()->in('address.postcode', ':postal_codes')
+ )
+ ->setParameter('now', new DateTimeImmutable('now'), Types::DATE_IMMUTABLE)
+ ->setParameter('postal_codes', $postalCodes);
+ }
+
return $qb;
}
@@ -77,6 +119,18 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
return $qb->getQuery()->getSingleScalarResult();
}
+ public function countByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes): int
+ {
+ if (null === $user) {
+ return 0;
+ }
+
+ return $this->buildQueryOpenedAccompanyingCourseByUser($user, $postalCodes)
+ ->select('COUNT(ap)')
+ ->getQuery()
+ ->getSingleScalarResult();
+ }
+
public function countByUserOpenedAccompanyingPeriod(?User $user): int
{
if (null === $user) {
@@ -158,6 +212,24 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
return $qb->getQuery()->getResult();
}
+ public function findByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes, array $orderBy = [], int $limit = 0, int $offset = 50): array
+ {
+ if (null === $user) {
+ return [];
+ }
+
+ $qb = $this->buildQueryOpenedAccompanyingCourseByUser($user);
+
+ $qb->setFirstResult($offset)
+ ->setMaxResults($limit);
+
+ foreach ($orderBy as $field => $direction) {
+ $qb->addOrderBy('ap.' . $field, $direction);
+ }
+
+ return $qb->getQuery()->getResult();
+ }
+
/**
* @return array|AccompanyingPeriod[]
*/
diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php
index 6dd44b290..0cca1a5f4 100644
--- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php
+++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepositoryInterface.php
@@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Repository;
+use Chill\MainBundle\Entity\PostalCode;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\UserJob;
@@ -25,6 +26,11 @@ interface AccompanyingPeriodACLAwareRepositoryInterface
*/
public function countByUnDispatched(array $jobs, array $services, array $administrativeLocations): int;
+ /**
+ * @param array|PostalCode[] $postalCodes
+ */
+ public function countByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes): int;
+
public function countByUserOpenedAccompanyingPeriod(?User $user): int;
public function findByPerson(
@@ -43,5 +49,10 @@ interface AccompanyingPeriodACLAwareRepositoryInterface
*/
public function findByUnDispatched(array $jobs, array $services, array $administrativeLocations, ?int $limit = null, ?int $offset = null): array;
+ /**
+ * @param array|PostalCode[] $postalCodes
+ */
+ public function findByUserAndPostalCodesOpenedAccompanyingPeriod(?User $user, array $postalCodes, array $orderBy = [], int $limit = 0, int $offset = 50): array;
+
public function findByUserOpenedAccompanyingPeriod(?User $user, array $orderBy = [], int $limit = 0, int $offset = 50): array;
}
diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig
index 63e25efeb..fb22f5153 100644
--- a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig
+++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingPeriod/reassign_list.html.twig
@@ -5,11 +5,13 @@
{% block js %}
{{ encore_entry_script_tags('mod_set_referrer') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
+ {{ encore_entry_script_tags('mod_pick_postal_code') }}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('mod_set_referrer') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
+ {{ encore_entry_link_tags('mod_pick_postal_code') }}
{% endblock %}
{% macro period_meta(period) %}
@@ -48,6 +50,8 @@
{{ form_start(form) }}
{{ form_label(form.user ) }}
{{ form_widget(form.user, {'attr': {'class': 'select2'}}) }}
+ {{ form_label(form.postal_code) }}
+ {{ form_widget(form.postal_code) }}
-