Ignoring null email field in oracle apex mail script - oracle-apex

I'm currently building a staffing CRM in Oracle Apex for my company and we have a lead generation form that allows recruiters to add any sales leads.
Once a recruiter adds a lead the page sends an email to the assigned sales person.
Now here's my issue, I need to get APEX.MAIL to ignore any null email address fields on the form page since management wants to be able to assign up to 3 sales people to receive that lead, though they may only assign 1 or 2.
How can I make APEX.MAIL ignore the page item for the sales email if the field is null.
Right now the "To" line is p_to=> :P3_SALESMAN
How I want it to look is p_to=> :P3_SALESMAN, :P3_SALESMAN2, :P3_SALESMAN,3,
But if :P3_SALESMAN2 or :P3_SALESMAN3 are null, I want APEX.MAIL to ignore them.
Or would that even cause a problem is the field is null?

You don't indicate how you are calling APEX.MAIL...
Since APEX.MAIL is a PLSQL pkg, one suggestion is to write a wrapper PLSQL pkg that will look at the parameters you pass in (P3_SALESMAN1.2,3...) and use If Else logic to evaluate the fields as null or not and then determine whether to call the APEX.MAIL pkg.
Writing in-line PLSQL in APEX quickly becomes a maintenance and reusability headache, so you should think about always using a PLSQL stored Proc/Func to encapsulate your logic and call it from the page.

Like Joe mentioned, using stored procedure is better than writing in-line pl/sql, which I learnt the hard way.
About building the list of email addresses, I can't think of another way, but to use if-else condition, and adding email addresses to a string, if they exist and passing the final string to p_to in APEX_MAIL.

Related

Using EXISTS and GetProfileAttrAsList in a Siebel calculated field

In our Siebel 7.8 application, we have three entities: service requests (SR), groups and employees. Each employee can be member of one or many groups, and each service request can be assigned to one or many groups too.
I have a requeriment to create a calculated field on the service request BC, which will indicate if the current user belongs to any of the groups asociated with the service request.
I already have created a multivalue field, called SR Groups, on the service request BC. I have also another multivalue field, Employee Groups; this one is on the Personalization Profile business component, which means that Siebel will generate automatically a multivalued profile attribute with the same name. All of the above is working as expected.
Next I've created this calculated field:
IIf(InList([SR Groups], GetProfileAttrAsList("Employee Groups")), "Y", "N")
It works, but it only checks if the SR's primary group is one of the current user's groups. I need to check all the SR groups, not only the primary one. So, I have created another calculated field:
IIf(EXISTS([SR Groups] = GetProfileAttrAsList("Employee Groups")), "Y", "N")
This one doesn't work. It shows always "N". However, according to this Bookshelf document:
a typical usage of the EXISTS operator in this scenario is EXISTS ([Targeted States] = GetProfileAttrAsList("State")). This does a many-to-many match of the MVG Business Component Field Targeted State against the MVG profile attribute State.
Which is exactly what I'm trying to do, without success. I can't see any difference between my expression and the example one. And there isn't any of the typical Bookshelf warnings, like "if you're going to use this function, you must activate the Link Specification property of the MVF", or anything like that.
The business component is based on a specialized class, CSSBCServiceRequest, but I don't think that should be a problem in this case - switching it to CSSBCBase doesn't fix the issue either. The only thing not working seems to be the EXISTS operator, which is pretty standard in Siebel.
Also, if I execute a query on the application with the expression EXISTS([SR Groups] = GetProfileAttrAsList("Employee Groups")), it doesn't filter out any service request as it should.
Any clues?
After a lot of testing, I've been able to figure out a workaround. I'd still like to know why my first attempt didn't work, but anyway...
Given that the problem with my first attempt seemed to be matching a many-to-many relationship between the MVF and the multivalued profile attribute, I've split it in two one-to-many matches:
In the link, I've stablished a search specification property. This way, my multivalue field will contain only groups associated with the user:
InList([Group], GetProfileAttrAsList("Employee Groups"))
In the BC, it only remains to check if there is any value in the MVF or not:
IIf(EXISTS([Filtered SR Groups] IS NOT NULL), "Y", "N")

