CakePHP how to display related information - cakephp

My order table includes customer filed , When add new order, after choose the customer name from dropdown list, I want the same page to display the information of customer, for example, address, phone number from customer table
How to do?
Thanks in advance...
Could you give me an example or related links? I don't know anything about AJAX, have no idea where to start.
Maybe this link: http://www.w3schools.com/ajax/ajax_database.asp, but it uses php not cakephp...
the code in example is : xmlhttp.open("GET","getuser.php?q="+str,true);
I don't know how to pass customer_id(q=str) to orderscontroller/getuser function.need help

You can use JsHelper to achieve the same you mentioned. Kindly try at your end, and provide some raw code so that peers can help you to do that.

Your code should be like this
function showCustomer(str)
{
var xmlhttp;
if (str=="")
{
document.getElementById("divtoDisplayInfo").innerHTML="";
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("divtoDisplayInfo").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","/yoursite/controllername/action/str,true); //if you use redirect and windows environment
xmlhttp.send();
}
you should expect the view of that action so do the normal cake processing, get data in the controller, render view, if there is an error set the actions autorender to false.
but i will just advice you to download Jquery add to your cakephp framework this simple line
$("divToDisplayInfo's_ID").load("Controllername/action")
solves your problem.

Related

CPQ Quote API, I can't save the quote

