I use SugarCRM and i try to make a Hook when someone save a opportunity.
This is the situation:
I have the column "Opportunity Amount" and i want to calculate the column "Montant %".
So i have add twoo ligne in the hook:
$hook_array['before_save'] = Array();
$hook_array['before_save'][] = Array(1,'calcul montant heure','custom/modules/Opportunities/calcul.php','calcul','montant');
I add the class file:
<?php
if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
class calcul
{
var $module = "Opportunities";
function montant($bean, $event, $arguments)
{
$bean->Montant_perc = ($bean->amount_usdollar * $bean->Probability (%))/100;
}
}
?>
it does not work but I do not understand why?
thanks for your help
I think that you need to recheck the fields name that you are using in before_save logic hook method becuase it seems to me that you are using field labels instead of field names i.e i think
$bean->Probability (%)
should be
$bean->probability
and as the field saved in db is generally in small letters so you should also check that the field
$bean->Montant_perc
should be
$bean->montant_perc
After making these modification do a Quick Repair and then resave the Opportunity to trigger before_save logic hook
Related
In Suitecrm/SugarCRM 6.5
I need to modify the ListView. Showing the value of a field based on a certain condition.
In the Account module, the name field may be empty based on certain conditions, I require that when this occurs show the value of a custom field. To do this, first I tryied using 'customCode' + smarty as usual in Edit/Detail vies, but in several posts mention that this is not possible in the ListView. The concession is to use logic hooks + a non-db field to store the calculated field. Following this SO answer I have written the following:
Custom field at custom/Extension/modules/Accounts/Ext/Vardefs/custom_field_name_c.php
<?php
$dictionary['Account']['fields']['name_c']['name'] = 'account_name_c';
$dictionary['Account']['fields']['name_c']['vname'] = 'LBL_ACCOUNT_NAME_C';
$dictionary['Account']['fields']['name_c']['type'] = 'varchar';
$dictionary['Account']['fields']['name_c']['len'] = '255';
$dictionary['Account']['fields']['name_c']['source'] = 'non-db';
$dictionary['Account']['fields']['name_c']['dbType'] = 'non-db';
$dictionary['Account']['fields']['name_c']['studio'] = 'visible';
Label at suitecrm/custom/Extension/modules/Accounts/Ext/Language/es_ES.account_name_c.php
<?php
$mod_strings['LBL_ACCOUNT_NAME_C'] = 'Nombre de cuenta';
Logic hook entry at custom/modules/Accounts/logic_hooks.php
$hook_array['process_record'] = Array();
$hook_array['process_record'][] = Array(
2,
'Get proper name',
'custom/modules/Accounts/hooks/ListViewLogicHook.php',
'ListViewLogicHook',
'getProperName'
);
Logic hook at custom/modules/Accounts/hooks/ListViewLogicHook.php
<?php
class ListViewLogicHook
{
public function getProperName(&$bean, $event, $arguments)
{
if (empty($bean->fetched_row['name'])) {
$bean->account_name_c = $bean->fetched_row['person_name_c'];
} else {
$bean->account_name_c = $bean->fetched_row['name'];
}
// Here I also tried, but same result
// $bean->account_name_c = empty($bean->name) ? $bean->person_name_c : $bean->name;
}
}
listviewdefs.php at custom/modules/Accounts/metadata/listviewdefs.php
I added the field
'NAME_C' =>
array (
'width' => '20%',
'label' => 'LBL_ACCOUNT_NAME_C',
'default' => true,
),
After these modifications and repair I hope to see the field full with the right value. But it appears empty. I have verified that the logic hook is properly called, but the name andperson_name_c fields are always empty. In case it is relevant I have verified in Studio that the name fields in Account is typename I do not know what this means when it comes to obtaining its value.
I appreciate your comments
The problem is in the logic hook is due to first that the $bean does not have access to the custom fields, so I have to invoke them using $bean->custom_fields->retrieve(); Also the name field is always empty, I had to use DBManager to get only the name field.
The logic of the final logic hook is the following:
<?php
class ListViewLogicHook
{
public function getProperName($bean, $event, $arguments)
{
// Get access to custom fields from $bean
$bean->custom_fields->retrieve();
// Get access to name property using DBManager because $bean->name return null
$sql = "SELECT name FROM accounts WHERE id = '{$bean->id}'";
$name = $GLOBALS['db']->getOne($sql);
// Assign a value to non-db field
$bean->name_c = empty($name) ? $bean->nombre_persona_c : $name;
}
}
I was not familiar with the method $bean->custom_fields->retrieve() and at the moment I do not know why is empty the name field and I understand others fields remain empty.
I hope this is useful
We achieved that doing an after_retrieve hook, very fast and simple - This is taken from a working example.
public function RemoveCost(&$bean, $event, $arguments)
{
global $current_user;
include_once(‘modules/ACLRoles/ACLRole.php’);
$roles = ACLRole::getUserRoleNames($current_user->id);
if(!array_search("CanSeeCostRoleName",$roles)){
$bean->cost = 0;
$bean->cost_usdollar = 0;
}
}
All you need is to define and add this function to the module logic_hooks.php
You can even tailor down to specific calls:
if (isset($_REQUEST['module'],$_REQUEST['action']) && $_REQUEST['module'] == 'Opportunities' && $_REQUEST['action'] == 'DetailView')
As some times there are views you do want to show the field, for example quicksearch popup.
I want to disable the fields, name and last name, in edit profile Joomla, so that user can not modify them. How can I change this?
The best approach, but not the easiest, is to create an user plugin to override form with a onContentPrepareForm method :
public function onContentPrepareForm($form, $data){
if (!($form instanceof JForm)){
$this->_subject->setError('JERROR_NOT_A_FORM');
return false;
}
$form->setFieldAttribute('name', 'readonly', 'true');
$form->setFieldAttribute('lastname', 'readonly', 'true');
return true;
}
There is not a configuration setting to achieve this.
So the easiest approach is to create a template override for the users view.
In the administrator, open the menu Extensions-Templates-Templates, then select your template and choose "Create Overrides" in the top tab:
In the center column, choose com_users - profile and edit.php
The display is done with a loop, starting at line 59 (as of v. 3.6.5) you want to add code to identify the fields you wish to keep readonly, and simply set their readonly property.
This is the kind of code you would add starting at line 59:
<?php foreach ($fields as $field) : ?>
<?php
if ($field->name == 'jform[name]') {
$field->readonly = true;
}
?>
<?php // If the field is hidden, just display the input. ?>
The $field contains something like this:
We are identifying it by name (well by its field name), then setting its readonly property.
First of all, let me clarify myself. I baked something on cakephp and entering values on localhost in that application. Basicly, there are 2 models called location and temp_readings.
In location model, there are temperature limits that are called high_temp and low_temp. and also the name of the location. I enter those values, (e.g. name= fridge, low_temp= 3, high_temp= 7)
In temp_readings model, I enter a temperature a value for a specific location, (e.g. temperature= 10, location= frigde).
If temp value is out of limits, my app sending a warning email to me.
I work on temp_readings.php script for doing that and i need to put that condition for sending email.
I think, i can get the value of temperature by writing;
$temperature = $this->data['temp_readings']['temperature'];
since i am working in temp_readings.php.
However, i cannot get the values of low_temp and high_temp, which are saved under location model.
How can I get low_temp and high_temp values to work in temp_readings.php?
Here is the part of temp_readings.php (I dont know if it helps)
class temp_readings extends AppModel {
function afterSave($created, $options = array()) {
//pr($this);
//$temperature = $this->data['TemperatureReading']['temperature'];
//$low_temp=
//$high_temp=
if ($temperature > $high_temp && $temperature < $low_temp) {
$Email = new CakeEmail('gmail');
$Email->from(array('****#gmail.com' => 'My Site'));
$Email->to('***#gmail.com');
$Email->subject('Temperature Warning!');
$Email->send('Temperature is at critical value of');
}
}
You should have a belongsTo relationship between temp_readings and location, like so:
class temp_readings extends AppModel {
public $belongsTo = [
'location' // I don't know your data structure, but you'll probably need to add some details here
];
/* ... */
}
Then, after saving:
function afterSave($created, $options = array()) {
$temperature = $this->data['TemperatureReading']['temperature'] ;
$location = $this->data['Location'] ;
/* ... */
}
Of course, this code needs changes because I don't know your database structure but it should give you a hint on what you should do.
Is it possible to create model rules that are dependent from selection?
I have a model "Deposit" which is used to enter the money transfer details..I have drop down list with two possible choices "Cash Transfer","Cheque Transfer", and i have fields cash_deposit_date,bank_name.. which is required only for cash transfer and cheque_date, cheque_no and in_favour_of.. which is required only at the time of cheque transfer.. how can i do that..?
I know i can use scenarios like this,
$model=new Deposit("cash_transfer");
or
$model=new Deposit("cheque_transfer");
but how can I change scenario depending on the value selected in dropdown list?
Couldn't you just do this:
Generated HTML:
<form>
....
<select name="scenario">
<option value="cash_transfer">Cash Transfer</option>
<option value="cheque_transfer">Checque Transfer</option>
</select>
....
</form>
Code:
// allow only lowercase letters and underscore
$scenario = preg_replace('/[^a-z_]/', '', $_POST['scenario']);
if (!empty($scenario)) {
$model = new Deposit($scenario);
} else {
die('Missing scenario!');
}
Extending from jupaju answer,
That dropdown list also a model field(transfer_type), so I have done something like this..
After checking POST values are set, I use $model->scenario = $model->transfer_type==1 ? 'cash_transfer':'cheque_transfer' to change the scenario.
My code is
$model=new Deposit;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Deposit']))
{
$model->attributes=$_POST['Deposit'];
$model->scenario = $model->transfer_type==1 ? 'cash_transfer':'cheque_transfer';
if($model->save())
$this->redirect(array('admin'));
}
$this->render('create',array('model'=>$model));
Now it is working..
I think the best way would be to use a personalized validation rule in your model and then check if the model's "scenario" property is set to one or other option.
You can read more about custom validation rules in here
Hope this helps. Good luck!
This is more simple form me
In your model put:
public $pay_type;
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
...
array('pay_type', 'required'),
array('cash_deposit_date', 'validationTransfer'),
...
);
}
public function validationTransfer($attribute,$params)
{
// this a sample, put all your need
if($this->pay_type=='cash_transfer' and $this->cash_deposit_date==='')
$this->addError('cash_deposit_date','If you will pay to Cash Transfer, enter your cahs deposit date');
// this a sample, put all your need
if($this->pay_type=='cheque_transfer' and $this->cheque_date==='')
$this->addError('cheque_date','If you will pay to Cheque Transfer, enter your cheque date');
// this a sample, put all your need
if($this->pay_type=='cheque_transfer' and $this->cheque_no==='')
$this->addError('cheque_no','If you will pay to Cheque Transfer, enter your Cheque No');
}
In the view into your widget form
<?php echo $form->labelEx($model,'pay_type',array('class'=>'control-label')); ?>
<?php echo $form->dropDownList($model,'pay_type',array("cash_transfer"=>"Cash Transfer","cheque_transfer"=>"Cheque Transfer"),array('class'=>'form-control','empty'=>'Pay Type...')); ?>
<?php echo $form->error($model,'pay_type',array('class'=>'help-block')); ?>
Note: css class like "help-block", "control-label", "form-control" on witget form are optionals, maybe you use Bootstrap 3 and it will looks good
I got dpm($form) working. Nice! This is much better way to view data. I am still trying to figure out where stuff is coming from eg: location longitude & latitude. The word 'longitude' is referenced in 20 different places. I thought this was a likely place to isolate text box for this input field. dpm($form['#field_info']['field_store_latitude']['location_settings']['form']['fields']);
Any tips on how to track down individual input elements?
** this is not an answer, but a supplement to my first question **
hi googletorp -
I am trying to modify existing forms using hook_form_alter.
After several hours of poking around, I can now turn off location (longitude/latitude) section of a form like this:
unset($form['field_store_latitude']);
However, turning off just the latitude like this, does not work:
unset($form['field_store_latitude']['0']['#location_settings']['form']['fields']['locpick']);
I cannot find a easy way to link id and names in html source with arrays produced by Krumo.
In this case id is called "edit-field-store-latitude-0-locpick-user-latitude".
I need a recipe or guidelines for identifying form elemets in Drupal form.
I think I nailed down a solution
<?php
// allows you to alter locations fields, which are tricky to access.
// this will require a patch in location module described here:
// http://drupal.org/node/381458#comment-1287362
/**
* Implementation of custom _element_alert() hook.
*/
function form_overrides_location_element_alter(&$element){
// change some location descriptions
$element['locpick']['user_latitude']['#description'] = ' ' . t('Use decimal notation.');
$element['locpick']['user_longitude']['#description'] = ' ' . t('See <a href=!url target=_blank>our help page</a> for more information.', array('!url' => url('latlon_help')));
// or make them disappear entirely
unset($element['locpick']['user_longitude']);
unset($element['locpick']['user_latitude']);
}
/**
* Implementation of form_alter hook.
*/
function form_overrides_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'user_profile_form':
// change titles in user profile form
$form['account']['name']['#title'] = t('Login Name');
$form['account']['mail']['#title'] = t('Email');
break;
case 'retailer_node_form':
// let's check what is supposed to be here...
print '<pre>';
//print_r($form);
dsm($form);
print '</pre>';
// this works to remove the city
unset($form['field_myvar_latitude']['0']['#location_settings']['form']['fields']['city']);
// let's try #after_build property
$form['#after_build'][]='mymodule_after_build_mynode';
break;
}
}
function mymodule_after_build_mynode($form, $form_values) {
// This will not work for locations fields
return $form;
}`enter code here`
So there is sneaky way to alter the location field, what you need to do is to use the #after_built callback:
/**
* Implements hook_form_alter().
*/
function mymodule_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'x_node_form') {
// alter the location field
if (isset($form['locations'])) {
$form['locations']['#after_build'][] = 'mymodule_alter_location_field';
}
}
}
/**
* Remove the delete checkbox from location element.
*/
function mymodule_alter_location_field($form_element, &$form_state) {
$location = $form_element[0]; // The location field which you can alter
return $form_element;
}