Linked Fields in n:n Relationships

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • agri
    commented on 's reply
    Hi Tanja,
    this is an old post, I know. Still, I have the same task and try to understand the procedure. I get the part
    "Opportunity > links > contacts has "additionalColumns" option - here you need to define your additional fields for data base",
    but I dont understand what is meant by
    "in Contact fields defined opportunityRole field,
    in Opportunity > contactRole and contacts with columns."
    Could you explain this again in a few words?
    Thank you
    Uli
    p.s.: Does this apply to EspoCRM v. 8.x?

  • pathfinder
    replied
    Thanks rabii, i will try this!

    Leave a comment:


  • rabii
    commented on 's reply
    I am not sure why would you need to do that because you can create a report that does this for you instead of creating new entities. However if this what you need then, follow these steps: (all of this can be done using Entity Manager through UI and using formula).

    1 - You create a relationship between "monthly opportunities" and "opportunity" entities (one-to-many) meaning one (monthly opportunity) has many (opportunities).
    2 - Add a currency field call it (totalValue) on the monthly opportunities entity
    3 - Add this formula to your monthly opportunities entity to calculate the totals of related opportunities (amount)
    Code:
    totalValue = entity\sumRelated('opportunities', 'amountConverted');
    Don't forget to place the fields/list on the UI once you created the relationships.

    Hope this helps

  • pathfinder
    commented on 's reply
    Hi, for example:

    I've created several opportunities, so I would like to summarize the total value of all the opportunities for a specific month. I created a separate entity "monthly opportunities", so would like to link the opportunities (that I choose) to this entity, to create a record.

    I have NO programming skills. So I cant do it in code.

  • rabii
    commented on 's reply
    what do you mean by linking fields in different entities ? do you linking two different entities ?

  • pathfinder
    replied
    Hi, is there any way of linking fields in different entities? Non coding way. I'm not a programmer. Don't know how to access the code.
    Thanks!

    Leave a comment:


  • saled
    replied
    ok...

    then I have this in my Company.json file :

    Code:
            "accounts": {
                "type": "linkMultiple",
                "layoutDetailDisabled": false,
                "layoutListDisabled": true,
                "layoutMassUpdateDisabled": false,
                "importDisabled": false,
                "noLoad": false,
                "isCustom": true,
                "view": "custom:views/company/fields/accounts",
                "columns": {
                    "shares": "companyShares",
                    "isInactive": "CompanyLinkIsInactive"
                }
           }    
        },
    and the file /client/custom/src/views/company/fields/accounts.js :

    It's a copy of the client/modules/crm/src/views/contact/fields/accounts.js file, except the first line (Espo.define) and the replacement of "role" by "shares".




    Code:
    Espo.define('custom:views/company/fields/accounts', 'views/fields/link-multiple-with-columns', function (Dep) {
    
        return Dep.extend({
     
            roleType: 'varchar',
    
            events: {
                'click [data-action="switchPrimary"]': function (e) {
                    $target = $(e.currentTarget);
                    var id = $target.data('id');
    
                    if (!$target.hasClass('active')) {
                        this.$el.find('button[data-action="switchPrimary"]').removeClass('active').children().addClass('text-muted');
                        $target.addClass('active').children().removeClass('text-muted');
                        this.setPrimaryId(id);
                    }
                }
            },
    
            getAttributeList: function () {
                var list = Dep.prototype.getAttributeList.call(this);
                list.push('accountId');
                list.push('accountName');
                list.push('shares');
                return list;
            },
    
            setup: function () {
                Dep.prototype.setup.call(this);
    
                this.primaryIdFieldName = 'accountId';
                this.primaryNameFieldName = 'accountName';
                this.primarySharesFieldName = 'shares';
    
                this.primaryId = this.model.get(this.primaryIdFieldName);
                this.primaryName = this.model.get(this.primaryNameFieldName);
    
                this.listenTo(this.model, 'change:' + this.primaryIdFieldName, function () {
                    this.primaryId = this.model.get(this.primaryIdFieldName);
                    this.primaryName = this.model.get(this.primaryNameFieldName);
                }, this);
    
    
                if (this.mode === 'edit' || this.mode === 'detail') {
                    this.events['click a[data-action="setPrimary"]'] = function (e) {
                        var id = $(e.currentTarget).data('id');
                        this.setPrimaryId(id);
                        this.reRender();
                    }
                }
            },
    
            setPrimaryId: function (id) {
                this.primaryId = id;
                if (id) {
                    this.primaryName = this.nameHash[id];
                } else {
                    this.primaryName = null;
                }
    
                this.trigger('change');
            },
    
            renderLinks: function () {
                if (this.primaryId) {
                    this.addLinkHtml(this.primaryId, this.primaryName);
                }
                this.ids.forEach(function (id) {
                    if (id != this.primaryId) {
                        this.addLinkHtml(id, this.nameHash[id]);
                    }
                }, this);
            },
    
            getValueForDisplay: function () {
                if (this.mode == 'detail' || this.mode == 'list') {
                    var names = [];
                    if (this.primaryId) {
                        names.push(this.getDetailLinkHtml(this.primaryId, this.primaryName));
                    }
                    this.ids.forEach(function (id) {
                        if (id != this.primaryId) {
                            names.push(this.getDetailLinkHtml(id));
                        }
                    }, this);
                    return names.join('');
                }
            },
    
            getDetailLinkHtml: function (id, name) {
                var html = Dep.prototype.getDetailLinkHtml.call(this, id, name);
                if (this.getColumnValue(id, 'isInactive')) {
                    var $el = $(html);
                    $el.find('a').css('text-decoration', 'line-through');
                    return $el.prop('outerHTML');
                }
                return html;
            },
    
            afterAddLink: function (id) {
                if (this.ids.length === 1) {
                    this.primaryId = id;
                    this.primaryName = this.nameHash[id];
                }
                this.controlPrimaryAppearance();
            },
    
            afterDeleteLink: function (id) {
                if (this.ids.length === 0) {
                    this.primaryId = null;
                    this.primaryName = null;
                    return;
                }
                if (id === this.primaryId) {
                    this.primaryId = this.ids[0];
                    this.primaryName = this.nameHash[this.primaryId];
                }
                this.controlPrimaryAppearance();
            },
    
            controlPrimaryAppearance: function () {
                this.$el.find('li.set-primary-list-item').removeClass('hidden');
                if (this.primaryId) {
                    this.$el.find('li.set-primary-list-item[data-id="'+this.primaryId+'"]').addClass('hidden');
                }
            },
    
            addLinkHtml: function (id, name) {
                if (this.mode == 'search') {
                    return Dep.prototype.addLinkHtml.call(this, id, name);
                }
    
                var $el = Dep.prototype.addLinkHtml.call(this, id, name);
    
                var isPrimary = (id == this.primaryId);
    
                var $a = $(
                    '<a href="javascript:" data-action="setPrimary" data-id="' + id+ '"</a>' +
                    this.translate('Set Primary', 'labels', 'Account') +
                    '</a>'
                );
    
                var $li = $('<li class="set-primary-list-item" data-id="'+id+'">').append($a);
    
                if (isPrimary || this.ids.length === 1) {
                    $li.addClass('hidden');
                }
    
                $el.find('ul.dropdown-menu').append($li);
    
    
                if (this.getColumnValue(id, 'isInactive')) {
                    $el.find('div.link-item-name').css('text-decoration', 'line-through');
                }
            },
    
            afterRender: function () {
                Dep.prototype.afterRender.call(this);
            },
    
            fetch: function () {
                var data = Dep.prototype.fetch.call(this);
    
                data[this.primaryIdFieldName] = this.primaryId;
                data[this.primaryNameFieldName] = this.primaryName;
                data[this.primarySharesFieldName] = (this.columns[this.primaryId] || {}).shares || null;
    
                data.accountIsInactive = (this.columns[this.primaryId] || {}).isInactive || false;
    
                return data;
            }
    
        });
    
    });
    ... But nothing on the interface. the field "shares" and companyLinkIsactive appears nowhere...



    Leave a comment:


  • saled
    replied
    Thanks! You're used to read this code!!
    I'm not...

    Leave a comment:


  • tanya
    replied
    yeah, right (about the view name and the path)
    but
    as I see, you define the view in links accounts, but you need to do it in fields section
    check the example again



    Leave a comment:


  • saled
    replied
    so...

    for the view, the accounts.js file must be created in the client/custom/src/views/company/fields folder?

    and defined in my Company.json file as bellow ?
    "accounts": { "type": "hasMany", "relationName": "accountCompany", "foreign": "companies", "entity": "Account", "audited": true, "isCustom": true, "view": "custom:views/company/fields/accounts", "additionalColumns": { "shares": { "type": "int" }, "isInactive": { "type": "bool", "default": false } }, "layoutRelationshipsDisabled": true } ?




    Leave a comment:


  • saled
    replied
    Thanks!

    Leave a comment:


  • tanya
    replied
    only in custom/Espo/Custom/Resources/metadata/entityDefs/
    Account.json and Company.json (or other name)

    In this case the modification is upgrade safe.

    Leave a comment:


  • saled
    replied
    I want to modify a n:n link between the entity Account a a new entity type "comptany". the company.json file to modify is in "custom/Espo/Custom/Resources/metadata/entityDefs/" and not in "application/Espo/Modules/Crm/Resources/metadata/entityDefs/", is it correct?

    Leave a comment:


  • tanya
    replied


    Example:

    application/Espo/Modules/Crm/Resources/metadata/entityDefs/Contact.json > fields > accounts > view
    client/modules/crm/src/views/contact/fields/accounts.js

    Leave a comment:


  • saled
    replied
    Hi,
    How to create a view for the linkMultiple field ?

    Leave a comment:

Working...