custom entity type Person as attendee

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • item
    Active Community Member
    • Mar 2017
    • 1476

    custom entity type Person as attendee

    Hello,

    is possible to have a cutom entity as attendees in Meeting and Call ?

    Thanks
    Attached Files
    If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​
  • telecastg
    Active Community Member
    • Jun 2018
    • 907

    #2
    Hello item, here's how I added a custom entity "Service Tech" as a possible meeting attendee (see the attached image)

    1) Go to Administration > Entity Manager > Meeting > Relationships and create a new many-to-many relationship between Meeting and Service Tech
    With this action Espo will automatically:
    a) Create a new database table meeting-service-tech to link both entities in a many to many relationship
    b) Create a custom entityDefs metadata file for Meeting and for Service Tech with the new relationship specification
    c) Create new language file under your default language for the labels.

    2) Create a custom clientDefs metadata file for Meeting, specifying a custom view to be used to render the Meeting's Attendees panel.
    custom/Espo/Custom/Resources/metadata/clientDefs/Meeting.json

    Code:
    {
        "sidePanels":{
            "detail":[
                {
                    "name":"attendees",
                    "label":"Attendees",
    [COLOR=#FFA500]              "view":"custom:views/meeting/record/panels/attendees",[/COLOR]
                    "options":{
                        "fieldList":[
                            "users",
                            "contacts",
                            "leads"
                        ]
                    },
                    "sticked": true,
                    "isForm": true,
                    "notRefreshable": true
                }
            ],
            "detailSmall":[
                {
                    "name":"attendees",
                    "label":"Attendees",
    [COLOR=#FFA500]              "view":"custom:views/meeting/record/panels/attendees",[/COLOR]
                    "sticked": true,
                    "isForm": true,
                    "notRefreshable": true
                }
            ],
            "edit":[
                {
                    "name":"attendees",
                    "label":"Attendees",
    [COLOR=#FFA500]              "view":"custom:views/meeting/record/panels/attendees",[/COLOR]
                    "sticked": true,
                    "isForm": true,
                    "notRefreshable": true
                }
            ],
            "editSmall":[
                {
                    "name":"attendees",
                    "label":"Attendees",
    [COLOR=#FFA500]              "view":"custom:views/meeting/record/panels/attendees",[/COLOR]
                    "sticked": true,
                    "isForm": true,
                    "notRefreshable": true
                }
            ]
        }
    }
    3) Create the custom view script to render the modified Attendees panel.
    client/custom/src/views/meeting/record/panels/attendees.js
    Code:
    Espo.define('[COLOR=#FFA500]custom:views/meeting/record/panels/attendees[/COLOR]', 'crm:views/meeting/record/panels/attendees', function (Dep) {
    
        return Dep.extend({
    
            setupFields: function () {
                this.fieldList = [];
    
                this.fieldList.push('users');
    
                if (this.getAcl().check('Contact') && !this.getMetadata().get('scopes.Contact.disabled')) {
                    this.fieldList.push('contacts');
                }
                if (this.getAcl().check('Lead') && !this.getMetadata().get('scopes.Lead.disabled')) {
                    this.fieldList.push('leads');
                }
                if (this.getAcl().check('ServiceTech') && !this.getMetadata().get('scopes.ServiceTech.disabled')) {
                    this.fieldList.push('serviceTechs');
                }
            }
    
        });
    
    });
    4) Go to Administration > Rebuild and refresh the page.

    To do the same for Call repeat Steps 1 and 2 for Call only, the front-end view client/custom/src/views/meeting/record/panels/attendees is the same for both entities.

    Saludos
    Last edited by telecastg; 04-28-2020, 05:09 PM.

    Comment

    • item
      Active Community Member
      • Mar 2017
      • 1476

      #3
      telecastg nice wonderfull ..
      i have now the front-end .. i think missing back-end (field accept/decline/tentative), loadAdditionalColum.. this i will look core code for see how do. and post my result
      Many thanks.
      If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

      Comment


      • telecastg
        telecastg commented
        Editing a comment
        You're welcome
    • item
      Active Community Member
      • Mar 2017
      • 1476

      #4
      Hello telecastg

      progress this work, i can change value of "status" and it's reflected in database..

      meeting.json
      PHP Code:
      {
      "fields": {
      "parent": {
      "entityList": [
      "Account",
      "Lead",
      "Contact",
      "Opportunity",
      "Case",
      "Patient"
      ]
      },
      "patients": {
      "type": "linkMultiple",
      "layoutDetailDisabled": false,
      "layoutMassUpdateDisabled": false,
      "importDisabled": false,
      "noLoad": false,
      "isCustom": true,
      "view": "crm:views/meeting/fields/contacts",
      "columns": {
      "status": "acceptanceStatus"
      },
      "additionalAttributeList": ["columns"],
      "orderBy": "name"
      }
      },
      "links": {
      "patients": {
      "type": "hasMany",
      "foreign": "meetings",
      "entity": "Patient",
      "audited": false,
      "isCustom": true,
      "additionalColumns": {
      "status": {
      "type": "varchar",
      "len": "36",
      "default": "None"
      }
      },
      "columnAttributeMap": {
      "status": "acceptanceStatus"
      }
      }
      }
      } 
      
      patient.json
      PHP Code:
      
      "acceptanceStatus": {
      "type": "varchar",
      "notStorable": true,
      "exportDisabled": true,
      "disabled": true
      },
      "acceptanceStatusMeetings": {
      "type": "enum",
      "notStorable": true,
      "directUpdateDisabled": true,
      "layoutAvailabilityList": ["filters"],
      "importDisabled": true,
      "exportDisabled": true,
      "view": "crm:views/lead/fields/acceptance-status",
      "link": "meetings",
      "column": "status"
      }
      
      "meetings": {
      "type": "hasMany",
      "foreign": "patients",
      "entity": "Meeting",
      "layoutRelationshipsDisabled": true,
      "audited": false,
      "isCustom": true,
      "columnAttributeMap": {
      "status": "acceptanceStatus"
      }
      } 
      


      If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

      Comment

      • item
        Active Community Member
        • Mar 2017
        • 1476

        #5
        Hello,

        https://github.com/espocrm/espocrm/b...ities.php#L404

        There and another place in same file, we need to add to "switch" another case with custom entity..

        PHP Code:
        
        
        switch ($scope) {
        case 'Contact':
        $link = 'contacts';
        break;
        case 'Lead':
        $link = 'leads';
        break;
        case 'User':
        $link = 'users';
        break;
        case 'Patient':
        $link = 'patients';
        break;
        } 
        
        i don't know how upgrade safe. i think with 6.2 and Defs, this can be refactoring and make full compatible with modification.. maybe feature request
        If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

        Comment

        • telecastg
          Active Community Member
          • Jun 2018
          • 907

          #6
          Hello item , I think that the only way to modify the Activities Service class in an "upgrade safe" way is to actually create a custom Service class, extended from the core "Activities.php" Service class and then create a new "program flow" to invoke that class.

          These diagrams are my interpretation of Espo's program flow, and how Activities are handled now, so as you can see, to invoke a custom Service class, you would need to implement a custom Back-end Controller class that invokes the custom Service class, and possibly a custom router that directs to the custom Back-end Controller when a user clicks a button.

          Click image for larger version  Name:	Program Flow Overview.PNG Views:	0 Size:	13.8 KB ID:	68593Click image for larger version  Name:	Activities Flow Overview.PNG Views:	0 Size:	10.1 KB ID:	68594

          Unfortunately, I don't have any code samples since we haven't customized Activities but hopefully this might help you with this project.

          Comment

          • item
            Active Community Member
            • Mar 2017
            • 1476

            #7
            Hello @telecastg,

            Yes i have do that .. and it's work
            i have just copy past activities.php to custom path and make changement in 3 function

            but with 6.2, i think this can be more easy to customize out-of-box https://docs.espocrm.com/development/orm/#defs
            switch/case can use these new function so no need to do what i have do (hard writed Account/Lead/Contact/...)

            Why i do this : because, without that, patients activity is not listed in activities panels on side panel
            Need to reproduce to Call and Task.


            PHP Code:
            <?php
            /************************************************** **********************
            * This file is part of EspoCRM.
            *
            * EspoCRM - Open Source CRM application.
            * Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
            * Website: https://www.espocrm.com
            *
            * EspoCRM is free software: you can redistribute it and/or modify
            * it under the terms of the GNU General Public License as published by
            * the Free Software Foundation, either version 3 of the License, or
            * (at your option) any later version.
            *
            * EspoCRM is distributed in the hope that it will be useful,
            * but WITHOUT ANY WARRANTY; without even the implied warranty of
            * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
            * GNU General Public License for more details.
            *
            * You should have received a copy of the GNU General Public License
            * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
            *
            * The interactive user interfaces in modified source and object code versions
            * of this program must display Appropriate Legal Notices, as required under
            * Section 5 of the GNU General Public License version 3.
            *
            * In accordance with Section 7(b) of the GNU General Public License version 3,
            * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
            ************************************************** **********************/
            
            namespace Espo\Custom\Services;
            
            use Espo\Core\Exceptions\Error;
            use Espo\Core\Exceptions\NotFound;
            use Espo\Core\Exceptions\Forbidden;
            
            use Espo\ORM\{
            Entity,
            QueryParams\Select,
            };
            
            
            class Activities extends \Espo\Modules\Crm\Services\Activities {
            
            
            
            protected function isPerson($scope)
            {
            return in_array($scope, ['Contact', 'Lead', 'User', 'Patient']) ||
            $this->getMetadata()->get(['scopes', $scope, 'type']) === 'Person';
            }
            
            
            protected function getActivitiesMeetingQuery(
            Entity $entity, array $statusList = [], $isHistory = false, $additinalSelectParams = null
            ) {
            $scope = $entity->getEntityType();
            $id = $entity->id;
            
            $methodName = 'getActivities' . $scope . 'MeetingQuery';
            
            if (method_exists($this, $methodName)) {
            return $this->$methodName($entity, $statusList, $isHistory, $additinalSelectParams);
            }
            
            $selectManager = $this->getSelectManagerFactory()->create('Meeting');
            
            $baseSelectParams = [
            'from' => 'Meeting',
            'select' => [
            'id',
            'name',
            ['dateStart', 'dateStart'],
            ['dateEnd', 'dateEnd'],
            ['dateStartDate', 'dateStartDate'],
            ['dateEndDate', 'dateEndDate'],
            ['VALUE:Meeting', '_scope'],
            'assignedUserId',
            'assignedUserName',
            'parentType',
            'parentId',
            'status',
            'createdAt',
            ['VALUE:', 'hasAttachment'],
            ],
            'whereClause' => [],
            ];
            
            if (!empty($statusList)) {
            $baseSelectParams['whereClause'][] = [
            'status' => $statusList
            ];
            }
            
            $selectParams = $baseSelectParams;
            
            if ($scope == 'Account') {
            $selectParams['whereClause'][] = [
            'OR' => [
            [
            'parentId' => $id,
            'parentType' => 'Account'
            ],
            [
            'accountId' => $id
            ]
            ]
            ];
            } else if ($scope == 'Lead' && $entity->get('createdAccountId')) {
            $selectParams['whereClause'][] = [
            'OR' => [
            [
            'parentId' => $id,
            'parentType' => 'Lead'
            ],
            [
            'accountId' => $entity->get('createdAccountId')
            ]
            ]
            ];
            } else {
            $selectParams['whereClause']['parentId'] = $id;
            $selectParams['whereClause']['parentType'] = $scope;
            }
            
            $selectManager->applyAccess($selectParams);
            
            $selectParams = $selectManager->mergeSelectParams($selectParams, $additinalSelectParams);
            
            $query = Select::fromRaw($selectParams);
            
            if (!$this->isPerson($scope)) {
            return $query;
            }
            
            $queryList = [$query];
            
            $link = null;
            
            switch ($scope) {
            case 'Contact':
            $link = 'contacts';
            break;
            case 'Lead':
            $link = 'leads';
            break;
            case 'User':
            $link = 'users';
            break;
            case 'Patient':
            $link = 'patients';
            }
            
            //$GLOBALS['log']->warning( 'JE SUIS ICI' );
            if (!$link) {
            return $queryList;
            }
            
            $selectParams = $baseSelectParams;
            
            $selectManager->addJoin($link, $selectParams);
            
            $selectParams['whereClause'][$link .'.id'] = $id;
            $selectParams['whereClause'][] = [
            'OR' => [
            'parentType!=' => $scope,
            'parentId!=' => $id,
            'parentType' => null,
            'parentId' => null,
            ]
            ];
            
            $selectManager->applyAccess($selectParams);
            
            $selectParams = $selectManager->mergeSelectParams($selectParams, $additinalSelectParams);
            
            $query = Select::fromRaw($selectParams);
            
            $queryList[] = $query;
            
            return $queryList;
            }
            
            protected function getActivitiesCallQuery(
            Entity $entity, array $statusList = [], $isHistory = false, $additinalSelectParams = null
            ) {
            $scope = $entity->getEntityType();
            $id = $entity->id;
            
            $methodName = 'getActivities' .$scope . 'CallQuery';
            
            if (method_exists($this, $methodName)) {
            return $this->$methodName($entity, $statusList, $isHistory, $additinalSelectParams);
            }
            
            $selectManager = $this->getSelectManagerFactory()->create('Call');
            
            $baseSelectParams = [
            'from' => 'Call',
            'select' => [
            'id',
            'name',
            ['dateStart', 'dateStart'],
            ['dateEnd', 'dateEnd'],
            ['VALUE:', 'dateStartDate'],
            ['VALUE:', 'dateEndDate'],
            ['VALUE:Call', '_scope'],
            'assignedUserId',
            'assignedUserName',
            'parentType',
            'parentId',
            'status',
            'createdAt',
            ['VALUE:', 'hasAttachment'],
            ],
            'whereClause' => [],
            ];
            
            if (!empty($statusList)) {
            $baseSelectParams['whereClause'][] = [
            'status' => $statusList
            ];
            }
            
            $selectParams = $baseSelectParams;
            
            if ($scope == 'Account') {
            $selectParams['whereClause'][] = [
            'OR' => [
            [
            'parentId' => $id,
            'parentType' => 'Account'
            ],
            [
            'accountId' => $id
            ]
            ]
            ];
            } else if ($scope == 'Lead' && $entity->get('createdAccountId')) {
            $selectParams['whereClause'][] = [
            'OR' => [
            [
            'parentId' => $id,
            'parentType' => 'Lead'
            ],
            [
            'accountId' => $entity->get('createdAccountId')
            ]
            ]
            ];
            } else {
            $selectParams['whereClause']['parentId'] = $id;
            $selectParams['whereClause']['parentType'] = $scope;
            }
            
            $selectManager->applyAccess($selectParams);
            
            $selectParams = $selectManager->mergeSelectParams($selectParams, $additinalSelectParams);
            
            $query = Select::fromRaw($selectParams);
            
            if (!$this->isPerson($scope)) {
            return $query;
            }
            
            $queryList = [$query];
            
            $link = null;
            
            switch ($scope) {
            case 'Contact':
            $link = 'contacts';
            break;
            case 'Lead':
            $link = 'leads';
            break;
            case 'User':
            $link = 'users';
            break;
            }
            
            if (!$link) {
            return $queryList;
            }
            
            $selectParams = $baseSelectParams;
            $selectManager->addJoin($link, $selectParams);
            $selectParams['whereClause'][$link .'.id'] = $id;
            $selectParams['whereClause'][] = [
            'OR' => [
            'parentType!=' => $scope,
            'parentId!=' => $id,
            'parentType' => null,
            'parentId' => null,
            ]
            ];
            
            $selectManager->applyAccess($selectParams);
            
            $selectParams = $selectManager->mergeSelectParams($selectParams, $additinalSelectParams);
            
            $query = Select::fromRaw($selectParams);
            
            $queryList[] = $query;
            
            return $queryList;
            }
            
            }
            If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

            Comment

            • telecastg
              Active Community Member
              • Jun 2018
              • 907

              #8
              but with 6.2, i think this can be more easy to customize out-of-box https://docs.espocrm.com/development/orm/#defs
              switch/case can use these new function so no need to do what i have do (hard writed Account/Lead/Contact/...)
              I couldn't follow the instructions, if you use this new feature, could you please post a code example ?, I wish that the official documentation would have more actual samples when describing features so it would be easier to understand.

              Comment

              • item
                Active Community Member
                • Mar 2017
                • 1476

                #9
                Hello telecastg,

                patiente, waiting 6.2 to test

                but look this :

                PHP Code:
                <?php
                if ($scope == 'Account') {
                $selectParams['whereClause'][] = [
                'OR' => [
                [
                'parentId' => $id,
                'parentType' => 'Account'
                ],
                [
                'accountId' => $id
                ]
                ]
                ];
                } else if ($scope == 'Lead' && $entity->get('createdAccountId')) {
                $selectParams['whereClause'][] = [
                'OR' => [
                [
                'parentId' => $id,
                'parentType' => 'Lead'
                ],
                [
                'accountId' => $entity->get('createdAccountId')
                ]
                ]
                ];
                } else {
                $selectParams['whereClause']['parentId'] = $id;
                $selectParams['whereClause']['parentType'] = $scope;
                }
                this can be rewrite .. so (without big brainstorming ) :

                PHP Code:
                
                $selectParams['whereClause'][] = [
                'OR' => [
                [
                'parentId' => $id,
                'parentType' => $scope
                ],
                [
                'accountId' => $id
                ]
                ]
                ]; 
                
                The goal is not have Account, Lead, Contact : hard coded
                Last edited by item; 03-14-2021, 11:01 PM.
                If you could give the project a star on GitHub. EspoCrm believe our work truly deserves more recognition. Thanks.​

                Comment

              Working...