From aa8d445220ddec38fa7158a9bf5d1ee9fe7243dc Mon Sep 17 00:00:00 2001 From: Damien <damien.burel@maarch.org> Date: Thu, 12 Dec 2019 11:46:16 +0100 Subject: [PATCH] FEAT #12510 TIME 7:00 Autocomplete contacts with parameters --- migration/19.12/1912.sql | 13 +- migration/19.12/migrateContacts.php | 26 ++-- sql/structure.sql | 11 -- .../contact/controllers/ContactController.php | 125 ++++++++++++++---- .../ContactCustomFieldController.php | 4 +- .../models/ContactCustomFieldModel.php | 93 ------------- src/app/contact/models/ContactModel.php | 1 - .../controllers/AutoCompleteController.php | 40 ++++-- .../app/viewer/document-viewer.component.html | 2 +- 9 files changed, 145 insertions(+), 170 deletions(-) delete mode 100644 src/app/contact/models/ContactCustomFieldModel.php diff --git a/migration/19.12/1912.sql b/migration/19.12/1912.sql index 7d7e5992a2d..0b59000b538 100644 --- a/migration/19.12/1912.sql +++ b/migration/19.12/1912.sql @@ -180,18 +180,6 @@ CREATE TABLE contacts_custom_fields_list ) WITH (OIDS=FALSE); -DROP TABLE IF EXISTS contacts_custom_fields; -CREATE TABLE contacts_custom_fields -( - id serial NOT NULL, - contact_id INTEGER NOT NULL, - custom_field_id INTEGER NOT NULL, - value jsonb NOT NULL, - CONSTRAINT contacts_custom_fields_pkey PRIMARY KEY (id), - CONSTRAINT contacts_custom_fields_unique_key UNIQUE (contact_id, custom_field_id) -) -WITH (OIDS=FALSE); - /* INDEXING MODELS */ DROP TABLE IF EXISTS indexing_models; @@ -424,6 +412,7 @@ CREATE TABLE contacts creation_date TIMESTAMP without time zone NOT NULL DEFAULT NOW(), modification_date TIMESTAMP without time zone, enabled boolean NOT NULL DEFAULT TRUE, + custom_fields jsonb, external_id jsonb DEFAULT '{}', CONSTRAINT contacts_pkey PRIMARY KEY (id) ) diff --git a/migration/19.12/migrateContacts.php b/migration/19.12/migrateContacts.php index e4f18783f25..c6e9a85e871 100644 --- a/migration/19.12/migrateContacts.php +++ b/migration/19.12/migrateContacts.php @@ -19,10 +19,6 @@ foreach ($customs as $custom) { 'table' => 'contacts', 'where' => ['id > 0'] ]); - \SrcCore\models\DatabaseModel::delete([ - 'table' => 'contacts_custom_fields', - 'where' => ['id > 0'] - ]); \SrcCore\models\DatabaseModel::delete([ 'table' => 'contacts_custom_fields_list', 'where' => ['id > 0'] @@ -226,15 +222,23 @@ function addCustomFields($args = []) function migrateCustomField($args = []) { - $customFields = []; foreach ($args['contactCustomInfo'] as $key => $value) { if (!empty($value)) { - $id = \Contact\models\ContactCustomFieldModel::create([ - 'contact_id' => $args['newContactId'], - 'custom_field_id' => $args['newCustomFields'][$key], - 'value' => json_encode($value) - ]); - $customFields[$key] = $id; + $contact = \Contact\models\ContactModel::getById(['id' => $args['newContactId'], 'select' => ['custom_fields']]); + $value = json_encode($value); + if (empty($contact['custom_fields'])) { + \Contact\models\ContactModel::update([ + 'postSet' => ['custom_fields' => "jsonb_set('{}', '{{$args['newCustomFields'][$key]}}', '{$value}')"], + 'where' => ['id = ?'], + 'data' => [$args['newContactId']] + ]); + } else { + \Contact\models\ContactModel::update([ + 'postSet' => ['custom_fields' => "jsonb_set(custom_fields, '{{$args['newCustomFields'][$key]}}', '{$value}')"], + 'where' => ['id = ?'], + 'data' => [$args['newContactId']] + ]); + } } } } diff --git a/sql/structure.sql b/sql/structure.sql index fd283503506..3b9596dbada 100755 --- a/sql/structure.sql +++ b/sql/structure.sql @@ -1463,14 +1463,3 @@ CREATE TABLE contacts_custom_fields_list CONSTRAINT contacts_custom_fields_list_unique_key UNIQUE (label) ) WITH (OIDS=FALSE); - -CREATE TABLE contacts_custom_fields -( - id serial NOT NULL, - contact_id INTEGER NOT NULL, - custom_field_id INTEGER NOT NULL, - value jsonb NOT NULL, - CONSTRAINT contacts_custom_fields_pkey PRIMARY KEY (id), - CONSTRAINT contacts_custom_fields_unique_key UNIQUE (contact_id, custom_field_id) -) -WITH (OIDS=FALSE); diff --git a/src/app/contact/controllers/ContactController.php b/src/app/contact/controllers/ContactController.php index 31e67f04095..209c5ee4fcc 100755 --- a/src/app/contact/controllers/ContactController.php +++ b/src/app/contact/controllers/ContactController.php @@ -14,7 +14,6 @@ namespace Contact\controllers; use Contact\models\ContactCustomFieldListModel; -use Contact\models\ContactCustomFieldModel; use Contact\models\ContactFillingModel; use Contact\models\ContactModel; use Contact\models\ContactParameterModel; @@ -86,6 +85,8 @@ class ContactController 'function' => $body['function'] ?? null, 'address_number' => $body['addressNumber'] ?? null, 'address_street' => $body['addressStreet'] ?? null, + 'address_additional1' => $body['addressAdditional1'] ?? null, + 'address_additional2' => $body['addressAdditional2'] ?? null, 'address_postcode' => $body['addressPostcode'] ?? null, 'address_town' => $body['addressTown'] ?? null, 'address_country' => $body['addressCountry'] ?? null, @@ -95,6 +96,7 @@ class ContactController 'notes' => $body['notes'] ?? null, 'creator' => $GLOBALS['id'], 'enabled' => 'true', + 'custom_fields' => !empty($body['customFields']) ? json_encode($body['customFields']) : null, 'external_id' => $externalId ]); @@ -117,8 +119,6 @@ class ContactController 'eventId' => 'contactCreation', ]); - ContactController::createAdjacentData(['body' => $body, 'id' => $id]); - return $response->withJson(['id' => $id]); } @@ -143,6 +143,8 @@ class ContactController 'function' => $rawContact['function'], 'addressNumber' => $rawContact['address_number'], 'addressStreet' => $rawContact['address_street'], + 'addressAdditional1' => $rawContact['address_additional1'], + 'addressAdditional2' => $rawContact['address_additional2'], 'addressPostcode' => $rawContact['address_postcode'], 'addressTown' => $rawContact['address_town'], 'addressCountry' => $rawContact['address_country'], @@ -155,6 +157,7 @@ class ContactController 'enabled' => $rawContact['enabled'], 'creationDate' => $rawContact['creation_date'], 'modificationDate' => $rawContact['modification_date'], + 'customFields' => !empty($rawContact['custom_fields']) ? json_decode($rawContact['custom_fields'], true) : null, 'externalId' => json_decode($rawContact['external_id'], true) ]; @@ -207,6 +210,8 @@ class ContactController 'function' => $body['function'] ?? null, 'address_number' => $body['addressNumber'] ?? null, 'address_street' => $body['addressStreet'] ?? null, + 'address_additional1' => $body['addressAdditional1'] ?? null, + 'address_additional2' => $body['addressAdditional2'] ?? null, 'address_postcode' => $body['addressPostcode'] ?? null, 'address_town' => $body['addressTown'] ?? null, 'address_country' => $body['addressCountry'] ?? null, @@ -215,6 +220,7 @@ class ContactController 'communication_means' => !empty($body['communicationMeans']) ? json_encode($body['communicationMeans']) : null, 'notes' => $body['notes'] ?? null, 'modification_date' => 'CURRENT_TIMESTAMP', + 'custom_fields' => !empty($body['customFields']) ? json_encode($body['customFields']) : null, 'external_id' => $externalId ], 'where' => ['id = ?'], @@ -428,17 +434,14 @@ class ContactController if ($contactsFilling['enable'] && !empty($contactsParameters)) { $contactRaw = ContactModel::getById([ - 'select' => ['civility', 'firstname', 'lastname', 'company', 'department', 'function', 'address_number', 'address_street', 'address_additional1', 'address_additional2', 'address_postcode', 'address_town', 'address_country', 'email', 'phone'], + 'select' => ['civility', 'firstname', 'lastname', 'company', 'department', 'function', 'address_number', 'address_street', 'address_additional1', 'address_additional2', 'address_postcode', 'address_town', 'address_country', 'email', 'phone', 'custom_fields'], 'id' => $aArgs['contactId'] ]); - $contactCustomRaw = ContactCustomFieldModel::getByContactId([ - 'select' => ['value'], - 'contactId' => $aArgs['contactId'] - ]); + $customFields = json_decode($contactRaw['custom_fields'], true); $percent = 0; foreach ($contactsParameters as $ratingColumn) { - if (strpos($ratingColumn['identifier'], 'contactCustomField_') !== false && !empty($contactCustomRaw[str_replace("contactCustomField_", "", $ratingColumn['identifier'])])) { + if (strpos($ratingColumn['identifier'], 'contactCustomField_') !== false && !empty($customFields[str_replace("contactCustomField_", "", $ratingColumn['identifier'])])) { $percent++; } elseif (!empty($contactRaw[$ratingColumn['identifier']])) { $percent++; @@ -759,23 +762,6 @@ class ContactController return true; } - private static function createAdjacentData(array $args) - { - ValidatorModel::notEmpty($args, ['id', 'body']); - ValidatorModel::intVal($args, ['id']); - ValidatorModel::arrayType($args, ['body']); - - $body = $args['body']; - - if (!empty($body['customFields'])) { - foreach ($body['customFields'] as $key => $value) { - ContactCustomFieldModel::create(['contact_id' => $args['id'], 'custom_field_id' => $key, 'value' => json_encode($value)]); - } - } - - return true; - } - public static function getFormattedOnlyContact(array $args) { ValidatorModel::notEmpty($args, ['contact']); @@ -872,4 +858,91 @@ class ContactController return ['contact' => $contact]; } + + public static function getAutocompleteFormat(array $args) + { + ValidatorModel::notEmpty($args, ['id']); + ValidatorModel::intVal($args, ['id']); + + $displayableParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['displayable = ?'], 'data' => [true]]); + + $displayableStdParameters = []; + $displayableCstParameters = []; + foreach ($displayableParameters as $displayableParameter) { + if (strpos($displayableParameter['identifier'], 'contactCustomField_') !== false) { + $displayableCstParameters[] = explode('_', $displayableParameter['identifier'])[1]; + } else { + $displayableStdParameters[] = $displayableParameter['identifier']; + } + } + + if (!empty($displayableCstParameters)) { + $displayableStdParameters[] = 'custom_fields'; + $customFieldsLabels = ContactCustomFieldListModel::get(['select' => ['id', 'label'], 'where' => ['id in (?)'], 'data' => [$displayableCstParameters]]); + } + + $rawContact = ContactModel::getById(['id' => $args['id'], 'select' => $displayableStdParameters]); + $contact = ['type' => 'contact', 'id' => $args['id'], 'lastname' => $rawContact['lastname'], 'company' => $rawContact['company']]; + + if (in_array('civility', $displayableStdParameters)) { + $contact['civility'] = !empty($rawContact['civility']) ? ContactModel::getCivilityLabel(['civilityId' => $rawContact['civility']]) : null; + } + if (in_array('firstname', $displayableStdParameters)) { + $contact['firstname'] = $rawContact['firstname']; + } + if (in_array('department', $displayableStdParameters)) { + $contact['department'] = $rawContact['department']; + } + if (in_array('function', $displayableStdParameters)) { + $contact['function'] = $rawContact['function']; + } + if (in_array('address_number', $displayableStdParameters)) { + $contact['addressNumber'] = $rawContact['address_number']; + } + if (in_array('address_street', $displayableStdParameters)) { + $contact['addressStreet'] = $rawContact['address_street']; + } + if (in_array('address_additional1', $displayableStdParameters)) { + $contact['addressAdditional1'] = $rawContact['address_additional1']; + } + if (in_array('address_additional2', $displayableStdParameters)) { + $contact['addressAdditional2'] = $rawContact['address_additional2']; + } + if (in_array('address_postcode', $displayableStdParameters)) { + $contact['addressPostcode'] = $rawContact['address_postcode']; + } + if (in_array('address_town', $displayableStdParameters)) { + $contact['addressTown'] = $rawContact['address_town']; + } + if (in_array('address_country', $displayableStdParameters)) { + $contact['addressCountry'] = $rawContact['address_country']; + } + if (in_array('email', $displayableStdParameters)) { + $contact['email'] = $rawContact['email']; + } + if (in_array('phone', $displayableStdParameters)) { + $contact['phone'] = $rawContact['phone']; + } + if (in_array('notes', $displayableStdParameters)) { + $contact['notes'] = $rawContact['notes']; + } + + if (!empty($customFieldsLabels)) { + $contact['customFields'] = []; + $customFields = json_decode($rawContact['custom_fields'], true); + foreach ($customFieldsLabels as $customFieldsLabel) { + $contact['customFields'][$customFieldsLabel['id']] = [ + 'label' => $customFieldsLabel['label'], + 'value' => $customFields[$customFieldsLabel['id']] ?? null + ]; + } + } + + $rate = ContactController::getFillingRate(['contactId' => $args['id']]); + if (!empty($rate)) { + $contact['fillingRate'] = $rate; + } + + return $contact; + } } diff --git a/src/app/contact/controllers/ContactCustomFieldController.php b/src/app/contact/controllers/ContactCustomFieldController.php index 47a014010d4..2b851b2cda7 100644 --- a/src/app/contact/controllers/ContactCustomFieldController.php +++ b/src/app/contact/controllers/ContactCustomFieldController.php @@ -14,7 +14,7 @@ namespace Contact\controllers; use Contact\models\ContactCustomFieldListModel; -use Contact\models\ContactCustomFieldModel; +use Contact\models\ContactModel; use Contact\models\ContactParameterModel; use Group\controllers\PrivilegeController; use History\controllers\HistoryController; @@ -139,7 +139,7 @@ class ContactCustomFieldController $field = ContactCustomFieldListModel::getById(['select' => ['label'], 'id' => $args['id']]); - ContactCustomFieldModel::delete(['where' => ['custom_field_id = ?'], 'data' => [$args['id']]]); + ContactModel::update(['postSet' => ['custom_fields' => "custom_fields - '{$args['id']}'"], 'where' => ['1 = ?'], 'data' => [1]]); ContactParameterModel::delete(['where' => ['identifier = ?'], 'data' => ['contactCustomField_' . $args['id']]]); ContactCustomFieldListModel::delete([ diff --git a/src/app/contact/models/ContactCustomFieldModel.php b/src/app/contact/models/ContactCustomFieldModel.php deleted file mode 100644 index 1f9bd25a899..00000000000 --- a/src/app/contact/models/ContactCustomFieldModel.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/** -* Copyright Maarch since 2008 under licence GPLv3. -* See LICENCE.txt file at the root folder for more details. -* This file is part of Maarch software. - -* @brief ResourceFolderModel -* @author dev <dev@maarch.org> -* @ingroup core -*/ - -/** - * @brief Contact Custom Field Model - * @author dev@maarch.org - */ - -namespace Contact\models; - -use SrcCore\models\ValidatorModel; -use SrcCore\models\DatabaseModel; - -class ContactCustomFieldModel -{ - public static function get(array $aArgs) - { - ValidatorModel::arrayType($aArgs, ['select', 'where', 'data', 'orderBy']); - ValidatorModel::intType($aArgs, ['limit']); - - $customFields = DatabaseModel::select([ - 'select' => empty($aArgs['select']) ? ['*'] : $aArgs['select'], - 'table' => ['contacts_custom_fields'], - 'where' => empty($aArgs['where']) ? [] : $aArgs['where'], - 'data' => empty($aArgs['data']) ? [] : $aArgs['data'], - 'order_by' => empty($aArgs['orderBy']) ? [] : $aArgs['orderBy'], - 'limit' => empty($aArgs['limit']) ? 0 : $aArgs['limit'] - ]); - - return $customFields; - } - - public static function getByContactId(array $args) - { - ValidatorModel::notEmpty($args, ['contactId', 'select']); - ValidatorModel::intVal($args, ['contactId']); - ValidatorModel::arrayType($args, ['select']); - - $contact = DatabaseModel::select([ - 'select' => $args['select'], - 'table' => ['contacts_custom_fields'], - 'where' => ['contact_id = ?'], - 'data' => [$args['contactId']], - ]); - - if (empty($contact[0])) { - return []; - } - - return $contact[0]; - } - - public static function create(array $args) - { - ValidatorModel::notEmpty($args, ['contact_id', 'custom_field_id', 'value']); - ValidatorModel::intVal($args, ['contact_id', 'custom_field_id']); - ValidatorModel::stringType($args, ['value']); - - DatabaseModel::insert([ - 'table' => 'contacts_custom_fields', - 'columnsValues' => [ - 'contact_id' => $args['contact_id'], - 'custom_field_id' => $args['custom_field_id'], - 'value' => $args['value'], - ] - ]); - - return true; - } - - public static function delete(array $args) - { - ValidatorModel::notEmpty($args, ['where', 'data']); - ValidatorModel::arrayType($args, ['where', 'data']); - - DatabaseModel::delete([ - 'table' => 'contacts_custom_fields', - 'where' => $args['where'], - 'data' => $args['data'] - ]); - - return true; - } -} diff --git a/src/app/contact/models/ContactModel.php b/src/app/contact/models/ContactModel.php index 2266cd98adc..b81787d7f84 100755 --- a/src/app/contact/models/ContactModel.php +++ b/src/app/contact/models/ContactModel.php @@ -14,7 +14,6 @@ namespace Contact\models; -use Resource\models\ResModel; use Resource\models\ResourceContactModel; use SrcCore\models\CoreConfigModel; use SrcCore\models\DatabaseModel; diff --git a/src/core/controllers/AutoCompleteController.php b/src/core/controllers/AutoCompleteController.php index 5e8ca256370..6bbd1247c62 100755 --- a/src/core/controllers/AutoCompleteController.php +++ b/src/core/controllers/AutoCompleteController.php @@ -15,8 +15,10 @@ namespace SrcCore\controllers; use Contact\controllers\ContactController; +use Contact\models\ContactCustomFieldListModel; use Contact\models\ContactGroupModel; use Contact\models\ContactModel; +use Contact\models\ContactParameterModel; use Entity\models\EntityModel; use Respect\Validation\Validator; use Slim\Http\Request; @@ -155,28 +157,42 @@ class AutoCompleteController //Contacts $autocompleteContacts = []; if (empty($queryParams['noContacts'])) { - $fields = ['firstname', 'lastname', 'company', 'address_number', 'address_street', 'address_town', 'address_postcode']; + $searchableParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['searchable = ?'], 'data' => [true]]); + + $fields = []; + $searchableCstParameters = []; + foreach ($searchableParameters as $searchableParameter) { + if (strpos($searchableParameter['identifier'], 'contactCustomField_') !== false) { + $searchableCstParameters[] = explode('_', $searchableParameter['identifier'])[1]; + } else { + $fields[] = $searchableParameter['identifier']; + } + } + + foreach ($searchableCstParameters as $cstParameter) { + $fields[] = "custom_fields->>'{$cstParameter}'"; + } + $fieldsNumber = count($fields); $fields = AutoCompleteController::getUnsensitiveFieldsForRequest(['fields' => $fields]); + $requestData = AutoCompleteController::getDataForRequest([ 'search' => $queryParams['search'], 'fields' => $fields, 'where' => ['enabled = ?'], 'data' => [true], - 'fieldsNumber' => 7, + 'fieldsNumber' => $fieldsNumber, ]); $contacts = ContactModel::get([ - 'select' => ['*'], + 'select' => ['id'], 'where' => $requestData['where'], 'data' => $requestData['data'], 'orderBy' => ['company', 'lastname'], 'limit' => self::TINY_LIMIT ]); - $color = isset($queryParams['color']) && filter_var($queryParams['color'], FILTER_VALIDATE_BOOLEAN); - foreach ($contacts as $contact) { - $autocompleteContacts[] = ContactController::getFormattedContactWithAddress(['contact' => $contact, 'color' => $color])['contact']; + $autocompleteContacts[] = ContactController::getAutocompleteFormat(['id' => $contact['id']]); } } @@ -205,8 +221,8 @@ class AutoCompleteController $autocompleteUsers[] = [ 'type' => 'user', 'id' => $user['id'], - 'idToDisplay' => "{$user['firstname']} {$user['lastname']}", - 'otherInfo' => "{$user['firstname']} {$user['lastname']}" + 'firstname' => $user['firstname'], + 'lastname' => $user['lastname'] ]; } } @@ -236,8 +252,7 @@ class AutoCompleteController $autocompleteEntities[] = [ 'type' => 'entity', 'id' => $value['id'], - 'idToDisplay' => $value['entity_label'], - 'otherInfo' => $value['short_label'] + 'lastname' => $value['entity_label'] ]; } } @@ -267,8 +282,7 @@ class AutoCompleteController $autocompleteContactsGroups[] = [ 'type' => 'contactGroup', 'id' => $value['id'], - 'idToDisplay' => $value['label'], - 'otherInfo' => $value['label'] + 'lastname' => $value['label'] ]; } } @@ -813,7 +827,7 @@ class AutoCompleteController $fields[$key] .= "ilike translate(?, 'ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽÃÃÑÒÓÔÕÖØÙÚÛÜÃÞßà áâãäåæçèéêëìÃîïðñòóôõöøùúûýýþÿŔŕ', 'aaaaaaaceeeeiiiidnoooooouuuuybsaaaaaaaceeeeiiiidnoooooouuuyybyRr')"; } $fields = implode(' OR ', $fields); - $fields = "($fields)"; + $fields = "({$fields})"; return $fields; } diff --git a/src/frontend/app/viewer/document-viewer.component.html b/src/frontend/app/viewer/document-viewer.component.html index ceecffcea2c..8daf906ad69 100644 --- a/src/frontend/app/viewer/document-viewer.component.html +++ b/src/frontend/app/viewer/document-viewer.component.html @@ -1,4 +1,4 @@ -<ng-container *ngIf="editInProgress && edition !== 'onlyoffice'; else elseTemplate"> +<ng-container *ngIf="editInProgress && edition !== 'onlyoffice'"> <div class="editInProgress"> <i class="fas fa-file-word bounce"></i> <div> -- GitLab