From 6c78b0ba584ccca6ebcafc20df7a5619f50d4460 Mon Sep 17 00:00:00 2001
From: "florian.azizian" <florian.azizian@maarch.org>
Date: Tue, 4 Aug 2020 23:10:56 +0200
Subject: [PATCH] FEAT #13826 TIME 3:45 enable/disable fields in indexing model

---
 migration/20.10/2010.sql                      |  3 +
 sql/structure.sql                             |  1 +
 .../controllers/IndexingModelController.php   | 14 ++--
 .../models/IndexingModelFieldModel.php        |  5 +-
 .../indexing-form.component.html              | 19 ++++--
 .../indexing-form/indexing-form.component.ts  | 66 ++++++++++++++-----
 src/frontend/lang/lang-fr.ts                  |  4 +-
 .../IndexingModelControllerTest.php           | 24 +++++--
 8 files changed, 103 insertions(+), 33 deletions(-)
 mode change 100644 => 100755 src/app/indexingModel/models/IndexingModelFieldModel.php

diff --git a/migration/20.10/2010.sql b/migration/20.10/2010.sql
index f9a247dd0f3..45ba41fcc7b 100755
--- a/migration/20.10/2010.sql
+++ b/migration/20.10/2010.sql
@@ -40,6 +40,9 @@ DO $$ BEGIN
     END IF;
 END$$;
 
+/*INDEXING_MODELS_FIELDS*/
+ALTER TABLE indexing_models_fields DROP COLUMN IF EXISTS enabled;
+ALTER TABLE indexing_models_fields ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT TRUE;
 
 /* CONTACTS GROUPS */
 ALTER TABLE contacts_groups DROP COLUMN IF EXISTS entity_owner;
diff --git a/sql/structure.sql b/sql/structure.sql
index 425193a3c3b..994aaa8e773 100755
--- a/sql/structure.sql
+++ b/sql/structure.sql
@@ -1354,6 +1354,7 @@ CREATE TABLE indexing_models_fields
     model_id INTEGER NOT NULL,
     identifier text NOT NULL,
     mandatory BOOLEAN NOT NULL,
+    enabled BOOLEAN DEFAULT TRUE NOT NULL,
     default_value json,
     unit text NOT NULL,
     CONSTRAINT indexing_models_fields_pkey PRIMARY KEY (id)
diff --git a/src/app/indexingModel/controllers/IndexingModelController.php b/src/app/indexingModel/controllers/IndexingModelController.php
index 094c3f2beac..6b7d642f707 100755
--- a/src/app/indexingModel/controllers/IndexingModelController.php
+++ b/src/app/indexingModel/controllers/IndexingModelController.php
@@ -76,7 +76,7 @@ class IndexingModelController
             return $response->withStatus(400)->withJson(['errors' => 'Model out of perimeter']);
         }
 
-        $fields = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit'], 'where' => ['model_id = ?'], 'data' => [$args['id']]]);
+        $fields = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit', 'enabled'], 'where' => ['model_id = ?'], 'data' => [$args['id']]]);
         foreach ($fields as $key => $value) {
             $fields[$key]['default_value'] = json_decode($value['default_value'], true);
         }
@@ -134,7 +134,7 @@ class IndexingModelController
             }
             $master = $body['master'];
 
-            $fieldsMaster = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit'], 'where' => ['model_id = ?'], 'data' => [$body['master']]]);
+            $fieldsMaster = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit', 'enabled'], 'where' => ['model_id = ?'], 'data' => [$body['master']]]);
             foreach ($fieldsMaster as $key => $value) {
                 $fieldsMaster[$key]['default_value'] = json_decode($value['default_value'], true);
             }
