AnsweredAssumed Answered

Custom Api and Handlebars

Question asked by Gaelle Fernandez on Aug 13, 2014
Latest reply on Oct 20, 2015 by Gerardo Garcia Lima
Hello fellow Sugarers!

I'm stuck on a very difficult problem :
I've followed Insightful tutorial to create custom buttons and actions :
http://www.insightful.com.au/sugarcrm-how-do-i/creating-custom-button-sugar-7/

Except, i want to display Accounts' billing cities related to the current opportunity.
So i haven't changed a lot of code yet,
And i got this for my custom/modules/Opportunities/client/base/api/CustomOpportunitiesApi.php

<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
 
require_once('data/BeanFactory.php');
 
class CustomOpportunitiesApi extends SugarApi
{
        public function registerApiRest()
        {
                return array(
                        'count_accounts' => array(
                                'reqType' => 'GET',
                                'path' => array('Opportunities','?', 'count_accounts'),
                                'pathVars' => array('module', 'record'),
                                'method' => 'countAccounts',
                                'shortHelp' => 'Count the number of Accounts for the current Opportunitie record',
                                'longHelp' => '',
                        ),
                );
        }
 
        public function countAccounts($api, $args)
        {
                // get the Opportunitie
                $record = BeanFactory::getBean($args['module'], $args['record']);
 
                // check ACL
                if(!$record->ACLAccess('view'))
                {
                        return;
                }
 
                // load accounts relationship
                if(!$record->load_relationship('accounts'))
                {
                        return;
                }
 
                // Figure out the related accounts
                $linkModuleName = $record->accounts->getRelatedModuleName();
                $linkSeed = BeanFactory::newBean($linkModuleName);
 
                // check if we have access to accounts
                if(!$linkSeed->ACLAccess('view'))
                {
                        return;
                }
 
                // get the number of accounts
                $accounts = $record->accounts->getBeans();
 
                // get the primary address cities and the total number of Accounts in each
    $cities = array();
                if(!empty($accounts))
                {
                        foreach($accounts as $acc)
                        {
                                if(!in_array($acc->billing_address_city, array_keys($cities)))
                                {
                                        $cities[$acc->billing_address_city] = 1;
                                }
                                else
                                {
                                        $cities[$acc->billing_address_city]++;
                                }
                        }
                }
 
                return json_encode($cities);
        }
}
 
?>
              
And in custom/modules/Opportunities/client/base/view/record/record.js
I have this :

({        extendsFrom: 'RecordView',
        totalAccountsJSON: {},
 
        initialize: function(options) {
                app.view.invokeParent(this, {type: 'view', name: 'record', method: 'initialize', args:[options]});
    console.log("initiated");
                // add listener for the custom button
                this.context.on('button:create_declavente_button:click', this.count_accounts_code, this);
        },
 
        count_accounts_code: function() {
    //console.log("count_accounts_clicked");
                var OppID = this.model.get('id');
    console.log(OppID);
                app.api.call('GET', app.api.buildURL('Opportunities/' + OppID + '/count_accounts'), null, {
                        success: function(data) {
       console.log(data);
                                app.drawer.open({layout:'count-accounts',context:{totalAccounts: data}});
                        },
                        error: function(error) {
                                app.alert.show("server-error", {
                                        level: 'error',
                                        messages: 'ERR_GENERIC_SERVER_ERROR',
                                        autoClose: false
                                });
                                app.error.handleHttpError(error);
                        }
                });
        }
})


(as you can see, i did not much modifications)
Now, here is my handlebar file custom/modules/Opportunities/client/base/views/count-accounts/count-accounts.hbs

<div class="row">        <div class="span4 offset1">
                <h3>Accounts Count</h3>
                {{#each totalAccounts}}
                  <p>{{@key}}:{{this}}</p>
                {{else}}
                  <p>There are no Accounts in this Opportunitiy.</p>
                {{/each}}
                <br/>
                <a class="btn cancel" href="javascript:void(0);" track="click:close_button" name="close_button">Close</a>
        </div>
</div>

As you can see here again, it is quite the same as on Insightful. For the rest of every files/folder, i've followed insightful instructions, but replacing every "Accounts" by "Opportunities" and every "Contacts" by "Accounts" 
Well, my CustomOpportunitiesApi does work : on my view, when i make a console.log(data), here is the object i get :
Object {Lyon: 1}


And my drawer does open and displays the h3 and the close button. as you can see on my screenshot, Everything is here... EXCEPT the value "1". (which should be displayed by the "{{this}}" on count-accounts.hbs)


I'm new to handlebars, but i've read the documentation, and with the #each block helper, the {{this}} should work.
Please help me get this problem fixed, i need it !!


Have a nice sunny day,
Gaëlle

Outcomes