Making a Row Read Only in a tabular form based on table value

I have a tabular form which is updated throughout the year and i wanted to prevent users from editing certain rows. Currently the 'row type' is hard coded however I want the application admin to control which 'row types' are readable / write at certain times. My answered question, click here.
Currently a dynamic action is fired which prevents the rows that contain the type 'manager figure' and 'sales_target' being edited.
I have created a table with the three row types against each customer. Each status is set by a number: 0 to 3 (These i will decode into something meaningful for users).
0 - Row with that row type is read only.
1 - Users can enter into the row with that row type.
2 - row is read only with that row type.
3 - row is complete and set to read only.
I have created a new form (new tab) for the admin user to maintain each status.
Currently for Customer 'Big Toy Store' rows should be set as follows:
Manager Figure row should be read only (since set to 2)
Sales should be readable (since set to 0)
Sales target should be writable (since set to 1)
Please can i be pointed in the right direction, ive looked into jquery but struggling to work out how to pass the output of an sql query to it, so it can be used to determine which rows should be read only.
Link:apex.oracle.com
workspace: apps2
user: developer.user
password: DynamicAction
application name: Application 71656 Read only Rows for Tabular Form
I'm not sure that a tabular form is a good format to work out this idea. As you can see, you require quite a bit of javascript to produce the results you want. Not only that, but this is all client side too, and thus there are some security risks to take into account. After all, I could just run some Firebug and disable or revert all things you did, and even change the numbers. Especially with sales figures, which is something you most definitely do want altered by everybody and is also the nature of your question, security is important.
There are more elegant ways here for you to control this, and not in the least to reduce the amount of highly customized javascript code. For example, you could do away with the tabular form, and instead implement a modal popup from an interactive report. Since the modal popup would be an iframe and thus a different page, you can create a form page. On a form page you have a lot more control over what happens to certain elements. You can specify conditions, read-only conditions, or use authorization schemes. All things you can not evidently use in a tabular form.
I'd think you'd do yourself a service by thinking this over again, and explore a different option. How much of a dealbreaker is using a tabular form actually?
You need the user. You need to know what group he belongs to, and then this has to be checked against the different statusses and rows have to be en/disabled. Do you really want this to happen on the client side?
I'm not saying it can't be done in a tabular form and javascript. It can, I'm just really doubting this is the correct approach!

Explicit correspondence between Google spreadsheet cells and Google form input fields