@@ -148,6 +148,9 @@ class IndexingModelController
                 $found = false;
                 foreach ($body['fields'] as $value) {
                     if ($value['identifier'] == $field['identifier'] && $value['mandatory'] == $field['mandatory'] && $value['unit'] == $field['unit']) {
+                        if (!$field['enabled']) {
+                            $value = $field;
+                        }
                         array_push($arrayTmp, $value);
                         $found = true;
                         break;
@@ -196,6 +199,7 @@ class IndexingModelController
                 'model_id'      => $modelId,
                 'identifier'    => $field['identifier'],
                 'mandatory'     => empty($field['mandatory']) ? 'false' : 'true',
+                'enabled'       => $field['enabled'] === false ? 'false' : 'true',
                 'default_value' => !isset($field['default_value']) ? null : json_encode($field['default_value']),
                 'unit'          => $field['unit']
             ]);
@@ -283,7 +287,7 @@ class IndexingModelController
         if (!empty($childrenModels)) {
             // Update children models of master
             foreach ($childrenModels as $child) {
-                $childFields = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit'], 'where' => ['model_id = ?'], 'data' => [$child['id']]]);
+                $childFields = IndexingModelFieldModel::get(['select' => ['identifier', 'mandatory', 'default_value', 'unit', 'enabled'], 'where' => ['model_id = ?'], 'data' => [$child['id']]]);
                 foreach ($childFields as $key => $value) {
                     $childFields[$key]['default_value'] = json_decode($value['default_value'], true);
                 }
@@ -293,7 +297,7 @@ class IndexingModelController
                 foreach ($body['fields'] as $field) {
                     $found = false;
                     foreach ($childFields as $value) {
-                        if ($value['identifier'] == $field['identifier'] && $value['mandatory'] == $field['mandatory'] && $value['unit'] == $field['unit']) {
+                        if ($value['identifier'] == $field['identifier'] && $value['mandatory'] == $field['mandatory'] && $value['unit'] == $field['unit'] && $value['enabled'] == $field['enabled']) {
                             $fieldsToKeep[] = $value;
                             $found = true;
                         }
@@ -322,6 +326,7 @@ class IndexingModelController
                         'model_id'      => $child['id'],
                         'identifier'    => $field['identifier'],
                         'mandatory'     => empty($field['mandatory']) ? 'false' : 'true',
+                        'enabled'       => $field['enabled'] === false ? 'false' : 'true',
                         'default_value' => !isset($field['default_value']) ? null : json_encode($field['default_value']),
                         'unit'          => $field['unit']
                     ]);
@@ -381,6 +386,7 @@ class IndexingModelController
                 'model_id'      => $args['id'],
                 'identifier'    => $field['identifier'],
                 'mandatory'     => empty($field['mandatory']) ? 'false' : 'true',
+                'enabled'       => $field['enabled'] === false ? 'false' : 'true',
                 'default_value' => !isset($field['default_value']) ? null : json_encode($field['default_value']),
                 'unit'          => $field['unit']
             ]);
diff --git a/src/app/indexingModel/models/IndexingModelFieldModel.php b/src/app/indexingModel/models/IndexingModelFieldModel.php
old mode 100644
new mode 100755
index 91bde40f255..0e064052126
--- a/src/app/indexingModel/models/IndexingModelFieldModel.php
+++ b/src/app/indexingModel/models/IndexingModelFieldModel.php
@@ -38,8 +38,8 @@ class IndexingModelFieldModel
 
     public static function create(array $args)
     {
-        ValidatorModel::notEmpty($args, ['model_id', 'identifier', 'mandatory', 'unit']);
-        ValidatorModel::stringType($args, ['mandatory', 'identifier', 'unit']);
+        ValidatorModel::notEmpty($args, ['model_id', 'enabled', 'mandatory', 'identifier', 'unit']);
+        ValidatorModel::stringType($args, ['enabled', 'mandatory', 'identifier', 'unit']);
         ValidatorModel::intVal($args, ['model_id']);
 
         DatabaseModel::insert([
@@ -48,6 +48,7 @@ class IndexingModelFieldModel
                 'model_id'      => $args['model_id'],
                 'identifier'    => $args['identifier'],
                 'mandatory'     => $args['mandatory'],
+                'enabled'       => $args['enabled'],
                 'default_value' => $args['default_value'],
                 'unit'          => $args['unit']
             ]
diff --git a/src/frontend/app/indexation/indexing-form/indexing-form.component.html b/src/frontend/app/indexation/indexing-form/indexing-form.component.html
index 05a9a756d36..2e5737f7d5f 100644
--- a/src/frontend/app/indexation/indexing-form/indexing-form.component.html
+++ b/src/frontend/app/indexation/indexing-form/indexing-form.component.html
@@ -32,19 +32,26 @@
                                 <i *ngIf="adminMode" [title]="lang.move" class="fas fa-bars fa-2x" color="primary"
                                     style="cursor: move" cdkDragHandle></i>&nbsp;
                                 {{field.label}}
-                                <button *ngIf="adminMode && !field.system" mat-icon-button
+                                <button *ngIf="adminMode" mat-icon-button
                                     [matMenuTriggerFor]="fieldActions">
                                     <mat-icon class="fa fa-ellipsis-v" color="secondary"></mat-icon>
                                 </button>
                                 <mat-menu #fieldActions="matMenu">
-                                    <button mat-menu-item (click)="field.mandatory = !field.mandatory">
+                                    <button mat-menu-item (click)="field.mandatory = !field.mandatory" *ngIf="!field.system">
                                         <span *ngIf="!field.mandatory">{{lang.mandatoryField}}</span>
                                         <span *ngIf="field.mandatory">{{lang.optionalField}}</span>
                                     </button>
-                                    <mat-divider></mat-divider>
-                                    <button mat-menu-item (click)="removeItem('indexingModels_'+category,field,i)">
+                                    <mat-divider *ngIf="!field.system"></mat-divider>
+                                    <button mat-menu-item *ngIf="!field.enabled" (click)="enableField(field, true)">
+                                        <span>{{lang.enableField}}</span>
+                                    </button>
+                                    <button mat-menu-item *ngIf="field.enabled" (click)="enableField(field, false)">
+                                        <span>{{lang.disableField}}</span>
+                                    </button>
+                                    <mat-divider *ngIf="!field.system"></mat-divider>
+                                    <button mat-menu-item (click)="removeItem('indexingModels_'+category,field,i)" *ngIf="!field.system">
                                         <mat-icon class="fa fa-trash" color="warn"></mat-icon>
-                                        <span>{{lang.delete}}</span>
+                                        <span>{{lang.delete}} {{field.enabled}} {{arrFormControl[field.identifier].enabled}} {{isAlwaysDisabledField(field)}}</span>
                                     </button>
                                 </mat-menu>
                             </div>
@@ -209,7 +216,7 @@
                             <div style="padding: 10px;font-size: 16px;color: #135F7F;letter-spacing: 2px;font-weight: bold;display: flex;
                                 align-items: center;">
                                 <div style="display: flex;flex: 1;align-items: center;">
-                                    {{lang.diffusionList}} <button mat-icon-button  *ngIf="appDiffusionsList.canUpdateRoles() && canEdit && mode !== 'process'" color="primary"
+                                    {{lang.diffusionList}} <button mat-icon-button  *ngIf="appDiffusionsList.canUpdateRoles() && canEdit && mode !== 'process' && field.enabled" color="primary"
                                             (click)="appDiffusionsList.switchMode()" [title]="lang.modifyDiffusionList">
                                             <mat-icon class="fa fa-edit"></mat-icon>
                                         </button>
diff --git a/src/frontend/app/indexation/indexing-form/indexing-form.component.ts b/src/frontend/app/indexation/indexing-form/indexing-form.component.ts
index 6272a0b1edf..20ec038dd89 100755
--- a/src/frontend/app/indexation/indexing-form/indexing-form.component.ts
+++ b/src/frontend/app/indexation/indexing-form/indexing-form.component.ts
@@ -51,6 +51,7 @@ export class IndexingFormComponent implements OnInit {
             type: 'select',
             system: true,
             mandatory: true,
+            enabled: true,
             default_value: '',
             values: []
         },
@@ -61,6 +62,7 @@ export class IndexingFormComponent implements OnInit {
             type: 'string',
             system: true,
             mandatory: true,
+            enabled: true,
             default_value: '',
             values: []
         },
@@ -84,70 +86,80 @@ export class IndexingFormComponent implements OnInit {
             label: this.lang.getRecipients,
             type: 'autocomplete',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'priority',
             label: this.lang.priority,
             type: 'select',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'confidentiality',
             label: this.lang.confidential,
             type: 'radio',
             default_value: null,
-            values: [{ 'id': true, 'label': this.lang.yes }, { 'id': false, 'label': this.lang.no }]
+            values: [{ 'id': true, 'label': this.lang.yes }, { 'id': false, 'label': this.lang.no }],
+            enabled: true,
         },
         {
             identifier: 'initiator',
             label: this.lang.initiatorEntityAlt,
             type: 'select',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'departureDate',
             label: this.lang.departureDate,
             type: 'date',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'processLimitDate',
             label: this.lang.processLimitDate,
             type: 'date',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'tags',
             label: this.lang.tags,
             type: 'autocomplete',
             default_value: null,
-            values: ['/rest/autocomplete/tags', '/rest/tags']
+            values: ['/rest/autocomplete/tags', '/rest/tags'],
+            enabled: true,
         },
         {
             identifier: 'senders',
             label: this.lang.getSenders,
             type: 'autocomplete',
             default_value: null,
-            values: ['/rest/autocomplete/correspondents']
+            values: ['/rest/autocomplete/correspondents'],
+            enabled: true,
         },
         {
             identifier: 'destination',
             label: this.lang.destination,
             type: 'select',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'folders',
             label: this.lang.folders,
             type: 'autocomplete',
             default_value: null,
-            values: ['/rest/autocomplete/folders', '/rest/folders']
+            values: ['/rest/autocomplete/folders', '/rest/folders'],
+            enabled: true,
         },
         {
             identifier: 'documentDate',
@@ -155,7 +167,8 @@ export class IndexingFormComponent implements OnInit {
             unit: 'mail',
             type: 'date',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
         {
             identifier: 'arrivalDate',
@@ -163,7 +176,8 @@ export class IndexingFormComponent implements OnInit {
             unit: 'mail',
             type: 'date',
             default_value: null,
-            values: []
+            values: [],
+            enabled: true,
         },
     ];
     availableFieldsClone: any[] = [];
@@ -233,6 +247,7 @@ export class IndexingFormComponent implements OnInit {
                     this.availableCustomFields = data.customFields.map((info: any) => {
                         info.identifier = 'indexingCustomField_' + info.id;
                         info.system = false;
+                        info.enabled = true;
                         info.SQLMode = info.SQLMode;
 
                         info.default_value = ['integer', 'string', 'date'].indexOf(info.type) > -1 && !this.functions.empty(info.values) ? info.values[0].key : null;
@@ -287,6 +302,7 @@ export class IndexingFormComponent implements OnInit {
             filter((data: string) => data === 'ok'),
             tap(() => {
                 item.mandatory = false;
+                item.enabled = true;
                 if (item.identifier.indexOf('indexingCustomField') > -1) {
                     this.availableCustomFields.push(item);
                     this[arrTarget].splice(index, 1);
@@ -849,13 +865,31 @@ export class IndexingFormComponent implements OnInit {
         ).subscribe();
     }
 
+    enableField(field: any, enable: boolean) {
+        if (enable) {
+            if (!this.isAlwaysDisabledField(field)) {
+                this.arrFormControl[field.identifier].enable();
+            }
+            field.enabled = true;
+        } else {
+            this.arrFormControl[field.identifier].disable();
+            field.enabled = false;
+        }
+    }
+
+    isAlwaysDisabledField(field: any) {
+        if (this.adminMode && ((['integer', 'string', 'date'].indexOf(field.type) > -1 && !this.functions.empty(field.values)) || field.today)) {
+            return true;
+        }
+        return false;
+    }
+
     initValidator(field: any) {
         let valArr: ValidatorFn[] = [];
 
-        let disabledState: boolean = false;
-
-        if (this.adminMode && ((['integer', 'string', 'date'].indexOf(field.type) > -1 && !this.functions.empty(field.values)) || (field.today && this.adminMode))) {
-            disabledState = true;
+        const disabledState = !field.enabled || this.isAlwaysDisabledField(field);
+        if (!disabledState) {
+            field.enabled = true;
         }
 
         this.arrFormControl[field.identifier] = new FormControl({ value: field.default_value, disabled: disabledState });
diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts
index a25316ba499..63020cef2fb 100755
--- a/src/frontend/lang/lang-fr.ts
+++ b/src/frontend/lang/lang-fr.ts
@@ -1865,5 +1865,7 @@ export const LANG_FR = {
     "hideTool": "Cacher la barre d'outils",
     "showTool": "Afficher la barre d'outils",
     "rest": "Compte de webservice",
-    "mustSuperadmin": "Vous devez être vous-même administrateur pour définir des administrateurs"
+    "mustSuperadmin": "Vous devez être vous-même administrateur pour définir des administrateurs",
+    "enableField": "Activer le champ",
+    "disableField": "Désactiver le champ"
 };
diff --git a/test/unitTests/app/indexingModel/IndexingModelControllerTest.php b/test/unitTests/app/indexingModel/IndexingModelControllerTest.php
index 5b5395b5178..fd99499ad46 100755
--- a/test/unitTests/app/indexingModel/IndexingModelControllerTest.php
+++ b/test/unitTests/app/indexingModel/IndexingModelControllerTest.php
@@ -31,17 +31,20 @@ class IndexingModelControllerTest extends TestCase
                 [
                     'identifier'    => 'subject',
                     'mandatory'     => true,
+                    'enabled'       => true,
                     'default_value' => 'tika',
                     'unit'          => 'mail'
                 ], [
                     'identifier'    => 'doctype',
                     'mandatory'     => true,
+                    'enabled'       => false,
                     'default_value' => 'type_test',
                     'unit'          => 'mail'
                 ],
                 [
                     'identifier'    => 'name',
                     'mandatory'     => true,
+                    ''       => true,
                     'default_value' => 'massala',
                     'unit'          => 'contact'
                 ]
@@ -70,12 +73,15 @@ class IndexingModelControllerTest extends TestCase
         $this->assertSame(false, $responseBody->indexingModel->private);
         $this->assertSame('subject', $responseBody->indexingModel->fields[0]->identifier);
         $this->assertSame(true, $responseBody->indexingModel->fields[0]->mandatory);
+        $this->assertSame(true, $responseBody->indexingModel->fields[0]->enabled);
         $this->assertSame('tika', $responseBody->indexingModel->fields[0]->default_value);
         $this->assertSame('doctype', $responseBody->indexingModel->fields[1]->identifier);
         $this->assertSame(true, $responseBody->indexingModel->fields[1]->mandatory);
+        $this->assertSame(false, $responseBody->indexingModel->fields[1]->enabled);
         $this->assertSame('type_test', $responseBody->indexingModel->fields[1]->default_value);
         $this->assertSame('name', $responseBody->indexingModel->fields[2]->identifier);
         $this->assertSame(true, $responseBody->indexingModel->fields[2]->mandatory);
+        $this->assertSame(true, $responseBody->indexingModel->fields[2]->enabled);
         $this->assertSame('massala', $responseBody->indexingModel->fields[2]->default_value);
 
 
@@ -197,6 +203,7 @@ class IndexingModelControllerTest extends TestCase
         array_push($args['fields'], [
             'identifier'    => 'name',
             'mandatory'     => true,
+            'enabled'       => true,
             'default_value' => 'massala',
             'unit'          => 'contact'
         ]);
@@ -236,18 +243,21 @@ class IndexingModelControllerTest extends TestCase
                 [
                     'identifier'    => 'subject',
                     'mandatory'     => true,
+                    'enabled'       => true,
                     'default_value' => 'butter',
                     'unit'          => 'mail'
                 ],
                 [
                     'identifier'    => 'doctype',
                     'mandatory'     => true,
+                    'enabled'       => true,
                     'default_value' => 'type_test2',
                     'unit'          => 'mail'
                 ],
                 [
                     'identifier'    => 'siret',
                     'mandatory'     => false,
+                    'enabled'       => true,
                     'default_value' => 'chicken',
                     'unit'          => 'classement'
                 ]
@@ -273,16 +283,19 @@ class IndexingModelControllerTest extends TestCase
         $this->assertSame(false, $responseBody->indexingModel->private);
         $this->assertSame('subject', $responseBody->indexingModel->fields[0]->identifier);
         $this->assertSame(true, $responseBody->indexingModel->fields[0]->mandatory);
+        $this->assertSame(true, $responseBody->indexingModel->fields[0]->enabled);
         $this->assertSame('butter', $responseBody->indexingModel->fields[0]->default_value);
         $this->assertSame('mail', $responseBody->indexingModel->fields[0]->unit);
 
         $this->assertSame('doctype', $responseBody->indexingModel->fields[1]->identifier);
         $this->assertSame(true, $responseBody->indexingModel->fields[1]->mandatory);
+        $this->assertSame(true, $responseBody->indexingModel->fields[1]->enabled);
         $this->assertSame('type_test2', $responseBody->indexingModel->fields[1]->default_value);
         $this->assertSame('mail', $responseBody->indexingModel->fields[1]->unit);
 
         $this->assertSame('siret', $responseBody->indexingModel->fields[2]->identifier);
         $this->assertSame(false, $responseBody->indexingModel->fields[2]->mandatory);
+        $this->assertSame(true, $responseBody->indexingModel->fields[2]->enabled);
         $this->assertSame('chicken', $responseBody->indexingModel->fields[2]->default_value);
         $this->assertSame('classement', $responseBody->indexingModel->fields[2]->unit);
 
@@ -299,25 +312,28 @@ class IndexingModelControllerTest extends TestCase
         $foundSubject = false;
         $foundSiret = false;
         foreach ($responseBodyChild->indexingModel->fields as $field) {
-           if ($field->identifier == 'subject') {
+            if ($field->identifier == 'subject') {
                 $foundSubject = true;
 
                 $this->assertSame(true, $field->mandatory);
+                $this->assertSame(true, $field->enabled);
                 $this->assertSame('tika', $field->default_value);
                 $this->assertSame('mail', $field->unit);
-           } else if ($field->identifier == 'doctype') {
+            } elseif ($field->identifier == 'doctype') {
                 $foundDoctype = true;
 
                 $this->assertSame(true, $field->mandatory);
+                $this->assertSame(true, $field->enabled);
                 $this->assertSame('type_test', $field->default_value);
                 $this->assertSame('mail', $field->unit);
-           } else if ($field->identifier == 'siret') {
+            } elseif ($field->identifier == 'siret') {
                 $foundSiret = true;
 
                 $this->assertSame(false, $field->mandatory);
+                $this->assertSame(true, $field->enabled);
                 $this->assertSame('chicken', $field->default_value);
                 $this->assertSame('classement', $field->unit);
-           }
+            }
         }
 
         $this->assertSame(true, $foundSubject);
-- 
GitLab