fix canonicalization and show only active children in form

This commit is contained in:
Julien Fastré 2021-10-08 11:30:35 +02:00
parent 58ddbfb67b
commit 9a708ca618
6 changed files with 113 additions and 32 deletions

View File

@ -85,6 +85,10 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
private ?string $nameCompany = "";
/**
* Canonicalized form composed of name, company name and acronym.
*
* This field is read-only, and is generated on database side.
*
* @ORM\Column(name="canonicalized", type="text", options={"default":""})
*/
private ?string $canonicalized = "";
@ -116,7 +120,7 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
/**
* Contact Persons: One Institutional ThirdParty has Many Contact Persons
* @ORM\OneToMany(targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty", mappedBy="parent",
* cascade={"persist"})
* cascade={"persist"}, orphanRemoval=true)
* @var ThirdParty[]|Collection
* @Assert\Valid(traverse=true)
*/
@ -319,6 +323,17 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
return $this->email;
}
public function isContactDataAnonymous(): bool
{
return $this->contactDataAnonymous;
}
public function setContactDataAnonymous(bool $contactDataAnonymous): ThirdParty
{
$this->contactDataAnonymous = $contactDataAnonymous;
return $this;
}
/**
* Set comment.
*
@ -570,6 +585,47 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
return $this->children;
}
/**
* Get the children where active = true
*
* @return Collection
*/
public function getActiveChildren(): Collection
{
return $this->children->filter(fn (ThirdParty $tp) => $tp->getActive());
}
/**
* Add a child and set the child as active
*
* Method used in conjonction with getActiveChildren in form.
*
* @internal use the method addChild
* @param ThirdParty $child
* @return $this
*/
public function addActiveChild(ThirdParty $child): self
{
$child->setActive(true);
return $this->addChild($child);
}
/**
* mark the child as unactive, but keep the child existing in the
* database. To effectively remove the child, use removeChild instead.
*
* @param ThirdParty $child
* @return $this
*/
public function removeActiveChild(ThirdParty $child): self
{
$child->setActive(false);
return $this;
}
/**
* @param ThirdParty $child
* @return $this
@ -583,13 +639,17 @@ class ThirdParty implements TrackCreationInterface, TrackUpdateInterface
}
/**
* Remove the child from the database.
*
* If you want to keep the child into the database
* but desactivate it, use removeActiveChildren instead.
*
* @param ThirdParty $child
* @return $this
*/
public function removeChild(ThirdParty $child): self
{
$this->children->removeElement($child);
$child->setActive(false);
return $this;
}

View File

