mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/master' into issue439_residential_address_otf
This commit is contained in:
@@ -21,6 +21,7 @@ use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Iterator;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use Nelmio\Alice\Loader\NativeLoader;
|
||||
use Nelmio\Alice\ObjectSet;
|
||||
|
||||
@@ -29,6 +30,13 @@ use function count;
|
||||
|
||||
class LoadThirdParty extends Fixture implements DependentFixtureInterface
|
||||
{
|
||||
private PhoneNumberUtil $phoneNumberUtil;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->phoneNumberUtil = PhoneNumberUtil::getInstance();
|
||||
}
|
||||
|
||||
public function getDependencies()
|
||||
{
|
||||
return [
|
||||
@@ -66,7 +74,7 @@ class LoadThirdParty extends Fixture implements DependentFixtureInterface
|
||||
Address::class => [
|
||||
'address1' => [
|
||||
'name' => '<fr_FR:company()>',
|
||||
'telephone' => '<fr_FR:phonenumber()>',
|
||||
'telephone' => $this->phoneNumberUtil->getExampleNumber('FR'),
|
||||
'email' => '<email()>',
|
||||
'comment' => '<fr_FR:realTextBetween(10, 500)>',
|
||||
],
|
||||
@@ -116,7 +124,7 @@ class LoadThirdParty extends Fixture implements DependentFixtureInterface
|
||||
ThirdParty::class => [
|
||||
'thirdparty{1..75}' => [
|
||||
'name' => '<fr_FR:company()>',
|
||||
'telephone' => '<fr_FR:phonenumber()>',
|
||||
'telephone' => $this->phoneNumberUtil->getExampleNumber('FR'),
|
||||
'email' => '<email()>',
|
||||
'comment' => '<fr_FR:realTextBetween(10, 500)>',
|
||||
'address' => '@address<current()>',
|
||||
|
@@ -24,6 +24,7 @@ use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use libphonenumber\PhoneNumber;
|
||||
use Symfony\Component\Serializer\Annotation\Context;
|
||||
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
@@ -253,14 +254,11 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
|
||||
private ?ThirdPartyProfession $profession = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="telephone", type="string", length=64, nullable=true)
|
||||
* @Assert\Regex("/^([\+{1}])([0-9\s*]{4,20})$/",
|
||||
* message="Invalid phone number: it should begin with the international prefix starting with ""+"", hold only digits and be smaller than 20 characters. Ex: +33123456789"
|
||||
* )
|
||||
* @ORM\Column(name="telephone", type="phone_number", nullable=true)
|
||||
* @PhonenumberConstraint(type="any")
|
||||
* @Groups({"read", "write", "docgen:read", "docgen:read:3party:parent"})
|
||||
*/
|
||||
private ?string $telephone = null;
|
||||
private ?PhoneNumber $telephone = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="types", type="json", nullable=true)
|
||||
@@ -502,7 +500,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
|
||||
/**
|
||||
* Get telephone.
|
||||
*/
|
||||
public function getTelephone(): ?string
|
||||
public function getTelephone(): ?PhoneNumber
|
||||
{
|
||||
return $this->telephone;
|
||||
}
|
||||
@@ -821,12 +819,8 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
|
||||
|
||||
/**
|
||||
* Set telephone.
|
||||
*
|
||||
* @param string|null $telephone
|
||||
*
|
||||
* @return ThirdParty
|
||||
*/
|
||||
public function setTelephone($telephone = null)
|
||||
public function setTelephone(?PhoneNumber $telephone = null): self
|
||||
{
|
||||
$this->telephone = $telephone;
|
||||
|
||||
|
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace Chill\ThirdPartyBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Form\Type\ChillCollectionType;
|
||||
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
|
||||
use Chill\MainBundle\Form\Type\ChillTextareaType;
|
||||
use Chill\MainBundle\Form\Type\PickAddressType;
|
||||
use Chill\MainBundle\Form\Type\PickCenterType;
|
||||
@@ -75,7 +76,7 @@ class ThirdPartyType extends AbstractType
|
||||
->add('name', TextType::class, [
|
||||
'required' => true,
|
||||
])
|
||||
->add('telephone', TextType::class, [
|
||||
->add('telephone', ChillPhoneNumberType::class, [
|
||||
'label' => 'Phonenumber',
|
||||
'required' => false,
|
||||
])
|
||||
|
@@ -22,6 +22,9 @@ div.thirdparty-list {
|
||||
div.item-col:first-child {
|
||||
flex-basis: 25%;
|
||||
}
|
||||
div.wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,33 +34,45 @@
|
||||
<slot name="record-actions"></slot>
|
||||
</div>
|
||||
<ul class="list-content fa-ul">
|
||||
<li v-if="getProfession.length > 0">
|
||||
<i class="fa fa-li fa-id-card"></i>
|
||||
<p><span v-for="p in getProfession" :key="p" class="list-item">{{ p[0].toUpperCase() + p.slice(1).toLowerCase() }}</span></p>
|
||||
</li>
|
||||
<li v-if="hasParent">
|
||||
<i class="fa fa-li fa-hand-o-right"></i>
|
||||
<b class="me-2">{{ $t('child_of') }}</b>
|
||||
<span class="chill-entity badge-thirdparty">{{ thirdparty.parent.text }}</span>
|
||||
<on-the-fly
|
||||
:type="thirdparty.parent.type"
|
||||
:id="thirdparty.parent.id"
|
||||
:buttonText="thirdparty.parent.text"
|
||||
:displayBadge="'true' === 'true'"
|
||||
action="show">
|
||||
</on-the-fly>
|
||||
</li>
|
||||
<!-- TODO hasChildren
|
||||
NB: we cannot call on-the-fly from RenderBox. See error message in previous version of this file.
|
||||
-->
|
||||
</ul>
|
||||
<confidential v-if="thirdparty.contactDataAnonymous">
|
||||
<template v-slot:confidential-content>
|
||||
<ul 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.phonenumber">
|
||||
<i class="fa fa-li fa-mobile"></i>
|
||||
<a :href="'tel: ' + thirdparty.phonenumber">{{ thirdparty.phonenumber }}</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 v-if="thirdparty.contactDataAnonymous">
|
||||
<confidential :positionBtnFar="false">
|
||||
<template v-slot:confidential-content>
|
||||
<ul 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.phonenumber">
|
||||
<i class="fa fa-li fa-mobile"></i>
|
||||
<a :href="'tel: ' + thirdparty.phonenumber">{{ thirdparty.phonenumber }}</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>
|
||||
@@ -88,10 +100,8 @@
|
||||
|
||||
<script>
|
||||
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
|
||||
import {dateToISO} from 'ChillMainAssets/chill/js/date.js';
|
||||
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
||||
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
||||
//import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
|
||||
|
||||
export default {
|
||||
name: "ThirdPartyRenderBox",
|
||||
@@ -99,7 +109,10 @@ export default {
|
||||
AddressRenderBox,
|
||||
Confidential,
|
||||
BadgeEntity,
|
||||
//OnTheFly
|
||||
},
|
||||
// To avoid components recursively invoking eachother resolve OnTheFly component here
|
||||
beforeCreate() {
|
||||
this.$options.components.OnTheFly = require('ChillMainAssets/vuejs/OnTheFly/components/OnTheFly').default;
|
||||
},
|
||||
i18n: {
|
||||
messages: {
|
||||
@@ -120,6 +133,18 @@ export default {
|
||||
hasParent() {
|
||||
return !(this.thirdparty.parent === null || this.thirdparty.parent === undefined);
|
||||
},
|
||||
getProfession() {
|
||||
let profession = []
|
||||
if (this.hasParent && this.thirdparty.profession) {
|
||||
profession.push(this.thirdparty.profession.name.fr)
|
||||
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)
|
||||
@@ -139,6 +164,15 @@ export default {
|
||||
font-variant: all-small-caps;
|
||||
}
|
||||
}
|
||||
|
||||
.list-item {
|
||||
&::after {
|
||||
content: " | ";
|
||||
}
|
||||
&:last-child::after {
|
||||
content: ""
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@@ -110,8 +110,8 @@
|
||||
}) }}
|
||||
</li>
|
||||
<li><i class="fa fa-li fa-phone"></i>
|
||||
{% if thirdparty.telephone %}
|
||||
<a href="{{ 'tel:' ~ thirdparty.telephone }}">{{ thirdparty.telephone|chill_format_phonenumber }}</a>
|
||||
{% if thirdparty.telephone is not null %}
|
||||
<a href="{{ 'tel:' ~ thirdparty.telephone|phone_number_format('E164') }}">{{ thirdparty.telephone|chill_format_phonenumber }}</a>
|
||||
{% else %}
|
||||
<span class="chill-no-data-statement">{{ 'thirdparty.No_phonenumber'|trans }}</span>
|
||||
{% endif %}
|
||||
@@ -136,7 +136,7 @@
|
||||
</li>
|
||||
<li><i class="fa fa-li fa-phone"></i>
|
||||
{% if thirdparty.telephone %}
|
||||
<a href="{{ 'tel:' ~ thirdparty.telephone }}">{{ thirdparty.telephone|chill_format_phonenumber }}</a>
|
||||
<a href="{{ 'tel:' ~ thirdparty.telephone|phone_number_format('E164') }}">{{ thirdparty.telephone|chill_format_phonenumber }}</a>
|
||||
{% else %}
|
||||
<span class="chill-no-data-statement">{{ 'thirdparty.No_phonenumber'|trans }}</span>
|
||||
{% endif %}
|
||||
@@ -173,7 +173,7 @@
|
||||
{% if options['showContacts'] and thirdparty.activeChildren|length > 0 %}
|
||||
<div class="item-row">
|
||||
<div class="item-col"></div>
|
||||
<div class="item-col">
|
||||
<div class="item-col wrap">
|
||||
<h5 class="me-2">{{ 'thirdparty.Children'|trans ~ ': ' }}</h5>
|
||||
{% for c in thirdparty.activeChildren %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
|
@@ -67,10 +67,10 @@
|
||||
<dt>{{ 'Phonenumber'|trans }}</dt>
|
||||
<dd>
|
||||
{% if thirdParty.telephone == null %}
|
||||
<span class="chill-no-data-statement">{{ 'No phone given'|trans }}</span>
|
||||
<span class="chill-no-data-statement">{{ 'thirdparty.No_phonenumber'|trans }}</span>
|
||||
{% else %}
|
||||
<a href="{{ 'tel:' ~ thirdParty.telephone }}">
|
||||
{{ thirdParty.telephone|chill_print_or_message("thirdparty.No_phonenumber") }}
|
||||
<a href="{{ 'tel:' ~ thirdParty.telephone|phone_number_format('E164') }}">
|
||||
{{ thirdParty.telephone|chill_format_phonenumber }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</dd>
|
||||
|
@@ -11,7 +11,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ThirdPartyBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||
use Chill\ThirdPartyBundle\Entity\ThirdPartyCategory;
|
||||
use Chill\ThirdPartyBundle\Templating\Entity\ThirdPartyRender;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
@@ -23,9 +25,14 @@ class ThirdPartyNormalizer implements NormalizerAwareInterface, NormalizerInterf
|
||||
|
||||
private ThirdPartyRender $thirdPartyRender;
|
||||
|
||||
public function __construct(ThirdPartyRender $thirdPartyRender)
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ThirdPartyRender $thirdPartyRender,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->thirdPartyRender = $thirdPartyRender;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,13 +47,26 @@ class ThirdPartyNormalizer implements NormalizerAwareInterface, NormalizerInterf
|
||||
'text' => $this->thirdPartyRender->renderString($thirdParty, []),
|
||||
'id' => $thirdParty->getId(),
|
||||
'kind' => $thirdParty->getKind(),
|
||||
'category' => array_map(function ($el) {
|
||||
if ($el instanceof ThirdPartyCategory) {
|
||||
return [
|
||||
'text' => $this->translatableStringHelper->localize($el->getName()),
|
||||
'type' => 'thirdparty_category',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'text' => $el,
|
||||
'type' => 'thirdparty_kind',
|
||||
];
|
||||
}, $thirdParty->getTypesAndCategories()),
|
||||
'profession' => $this->normalizer->normalize($thirdParty->getProfession(), $format, $context),
|
||||
'address' => $this->normalizer->normalize($thirdParty->getAddress(), $format, ['address_rendering' => 'short']),
|
||||
'phonenumber' => $thirdParty->getTelephone(),
|
||||
'phonenumber' => $this->normalizer->normalize($thirdParty->getTelephone()),
|
||||
'email' => $thirdParty->getEmail(),
|
||||
'isChild' => $thirdParty->isChild(),
|
||||
'parent' => $this->normalizer->normalize($thirdParty->getParent(), $format, $context),
|
||||
'civility' => $this->normalizer->normalize($thirdParty->getCivility(), $format, $context),
|
||||
'profession' => $this->normalizer->normalize($thirdParty->getProfession(), $format, $context),
|
||||
'contactDataAnonymous' => $thirdParty->isContactDataAnonymous(),
|
||||
];
|
||||
}
|
||||
|
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\ThirdParty;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
|
||||
final class Version20220302143821 extends AbstractMigration implements ContainerAwareInterface
|
||||
{
|
||||
use ContainerAwareTrait;
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone TYPE VARCHAR(64)');
|
||||
$this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone DROP DEFAULT');
|
||||
$this->addSql('COMMENT ON COLUMN chill_3party.third_party.telephone IS NULL');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Upgrade phonenumber on third parties';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$carrier_code = $this->container
|
||||
->getParameter('chill_main')['phone_helper']['default_carrier_code'];
|
||||
|
||||
if (null === $carrier_code) {
|
||||
throw new RuntimeException('no carrier code');
|
||||
}
|
||||
|
||||
$this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone TYPE VARCHAR(35)');
|
||||
$this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone DROP DEFAULT');
|
||||
$this->addSql('ALTER TABLE chill_3party.third_party ALTER telephone TYPE VARCHAR(35)');
|
||||
$this->addSql('COMMENT ON COLUMN chill_3party.third_party.telephone IS \'(DC2Type:phone_number)\'');
|
||||
|
||||
$this->addSql(
|
||||
'UPDATE chill_3party.third_party SET ' .
|
||||
$this->buildMigrationPhonenumberClause($carrier_code, 'telephone')
|
||||
);
|
||||
}
|
||||
|
||||
private function buildMigrationPhoneNumberClause(string $defaultCarriercode, string $field): string
|
||||
{
|
||||
$util = PhoneNumberUtil::getInstance();
|
||||
|
||||
$countryCode = $util->getCountryCodeForRegion($defaultCarriercode);
|
||||
|
||||
return sprintf('%s=CASE
|
||||
WHEN %s = \'\' THEN NULL
|
||||
WHEN LEFT(%s, 1) = \'0\'
|
||||
THEN \'+%s\' || replace(replace(substr(%s, 2), \'(0)\', \'\'), \' \', \'\')
|
||||
ELSE replace(replace(%s, \'(0)\', \'\'),\' \', \'\')
|
||||
END', $field, $field, $field, $countryCode, $field, $field);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user