I am making a web form for people to sign up for an event. I found that I can use Google form and Google spreadsheet for this task, and I started to learn how to use these web applications. I would also like to send the automatic confirmation e-mail to those who have signed up. For this task, I am also looking into the Google Apps Script. As far as I understand, I should define a function to send e-mail in a script in the spreadsheet and trigger this function at 'Form Submission Event'. I would like to identify the e-mail address of a person who signed up from the data he/she submitted, and I would like to include all the submitted data as well as the time stamp in the confirmation e-mail.
My questions are the following.
How can I identify the cell in the spreadsheet into which the value of an input field in the Form is stored?
Or, is there any way that I can read the values of the respective input fields from a Google Apps Script?
I would be glad if you could kindly refer me to an unambiguous API reference related to these questions.
So far I learned about the applications from the help pages provided in Google Drive,
e.g.
https://developers.google.com/apps-script/overview
However, I feel documents there are too concise.
I am learning how to send confirmation e-mail from this Google Apps Script:
FormSubmissionResponseEmail
I could not find a help document that explicitly relates an input field in a Google form and a cell in the Google spreadsheet. From my limited number of experiment cases, it seems that the time stamps are always stored in the first column of the spreadsheet. Is this guaranteed? It seems that 'namedValues' member of the 'Spreadsheet Form Submit Events' class is said to contain "the question names and values from the form submission." (https://developers.google.com/apps-script/understanding_events)
However, when I modified the Google form, the 'namedValues' member still held the elements corresponding to deleted input fields. Is there any way to loop over only those elements in 'namedValues' that corresponds to the fields actually input by a user?
I would also be glad to hear about alternative tools to replace Google form and Google spreadsheet.
This answer applies to the "new Forms", the 2013 version, not "Legacy Forms" which have been discontinued.
How can I identify the cell in the spreadsheet into which the value of
an input field in the Form is stored?
You can identify the column that will collect answers to a form question by the label in row 1. Armed with that knowledge, you can reference the answers by column number in functions such as getRange().
...is there any way that I can read the values of the respective input
fields from a Google Apps Script?
There are multiple ways to reference input values:
As you found in Understanding Events, using a function triggered by Form Submission you can retrieve input values from the event itself. Two options here; you get a set of values in an array, and namedValues that you can reference using the question text as a name.
You can read the data from the spreadsheet; within that same trigger function mentioned earlier, you could use e.range.getValues() to get an array with all the submitted values, which you could then reference by index. Remember that this would be a 0-based array, while the column numbering starts at 1.
From my limited number of experiment cases, it seems that the
timestamps are always stored in the first column of the spreadsheet.
Is this guaranteed?
Unless you modify the spreadsheet, the timestamp will be in the first column. It is possible to insert columns to the left of the data table created by Forms, which will affect where you would find your form results in the sheet (although e.range will adjust). The order of all following values will be the order that the questions were created in the form. Note that if you delete a column (because you removed the question from the form, say), the column for the "deleted" question will be recreated at the end of the row.
...when I modified the Google form, the 'namedValues' member still
held the elements corresponding to deleted input fields. Is there any
way to loop over only those elements in namedValues that corresponds
to the fields actually input by a user?
There are reasons for remembering past questions, although they are just a bother when they weren't used to collect any real data. Better planning can be used to avoid the problem!
Unanswered questions will be empty strings in the event (e.g. e.namedValues["Dead Question"] == ''). So you could skip them like this:
for (var ans in e.namedValues) {
if (e.namedValues[ans] != '') {
doSomethingWith(e.namedValues[ans]
}
}
Note, too, that you can get array of "headers", or the form questions, like this:
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var headers = sheet.getDataRange().getValues()[0];
...and then use a search of headers to find the column containing the answer you're looking for.

How to make a date field to be autopopulated in Siebel CRM Desktop?

Whenever I create a new activity, I need a date field to be autopopulated ( it will be autopopulated but greyed out until and unless a checkbox next to it needs to be checked).
I perform a validation based on the date field, when a new activity is created. since the date field check box is not checked, it is not considering the value for the validation.
Any help or suggestion is appreciated.
Thanks.
Jaya Vignesh.
make use of predefault and postdefault values to populate current-date.
set field Read-only (BC field user property). You can find it under Business Component in object explorer.
Field read-only allows you to make a field read-only based on value of other field from same BC or joined field.
I perform a validation based on the date field, when a new activity is created. since the date field check box is not checked, it is not considering the value for the validation.
This requirement of yours isn't clear what exactly you want to validate. Since you are populating it bydefault, I don't find the significance in validating your own auto-populated data. well yet I provide a suggestion below
There are two types of validations, 1. Using configuration or 2. Using scripting. I am not pretty much sure if it can be achieved with configuration but scripting it is possible by overriding BusComp_presetFieldValue, BusComp_preWriteValue. The first one executed when you populate a field. And the latter one when you commit the record.
I have answer assuming your requirement. Let me know if you have any questions or clarifications required.
You can add the Predefault property of the field to be the following
System: TimeStamp

Listing SSRS subscriptions with user-defined descriptions

We have a growing number of non-data-driven SSRS 2008 subscriptions and the default list in SSRS does not provide any way to indicate what each subscription is all about. Yes, there is a description but it is auto-generated and not very helpful. We need it to say "Company ABC Quarterly to Managers", for instance.
I looked at using the ReportingService2010 web service and managed to not only read each report's description but modify it. However, as soon as someone edits the subscription from SSRS, which will be required sometimes, the description reverts to the auto-generated one.
Although I have never worked with data-driven reports, I wonder whether these will provide the functionality that I need. It just seems like a lot of work to set up, given that I don't really need the subscriptions to be data-driven.
Am I missing something simple here? Is this simple functionality something that comes with upgrading to a newer SSRS version?
Thanks!
Am I missing something simple here? Is this simple functionality
something that comes with upgrading to a newer SSRS version?
It does not appear that standard subscriptions in SSRS 2012 allow descriptions to be entered either (I couldn't find a screenshot of the UI though).
Although I have never worked with data-driven reports, I wonder
whether these will provide the functionality that I need. It just
seems like a lot of work to set up, given that I don't really need the
subscriptions to be data-driven.
I would argue against the need for data-driven subscriptions if standard subscriptions are fulfilling the business need. Would this be worth your time and effort? If it is, the obvious advantage is that subscription descriptions are editable in the UI, and do not appear to be overwritten when modifying the subscription.
If you're still interested in using standard subscriptions...
One way to "hack" SSRS such that the subscriptions will not overwrite the description (which isn't editable in the UI anyway) would be to modify the stored procedure ReportServer.dbo.UpdateSubscription.
DISCLAIMER: Use the following advice at your own risk. This involves modifying a standard sproc that Reporting Services relies on.
You can alter the update statement such that the description value would only be modified if the subscription is not a data-driven subscription (we do not want to break data-driven subscription descriptions, which are editable in the UI). In the stored procedure, you can distinguish data-driven subscriptions from standard subscriptions by looking at the value of #DataSettings. If it IS NULL, then it is a plain old subscription. If it IS NOT NULL, then we're looking at a data-driven subscription.
The following line in the Update statement:
[Description] = #Description,
Can be changed to:
[Description] = CASE WHEN #DataSettings IS NULL THEN [Description]
ELSE #Description
END,
This would keep all standard subscription descriptions the same when they are modified in SSRS, but allow data-driven subscription descriptions to be modified.
Per Mat's Mug, I am noting the solution that I eventually used:
Since all of our subscriptions involve emailing the report, we could get away with re-purposing the email subject field as the description. This way it was possible to produce a listing of all subscriptions and show an arbitrary description for each one.
Here's an expansion on the hack from dev_etter. I was able to use the Stored Procedure #parameter input along with a new Report Parameter (pReportParameterName) to create a dynamic, user controllable description that's unique to the report.
Add a new hidden text parameter to the report (pReportParameterName)
Add the Code Block 1 below in Stored Procedure UpdateSubscription above the UPDATE statement.
Change the 'Description = ' line of the UPDATE statement to something like Code Block 2 below.
With that set up, create or edit a Timed Subscription and enter the desired text into the Description parameter. After saving you should see the entered description in the Description column of the Subscriptions screen.
/*** Code Block 1 ***/
DECLARE #Param as XML = CAST(#Parameters as XML)
DECLARE #MY_Description as varchar(512)
SELECT #MY_Description = e.f.value('(.)[1]', 'varchar (100)')
FROM (select 1 id, #Param xCol) tx
CROSS APPLY tx.xCol.nodes('./ParameterValues/ParameterValue') AS a(b)
CROSS APPLY a.b.nodes('./Name') AS c(d)
CROSS APPLY a.b.nodes('./Value') AS e(f)
WHERE c.d.value('(.)[1]', 'varchar (100)') LIKE 'pReportParameterName'
/*** Code Block 2 ***/
[Description] = --#Description
CASE
WHEN #DataSettings IS NULL
AND #MY_Description IS NOT NULL
THEN #MY_Description
ELSE #Description
END,
Cheers,
Sj