How to add two numbers in sugar crm - sugarcrm

I made module addition and in this made three fields amount1_c, amount2_c and total_amount_c to add the two numbers and display the result in the third field. I done coding in the logic looks here is my code
<?
$hook_version = 1;
$hook_array = Array();
$hook_array['before_save'] = Array();
$hook_array['before_save'][] = Array(1,'calculate_field', 'custom/modules/cases/LogicHookMath.php','LogicHookMath', 'calculate_field');
?>
and made one more file logic hook math. here is my code for
<?php
class LogicHookMath {
function calculate_field(&$bean, $event, $arguments) {
$field1 = $bean->amount1_c;
$field2 = $bean->amount2_c;
$field3 = $field1 + $field2;
$bean->amount_total_c = $field3;
}
}
?>
but still i did not get any result. Please help me out for this.

The code looks correct.
Some common "mistakes" when custom logic hooks are not working:
Make sure, the custom logic hook has the correct name (LogicHookMath.php)
Make sure, that the $bean variable is prefixed with &, so the variable is passed as a reference
Make sure the logic_hooks.php and the LogicHookMath.php files are readable by the web server user
The entire custom directory should also be writeable for the web server user
If the above does not help, try logging the progress to the sugarcrm.log using $GLOBALS['log']->info( "Value 3: ". $field3); in the custom logic hook.

Related

Get Line Items in an Invoice logic hook in SuiteCRM