@ -16,6 +16,7 @@ use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
@ -138,6 +139,10 @@ class ThirdPartyType extends AbstractType
'placeholder' => 'thirdparty.choose profession',
'required' => false
])
->add('contactDataAnonymous', CheckboxType::class, [
'required' => false,
'label' => 'thirdparty.Contact data are confidential'
])
;
// Institutional ThirdParty (parent)
@ -165,12 +170,13 @@ class ThirdPartyType extends AbstractType
'multiple' => true,
'attr' => ['class' => 'select2']
])
->add('children', ChillCollectionType::class, [
->add('activeChildren', ChillCollectionType::class, [
'entry_type' => ThirdPartyType::class,
'entry_options' => [
'is_child' => true,
'block_name' => 'children'
],
'block_name' => 'active_children',
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,

View File

@ -23,7 +23,7 @@
{{ form_row(form.email) }}
<h2>{{ 'Contacts'|trans }}</h2>
{{ form_widget(form.children) }}
{{ form_widget(form.activeChildren) }}
<div class="mb-3 row">
{{ form_label(form.address) }}

View File

@ -1,5 +1,5 @@
{% block _third_party_children_entry_widget %}
{% block _third_party_active_children_entry_widget %}
<div class="container">
<div class="row">
<div class="form-group col-md-3 mb-3">
@ -19,16 +19,27 @@
</div>
</div>
<div class="row">
<div class="form-group col-md-6 mb-3">
<div class="form-group col-md-5 mb-3">
{{ form_widget(form.telephone) }}
{{ form_errors(form.telephone) }}
{{ form_label(form.telephone) }}
</div>
<div class="form-group col-md-6 mb-3">
<div class="form-group col-md-5 mb-3">
{{ form_widget(form.email) }}
{{ form_errors(form.email) }}
{{ form_label(form.email) }}
</div>
<div class="form-group col-md-2 mb-3">
{{ form_widget(form.contactDataAnonymous) }}
{{ form_label(form.contactDataAnonymous) }}
{{ form_errors(form.contactDataAnonymous) }}
</div>
</div>
<div class="row">
<div class="form-group col-md-12 mb-3">
{{ form_widget(form.comment) }}
{{ form_errors(form.comment) }}
</div>
</div>
</div>
{% endblock %}

View File

@ -20,9 +20,14 @@ class ThirdPartyApiSearch implements SearchApiInterface
return (new SearchApiQuery)
->setSelectKey('tparty')
->setSelectJsonbMetadata("jsonb_build_object('id', tparty.id)")
->setSelectPertinence("SIMILARITY(?, LOWER(UNACCENT(tparty.name)))", [ $pattern ])
->setSelectPertinence("GREATEST(".
"STRICT_WORD_SIMILARITY(LOWER(UNACCENT(?)), tparty.canonicalized),".
"(tparty.canonicalized LIKE '%' || LOWER(UNACCENT(?)) || '%')::int".
")", [ $pattern, $pattern ])
->setFromClause('chill_3party.third_party AS tparty')
->setWhereClause('SIMILARITY(LOWER(UNACCENT(?)), LOWER(UNACCENT(tparty.name))) > 0.20', [ $pattern ])
->setWhereClause("tparty.active IS TRUE ".
"AND (LOWER(UNACCENT(?)) <<% tparty.canonicalized OR ".
"tparty.canonicalized LIKE '%' || LOWER(UNACCENT(?)) || '%')", [ $pattern, $pattern ])
;
}
@ -33,7 +38,7 @@ class ThirdPartyApiSearch implements SearchApiInterface
public function prepare(array $metadatas): void
{
}
public function supportsResult(string $key, array $metadatas): bool

View File

@ -22,19 +22,15 @@ final class Version20211007165001 extends AbstractMigration
$this->addSql("
UPDATE chill_3party.third_party
SET canonicalized =
COALESCE(
UNACCENT(
LOWER(
name ||
CASE WHEN name <> '' THEN ' ' ELSE '' END ||
name_company ||
CASE WHEN name_company <> '' THEN ' ' ELSE '' END ||
acronym ||
CASE WHEN acronym <> '' THEN ' ' ELSE '' END
)
),
''
)
UNACCENT(
LOWER(
name ||
CASE WHEN COALESCE(name_company, '') <> '' THEN ' ' ELSE '' END ||
COALESCE(name_company, '') ||
CASE WHEN COALESCE(acronym, '') <> '' THEN ' ' ELSE '' END ||
COALESCE(acronym, '')
)
)
");
$this->addSql("
CREATE OR REPLACE FUNCTION chill_3party.canonicalize() RETURNS TRIGGER
@ -42,14 +38,17 @@ final class Version20211007165001 extends AbstractMigration
AS
$$
BEGIN
NEW.canonicalized = UNACCENT(LOWER(
NEW.name ||
CASE WHEN NEW.name <> '' THEN ' ' ELSE '' END ||
NEW.name_company ||
CASE WHEN NEW.name_company <> '' THEN ' ' ELSE '' END ||
NEW.acronym ||
CASE WHEN NEW.acronym <> '' THEN ' ' ELSE '' END
));
NEW.canonicalized =
UNACCENT(
LOWER(
name ||
CASE WHEN COALESCE(name_company, '') <> '' THEN ' ' ELSE '' END ||
COALESCE(name_company, '') ||
CASE WHEN COALESCE(acronym, '') <> '' THEN ' ' ELSE '' END ||
COALESCE(acronym, '')
)
)
;
return NEW;
END
@ -71,7 +70,7 @@ final class Version20211007165001 extends AbstractMigration
");
$this->addSql("
CREATE INDEX chill_custom_canonicalized_trgm_idx_gist
ON chill_3party.third_party USING GIST (canonicalized gist_trgm_ops)
ON chill_3party.third_party USING GIST (canonicalized gist_trgm_ops) WHERE active IS TRUE
");
}