I can't save the quote.
Doing the query:
select
ApexClass.name, Id, CreatedDate, CreatedById, JobType,
ApexClassId, Status, JobItemsProcessed, TotalJobItems,
NumberOfErrors, CompletedDate, MethodName, ExtendedStatus,
ParentJobId, LastProcessed, LastProcessedOffset
from
AsyncApexJob
order by
CreatedDate desc
I get this error:
Calculation error on quote Q-13761: "UNAUTHORIZED"
Code:
public with sharing class QuoteCalculator {
public void calculate(QuoteModel quote, String callbackClass) {
system.debug('quote: ' +quote);
system.debug('callbackClass: ' +callbackClass);
QuoteCalculatorContext ctx = new QuoteCalculatorContext(quote, callbackClass);
SBQQ.ServiceRouter.load('SBQQ.QuoteAPI.QuoteCalculator', null, JSON.serialize(ctx));
system.debug('QuoteCalculator.calculate');
}
private class QuoteCalculatorContext {
private QuoteModel quote; //The quote and callbackClass properties are called
in the API code by the exact names seen here.
private String callbackClass; //Altering these property names will cause
calculator API calls to fail.
private QuoteCalculatorContext(QuoteModel quote, String callbackClass) {
this.quote = quote;
this.callbackClass = callbackClass;
}
}
}
anonymous window:
QuoteReader reader = new QuoteReader();
QuoteModel quote = reader.read('a0p1w000BhfXzAAJ');
System.debug(quote);
quote.lineItems[0].record.SBQQ__Quantity__c = 2;
QuoteCalculator calculator = new QuoteCalculator();
calculator.calculate(quote, 'MyCallback')
Preface
I had (almost) the same exact code base as yours, and got the same error message.
In my case there was an other sandbox I could test my code, and it turned out to be working properly there.
Cause
Later found out that the Salesforce CPQ's Calculation Quote API is using Heroku to do the calculations in order to avoid apex limits exhaustion.
From this it can be deducted, that it needs to have a Connected App. I checked the Apps -> Connected Apps setup, and found that no record was listed under the "Connected Apps OAuth Usage" page for the Salesforce CPQ. (On my other sandbox there was a "Steelbrick CPQ" row.)
From this I concluded that this might be the reason for this behaviour.
Seems like something went wrong during the "Authorize new Calculation Service" process. (Or there was a sandbox refresh and something else went wrong during it.)
Solution
The bad news is that the option to authorize a new calculation service is only visible for the first time you configure the package, which you might already done. (Well... if you haven't done, then this is a great news, because your problem is probably solved. :D) (Otherwise read further.)
The good news is I figured out a solution for the case when you already done this, yet that "Steelbrick CPQ" row is missing.
Created a scratch org and installed the Salesforce CPQ package, then before I clicked on the "Authorize new Calculation Service" link under the "Pricing and Calculation" tab in the Settings Editor, I checked the source code in hope of finding something of interest.
I did.
This link: https://rest-na.steelbrick.com/oauth/auth/https%3A%2F%2Ftest.salesforce.com/SBQQ
(⚠️NOTE: You might have to change it according to your location. There are several servers across the globe:
rest-au.steelbrick.com
rest-eu.steelbrick.com
rest-jp.steelbrick.com
rest-na.steelbrick.com
But for me the above pasted link was generated on the settings page. Which is only interesting, because I live in the EU, yet, for some reason I got the link to the rest-NA server... whatever.gif
So just make sure if you click on the link, in the address bar you can find the appropriate salesforce instance URL.)
Conclusion
With this link you won't have to reinstall the package, you just have to click on it, and allow the access from Steelbrick and the missing row will appear, and you will be authorized to use the Calculation API.

Which way to load navbar for user/admin in NodeJS/AngularJS

I have a request, Can anyone tell me, how to properly do. I want to make two navbars in my project, first is intended for admin, second for user. I use with NodeJS (back), AngularJS (front). At the moment I created on the side NodeJS script, Which checks the status of the user role:
In router index.js (I think its good place?)
router.get('/checkRole', function (req, res) {
if (req.user != null) {
if (req.user.role == 'admin') {
res.json('admin');
}
} else {
res.json('user');
}
});
Now the question is what next?
Create Service with http.get to index route, and every time, when will be loaded page check status and load navbar?
(Important thing)
So I need in each controller to add a service (http get, check status, load navbar) yes?
Or is another way? Can someone explain me??
Sorry for english, and thanks for help.

Cakephp check if referer is from local url

I'm struggeling a litte with my Cakephp 2.1 application.
I want to render a different layout, if the referer is from an external url. Sadly this is not working :
if($this->referer(null, true))
{
$this->layout = 'lightview';
}
else
{
$this->layout = 'default';
}
Any ideas how I can fix this?
Thanks in advance
You got a logical error here:
$this->referer(null, true) // true as second param: only internal
will only return the lightview layout if
there is a referer (not always the case)
internal referrer
So this is probably not what you want.
You cannot do that this easily. Sometimes there is just no referrer.
And even if there is you might still don't know if this person came from somewhere else and just "hid" the referrer. Or then browsed your site (creating internal referrers from here on).
You would need to store the initial result on first visit in the session to check against later on.
But even so your approach is highly inconsistent and very likely breakable...

WMS GetFeatureInfo; multiple layers, different sources

I'm developing a web application using GeoExt, OpenLayers and having my own GeoServer to serve various maps. Still, I want to let the user add other WMS's if needed, to be able to play around with all desired layers.
Thus, my problem with the GetFeatureInfo request. Right now I have a toolbar button attached to geoext's map panel,
new GeoExt.Action({
iconCls: "feature",
map: map,
toggleGroup: "tools",
tooltip: "Feature",
control: featureControl
})
its control attribute being
var featureControl = new OpenLayers.Control.WMSGetFeatureInfo({
queryVisible: true,
drillDown: true,
infoFormat:"application/vnd.ogc.gml"
});
I've also defined an event listener to do what I really want once I receive the responses, but that is not relevant here. My problem is the following:
Considering the user clicks on a point where there are 2+ visible layers and at least one of them is from a different source, OpenLayers will have to do one AJAX request per different source and, from OpenLayers own documentation,
Triggered when a GetFeatureInfo response is received. The event
object has a text property with the body of the response (String), a
features property with an array of the parsed features, an xy property
with the position of the mouse click or hover event that triggered the
request, and a request property with the request itself. If drillDown
is set to true and multiple requests were issued to collect feature
info from all layers, text and request will only contain the response
body and request object of the last request.
so, yeah, it will obviously wont work like that right away. Having a look at the debugger I can clearly see that, giving two layers from different sources, it actually DOES the request, it's just that it doesn't wait for the first's response and jumps for the next one (obviously, being asynchronous). I've thought about doing the requests one-by-one, meaning doing the first one as stated above and once it's finished and the response saved, go for the next one. But I'm still getting used to the data structure GeoExt uses.
Is there any API (be it GeoExt or OpenLayers) option/method I'm missing? Any nice workarounds?
Thanks for reading :-)
PS: I'm sorry if I've not been clear enough, english is not my mother tongue. Let me know if something stated above was not clear enough :)
i Hope this help to someone else, I realized that: you're rigth this control make the request in asynchronous mode, but this is ok, no problem with that, the real problem is when the control handle the request and trigger the event "getfeatureinfo" so, i modified 2 methods for this control and it works!, so to do this i declare the control first, and then in the savage mode i modified the methods here is de code:
getInfo = new OpenLayers.Control.WMSGetFeatureInfo({ drillDown:true , queryVisible: true , maxFeatures:100 });
//then i declare a variable that help me to handle more than 1 request.....
getInfo.responses = [];
getInfo.handleResponse=function(xy, request) { var doc = request.responseXML;
if(!doc || !doc.documentElement) { doc = request.responseText; }
var features = this.format.read(doc);
if (this.drillDown === false) {
this.triggerGetFeatureInfo(request, xy, features);
} else {
this._requestCount++;
this._features = (this._features || []).concat(features);
if( this._numRequests > 1){
//if the num of RQ, (I mean more than 1 resource ), i put the Request in array, this is for maybe in a future i could be need other properties or methods from RQ, i dont know.
this.responses.push(request);}
else{
this.responses = request;}
if (this._requestCount === this._numRequests) {
//here i change the code....
//this.triggerGetFeatureInfo(request, xy, this._features.concat());
this.triggerGetFeatureInfo(this.responses, xy, this._features.concat());
delete this._features;
delete this._requestCount;
delete this._numRequests;
// I Adding this when the all info is done 4 reboot
this.responses=[];
}
}
}
getInfo.triggerGetFeatureInfo= function( request , xy , features) {
//finally i added this code for get all request.responseText's
if( isArray( request ) ){
text_rq = '';
for(i in request ){
text_rq += request[i].responseText;
}
}
else{
text_rq = request.responseText;
}
this.events.triggerEvent("getfeatureinfo", {
//text: request.responseText,
text : text_rq,
features: features,
request: request,
xy: xy
});
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");}
Thanks, you bring me a way for discover my problem and here is the way i solved, i hope this can help to somebody else.
saheka's answer was almost perfect! Congratulations and thank you, I had the same problem, and with it I finally managed to solve it.
What I would change in your code:
isArray() does not work, change it like this: if(request instanceof Array) {...} at the first line of getInfo.triggerGetFeatureInfo()
to show the results in a popup this is the way:
My code:
getInfo.addPopup = function(map, text, xy) {
if(map.popups.length > 0) {
map.removePopup(map.popups[0]);
}
var popup = new OpenLayers.Popup.FramedCloud(
"anything",
map.getLonLatFromPixel(xy),
null,
text,
null,
true
);
map.addPopup(popup);
}
and in the getInfo.triggerGetFeatureInfo() function, after the last line, append:
this.addPopup(map, text_rq, xy);
A GetFeatureInfo request is send as a JavaScript Ajax call to the external server. So, the requests are likely blocked for security reasons. You'll have to send the requests to the external servers by a proxy on your own domain.
Then, configure this proxy in openlayers by setting OpenLayers.ProxyHost to the proper path. For example:
OpenLayers.ProxyHost = "/proxy_script";
See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost for more background information.

How do I test an HTML Email Template on CakePHP?

To confirm a purchase I must send an e-mail to the customer with her shopping cart details. I'd like to test the HTML template to use the appropiate CSS, and of course to check the data that arrives to it.
What code should I use instead of setting the Email parameters, to watch how the template will render on the Email?
I'm all new on CakePHP, so your help will be very much appreciated.
Thanks in advance.
~José
This is CakePHP 1.3, but I have a feeling it may work well with 2.0 as well. While there may be other ways to do it, I do by creating a test action in any controller, then return a render call of the email template. Check this out:
function email_test()
{
$this->layout = 'email/html/default';
$user = $this->User->findById(1);
$this->set('name', $user['User']['firstname']);
$this->set('email_heading', 'Welcome to My App');
return $this->render('/elements/email/html/welcome');
}
This action will now render out your email in the browser.
Use the debug transport for testing.
If you want to make it more comfortable write your own transport that creates a new html file in for example APP/tmp/email/.html See the debug transport class as a reference, it's dead easy to do this http://api20.cakephp.org/view_source/debug-transport#l-34
See also the book -> http://book.cakephp.org/2.0/en/core-utility-libraries/email.html#using-transports
Here is the simple method I use to show html/plain text content of email in browser that I want to send using cakephp email class i.e. App::uses('CakeEmail', 'Network/Email');.
Just do an exit at the end of email template file or (email layout file) and then try to send email. it will render the email content.
HTH.
$this->Email->to = $user_id_array[0]['User']['email'];
$this->Email->subject = $arrTemplate[0]['EmailTemplate']['subject'];
$this->Email->replyTo = 'Admin<admin#indianic.com>';
$this->Email->from = 'Admin<admin#indianic.com>';
$this->Email->sendAs = 'html';
$this->Email->template = '/elements/email/html/warning_message';
$this->set('email_message',$arrTemplate[0]['EmailTemplate']['body']);
$this->Email->send();
in this way you can set template for email
If you want to print your email template on localhost for testing then you can use this code.
$this->Email->send();
print_r($this->Email->htmlMessage);

Resources