Via a logic hook I'm trying to update fields of my products, after an invoice has been saved.
What I understand so far is, that I need to get the invoice related AOS_Products_Quotes and from there I could get the products, update the required fields and save the products. Does that sound about right?
The logic hook is being triggered but relationships won't load.
function decrement_stocks ( $bean, $event, $arguments) {
//$bean->product_value_c = $bean->$product_unit_price * $bean->product_qty;
$file = 'custom/modules/AOS_Invoices/decrement.txt';
// Get the Invoice ID:
$sInvoiceID = $bean->id;
$oInvoice = new AOS_Invoices();
$oInvoice->retrieve($sInvoiceID);
$oInvoice->load_relationship('aos_invoices_aos_product_quotes');
$aProductQuotes = $oInvoice->aos_invoices_aos_product_quotes->getBeans();
/*
$aLineItemslist = array();
foreach ($oInvoice->aos_invoices_aos_product_quotes->getBeans() as $lineitem) {
$aLineItemslist[$lineitem->id] = $lineitem;
}
*/
$sBean = var_export($bean, true);
$sInvoice = var_export($oInvoice, true);
$sProductQuotes = var_export($aProductQuotes, true);
$current = $sProductQuotes . "\n\n\n------\n\n\n" . $sInvoice . "\n\n\n------\n\n\n" . $sBean;
file_put_contents($file, $current);
}
The invoice is being retrieved just fine. But either load_relationship isn't doing anything ($sInvoice isn't changing with or without it) and $aProductQuotes is Null.
I'm working on SuiteCRM 7.8.3 and tried it on 7.9.1 as well without success. What am I doing wrong?
I'm not familiar with SuiteCRM specifics, however I'd always suggest to check:
Return value of retrieve(): bean or null?
If null, then no bean with the given ID was found.
In such case $oInvoice would stay empty (Your comment suggests that's not the case here though)
Return value of load_relationship(): true (success) or false (failure, check logs)
And I do wonder, why don't you use $bean?
Instead you seem to receive another copy/reference of $bean (and calling it $oInvoice)? Why?
Or did you mean to receive a different type bean that is somehow connected to $bean?
Then its surely doesn't have the same id as $bean, unless you specifically coded it that way.

Trying to copy values into multiple embedded forms

I have a Symfony 1.4 application to allow users to enter data to a electrical appliance testing database. The page in questions consists of multiple embedded "new" forms so the user can submit many tests in one go. The form validates and saves correctly, but feedback is that it will be tedious to use.
As much of the data may be the same in each test (e.g. same date, same result, same person doing the testing), I would like the user to be able to fill in values in the top row, then click a button to fill the same information in the rows below. I'm pretty sure this would require javascript, but I don't have much experience.
I would appreciate any suggestions.
Many Thanks.
Well, I managed to figure it out without using javascript.
I put a button on the page
<input type="submit" name="copy_values" value="duplicate">
In the action for the page I included the code...
elseif (isset($_POST['copy_values'])) {
// get values from first embedded test
$newTests = $testList['new_tests'];
$testDate = $newTests[0]['et_date_tested'];
$testedBy = $newTests[0]['et_tester_id'];
$formOptions = array('test_date'=>$testDate, 'tester'=>$testedBy);
$this->form = new MultiTestForm(null, $formOptions);
}
$this->setTemplate('multiAdd');
... which takes the values from the widgets in the top row of the form and creates an array. This is passed as the options array to create a new form.
In the top level form class..
public function configure()
{
...
$subform = new sfForm();
for($i = 0;$i < sfConfig::get('app_new_test_rows'); $i ++)
{
$formToAdd = new TestsForMultiAddForm(null,$this->getOptions());
$subform->embedForm($i, $formToAdd);
}
$this->embedForm('new_tests', $subform);
}
...and in the embedded form class...
public function configure()
{
...
if ($this->getOption('test_date')) {
$this->setDefault('et_date_tested', $this->getOption('test_date'));
}
if ($this->getOption('tester')) {
$this->setDefault('et_tester_id', $this->getOption('tester'));
}
...
}
Not sure if this is the conventional way to approach the problem, but it works!

Call TYPO3 plugin from other plugin's body

I need to call typo3 plugin from other plugin's body and pass its result to template. This is pseudo-code that describes what I want to achieve doing this:
$data['###SOME_VARIABLE###'] = $someOtherPlugin->main();
$this->cObj->substituteMarkerArray($someTemplate, $data);
Is it possible?
Thanks!
It doenst work if you use the whole pi construct, e.g. for links, marker function etc, and the TSFE Data can be corrupted.
Dmitry said:
http://lists.typo3.org/pipermail/typo3-english/2008-August/052259.html
$cObjType = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_rgsmoothgallery_pi1'];
$conf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_rgsmoothgallery_pi1.'];
$cObj = t3lib_div::makeInstance('tslib_cObj');
$cObj->start(array(), '_NO_TABLE');
$conf['val'] = 1;
$content = $cObj->cObjGetSingle($cObjType, $conf); //calling the main method
You should use t3lib_div:makeInstance method.
There is a working example from TYPO3's "powermail" extension.
function getGeo() {
// use geo ip if loaded
if (t3lib_extMgm::isLoaded('geoip')) {
require_once( t3lib_extMgm::extPath('geoip').'/pi1/class.tx_geoip_pi1.php');
$this->media = t3lib_div::makeInstance('tx_geoip_pi1');
if ($this->conf['geoip.']['file']) { // only if file for geoip is set
$this->media->init($this->conf['geoip.']['file']); // Initialize the geoip Ext
$this->GEOinfos = $this->media->getGeoIP($this->ipOverride ? $this->ipOverride : t3lib_div::getIndpEnv('REMOTE_ADDR')); // get all the infos of current user ip
}
}
}
The answer of #mitchiru is nice and basically correct.
If you have created your outer extension with Kickstarter and you are using pi_base then there is already an instance of tslib_cObj and the whole construct becomes simpler:
// get type of inner extension, eg. USER or USER_INT
$cObjType = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_innerextension_pi1'];
// get configuration array of inner extension
$cObjConf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_innerextension_pi1.'];
// add own parameters to configuration array if needed - otherwise skip this line
$cObjConf['myparam'] = 'myvalue';
// call main method of inner extension, using cObj of outer extension
$content = $this->cObj->cObjGetSingle($cObjType, $cObjConf);
Firstly, you have to include your plugin class, before using, or outside your class:
include_once(t3lib_extMgm::extPath('myext').'pi1/class.tx_myext_pi1.php');
Secondly in your code (in the main as example)
$res = tx_myext_pi1::myMethod();
This will work for sure (I've checked this): http://lists.typo3.org/pipermail/typo3-english/2008-August/052259.html.
Probably Fedir's answer is correct too but I didn't have a chance to try it.
Cheers!

Help needed formatting Doctrine Query in Zend Framework

Can anyone tell me how to format the query below correctly in my controller.
Currently it gives me nothing in my FilteringSelect. However if I change it to >= I get back all the kennelIDs which is incorrect also but at least I'm getting something.
I've tested that the session variable is set and can confirm that there are kennels with the matching capacity.
// Create autocomplete selection for the service of this booking
public function servkennelAction()
{
$sessionKennelBooking = new Zend_Session_Namespace('sessionKennelBooking');
// disable layout and view rendering
$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender(true);
// get list of grooming services for dogs from the table
$qry= Doctrine_Query::create()
->from('PetManager_Model_Kennels k');
//This should be set by default and narrows down the search criteria
if(isset($sessionKennelBooking->numPets)){
$b=(int)$sessionKennelBooking->numPets;
$qry->addWhere('k.capacity = ?','$b');
}
$result=$qry->fetchArray();
//generate and return JSON string using the primary key of the table
$data = new Zend_Dojo_Data('kennelID',$result);
echo $data->toJson();
}
Many thanks in Advance.
Graham
I think that addWhere condition is wrong. It has to be:
$qry->addWhere('k.capacity = ?', $b);
i.e. $b without quotes.

Zend Framework email content generation

With Zend_Framework, I wondered what is considered best practice for building up the content to send in a HTML email. In my case the content of the email that is sent is determined by a number of factors, for example the number of returned rows for a specific value in the database. Because of this it makes sense for me that the content is built up within the controller that sends the email which talks to the relevant database models and determines what the content should be. Where i'm not sure this works is that our designers and copyrighters will often want to adjust the copy in emails and this would then require them to make changes to a model or ask me to. Should i be handling this differently? Should i perhaps be storing HTML snippets somewhere containing the different text and then calling these somehow?
EDIT following from the answer by fireeyedboy, would it be acceptable to do something like this. Create a folder inside views called "partials" and use this to store text/html snippets that i can then call in where i need and replace special strings with dynamic values using regexp(or similar).
$nview = new Zend_View();
$nview->setScriptPath(APPLICATION_PATH.'/views/partials/');
$bodytext = $nview->render('response.phtml');
$mail = new Zend_Mail();
$mail->setBodyText($bodytext);
// etc ...
e.g. in this context where two different templates could be used depending on variables returned from a Model:
// within a controller
public function emailAction()
{
$images = new Model_ApplicationImages();
$totimages = count($images->fetchImages($wsid));
$acceptedImages = $images->fetchImages($wsid,'approved');
$accepted = count($acceptedImages);
$rejectedImages = $images->fetchImages($wsid,'rejected');
$rejected = count($rejectedImages);
$response = ($rejected == $totimages)?'rejected':'approved';
$nview = new Zend_View();
$nview->setScriptPath(APPLICATION_PATH.'/views/partials/');
$content = $nview->render($response.'.phtml');
$mail = new Zend_Mail();
$mail->setBodyText($content);
// etc
}
Is there a more elegant way i can/should be doing this?
Not sure if this is best practice, but what I did is extend Zend_Mail with methods like these:
setTemplatePath( $templatePath );
setTemplateHtml( $templateHtml );
setTemplateText( $templateText );
setTemplateArguments( array $templateArguments );
...then at some point in my overwrittensend() I do:
$view = new Zend_View();
$view->setScriptPath( $this->_templatePath );
foreach( $this->_templateArguments as $key => $value )
{
$view->assign( $key, $value );
}
if( null !== $this->_templateText )
{
$bodyText = $view->render( $this->_templateText );
$this->setBodyText( $bodyText );
}
if( null !== $this->_templateHtml )
{
$bodyHtml = $view->render( $this->_templateHtml );
$this->setBodyHtml( $bodyHtml );
}
So to utilize this you would do something like:
$mail = new My_Extended_Zend_Mail();
$mail->setTemplatePath( 'path/to/your/mail/templates' );
$mail->setTemplateHtml( 'mail.html.phtml' );
$mail->setTemplateText( 'mail.text.phtml' );
$mail->setTemplateArguments(
'someModel' => $someFunkyModel,
/* etc, you get the point */
)
$mail->send();
In other words, with this you can let your designers and copywriters simply edit views (templates) like they are used to already. Hope this helps and has inspired you to come up with something funky that suits your needs.
PS:
Since you mention arbitrary data rows, you can, for instance, utilize the partialLoop view helper that comes with ZF for this. But you probably were aware of this already?
PPS:
I actually agree with chelmertz' comment about not extending Zend_Mail but wrapping it in my own component.