How to implement scheduler in Apex? - email

I see scheduler like feature in salesforce but it is somewhat tied with existing features that salesforce provide and no sample source code is provided as far as my research goes.
What I want to do is to create my own scheduler that sends simple email based on date.
Goal:
Custom Object Player has fields
startDate : date like '2010-11-01'
email : text field like foo#bar.com
name : player's name like John.
If today's date is one day before the startDate, I want to send email to the Player.
For instance, Player's name is John and if today is 2010-12-10 and one Player's startDate is set to 2010-12-11, email saying "hello John" is sent.
Unfortunately I cannot find good example or tutorial online or salesforce doc how to do this using Apex.
Could anyone point out where to get started?
UPDATE
I want to extend the answer from eyescream.
After setting scheduler, you can set what follow up action to take like sending email using template or set custom object fields to some values.
Below I found useful for people using email template in Visualforce format.
I have custom object 'alertTester' which has reference to other object 'custom' and even this object 'custom' has reference to another object 'custom1GrandChild' and all the relationship (up to 3 or 5 layers I think) can be accessed like below.
I've tested below and works fine. Now I'm receiving email with my condition set :)
<messaging:emailTemplate subject="Hello" recipientType="User" relatedToType="alertTester__c" >
<messaging:plainTextEmailBody >
{!relatedTo.name}
{!relatedTo.custom__r.name}
{!relatedTo.custom__r.custom1GrandChild__r.name}
</messaging:plainTextEmailBody>
</messaging:emailTemplate>

Check out solutions that don't involve code before you'll dive deeply to Apex...
Email Alert + Workflow Rule should provide you with all functionality you need in this scenario and involve just clicking without any code.

I'm answering to my own question again..
Below link, search for schedule
http://www.salesforce.com/us/developer/docs/apexcode/index.htm
Looks like Apex has Schedulable interface that I can implements and set up cron task.
Below is sample code provided in the doc:
global class TestScheduledApexFromTestMethod implements Schedulable {
// This test runs a scheduled job at midnight Sept. 3rd. 2022
public static String CRON_EXP = '0 0 0 3 9 ? 2022';
global void execute(SchedulableContext ctx) {
CronTrigger ct = [SELECT id, CronExpression, TimesTriggered, NextFireTime
FROM CronTrigger WHERE id = :ctx.getTriggerId()];
System.assertEquals(CRON_EXP, ct.CronExpression);
System.assertEquals(0, ct.TimesTriggered);
System.assertEquals('2022-09-03 00:00:00', String.valueOf(ct.NextFireTime));
Account a = [SELECT id, name FROM Account WHERE name =
'testScheduledApexFromTestMethod'];
a.name = 'testScheduledApexFromTestMethodUpdated';
update a;
}
}

Related

Multiple conditional emails sent based on Google Form submission

I use the below script with a google form which sends an email to different people based on the answer chosen on the form. The script works and sends an email to the correct person when I use it with a form where the user can only choose one option.
But now I have a form where a user can choose between 1 and 6 options for the selection of cases to match. For every option chosen, I need an email to be sent to the corresponding department. With switch command, I understand that it tests an expression against a list of cases and returns the corresponding value of the first matching case. What I need is for it to test against a list of cases and return ALL corresponding values and then email based on that. Sometimes that would be one email, sometimes that could be 3 emails to 3 different people, etc.
The question on the google form is a checkbox question so a user can choose any and all if it applies. Each option correlates with a different email in my script.
Currently, if the form is filled out and only one option is chosen (see screenshot question "announcement outlet"), the script runs and sends the email as it should. But if two or more options are selected, no email goes out. When I check the trigger notes, the error is:
Exception: Failed to send email: no recipient
at sendFormByEmail(Code:47:13)
Here is my current script which works when only one option can be chosen. I believe I need a different command other than switch, but don't know what. I looked into fallthrough, but don't think that would work for this either.
function sendFormByEmail(e)
{      
// Remember to replace XYZ with your own email address  
var named_values = e.namedValues  
var teachername = named_values["Teacher Name"];    
var info = named_values["Your message/announcement"];  
var time = named_values["Please include time frame"];  
var photos = named_values["Include photos with this form if applicable; you can also create the graphic for social media and include below"];  
var announce = named_values["Choose announcement outlet"].toString();  
var email;
 
 // Optional but change the following variable  
// to have a custom subject for Google Docs emails  
  
// The variable e holds all the form values in an array.  
// Loop through the array and append values to the body.  
var message = "";      
for(var field in e.namedValues) {    
message += field + ' :: ' 
              + e.namedValues[field].toString() + "\n\n"; 
 }   
  switch (announce) {    
case "School Intercom Announcement":      
var email = "person1#school.net";      
break;    
case "MHHS Website":      
var email = "person2#school.net";      
break;    
case "MHHS Social Media (Instagram, Facebook, Twitter)":      
var email = "person3#school.net"     
break;    
case "Week in Pics":      
var email = "person4#school.net"  
var body = "Week in Pics Request"    
break;  
case "Remind text message (goes to students - please specify in your message info if it is all grades or specific grades)":
var email = "person5#school.net"
var subject = "Remind Text Request"
break;
case "Phone call home":
var email = "person6#school.net"
break;
}  
 // This is the MailApp service of Google Apps Script  
// that sends the email. You can also use GmailApp here.  
MailApp.sendEmail(email, subject, message);   
}
When multiple options are chosen, the data in the cell reads "Option 2, Option 4" and all my listed cases in the script above are for only "Option 2" or "Option 4", etc. Is there a way make this happen without having to make a case for every possible combination of the 6 choices that could potentially happen?
One way to fix the code
Remove .toString() from var announce = named_values["Choose announcement outlet"].toString();. Rationale: There is no need to convert an Array into a string for this case.
Instead of switch use if's, more specifically, add one if for each case clause, using an expression to test if the case label is included in announce. Example:
Replace
case "School Intercom Announcement":
by
if(announce.includes("School Intercom Announcement")){
// put here the case clause, don't include break;
// Add the following line before the closing `}` of the if statement
MailApp.sendEmail(email, subject, message);
}
Rationale: It's easier to implement the required control logic using if and Array.prototype.includes rather than doing it using switch.

Get SOST database ID of sent emails

I have an ABAP program that sends emails. A sent email is stored in SOOD table. After sending an email I would like to get some ID of the email to be able to check its status later (in SOST table). I have seen more functions/methods to send email (e.g. cl_bcs/send, SO_NEW_DOCUMENT_SEND_API1), but none of them returns any ID. Is there a reliable way to get it?
Function module SO_NEW_DOCUMENT_SEND_API1 create and export a new OBJECT_ID for every new message sent, As you can see in here -
This NEW_OBJECT_ID stored at BCST_SR table in SCOM_KEY field. From BCST_SR table you've to get DOC_OID, using DOC_OID you can get details from SOOD table. (Reference field in SOOD is - IF_DOC_BCS ) Then use the Object number OBJNO to get the details from SOST table.
Also you can refer t-code SBWP to check your mail status.
For class CL_BCS, you can check the send_request object's method doc_wrapper_id. This will return the sood structer.
Two other answers gave me together valuable clues to get it done (+1). But both missed some accuracy and code snippets, so I sum it all up in my answer.
using cl_bcs
DATA gr_send_request TYPE REF TO cl_bcs.
DATA emailid LIKE soodk.
gr_send_request = cl_bcs=>create_persistent( ).
" ...
CALL METHOD gr_send_request->send(EXPORTING i_with_error_screen = 'X'
RECEIVING result = gv_sent_to_all ).
IF gv_sent_to_all = 'X'.
emailid = gr_send_request->send_request->doc_wrapper_id( ).
ENDIF.
SOODK (not sood) is structure containing three components (OBJTP, OBJYR, OBJNO) which are together the key in SOOD table.
using SO_NEW_DOCUMENT_SEND_API1
DATA LT_OBJECTID TYPE SOFOLENTI1-OBJECT_ID.
CALL FUNCTION 'SO_NEW_DOCUMENT_SEND_API1'
EXPORTING
DOCUMENT_DATA = LT_MAILSUBJECT
DOCUMENT_TYPE = 'HTM'
IMPORTING
new_object_id = lt_objectid
" ...
lt_objectid (SOFOLENTI1-OBJECT_ID) is char(17), that contains concatenated SOODK structure OBJTP+OBJYR+OBJNO. When divided to parts, it can be used to lookup a record in SOODK table. (I didn't find it in BCST_SR-SCOM_KEY, but it was not necessary.)

how to solve actions on google-Api.ai error

Screenshot 2The one screen shot of this errorissue I am building an app using api.ai , an syllabus app which tells you the syllabus, but when I invoke it with desired parameters like branch and semester I have made each individual intent for it even then I'm getting miss answers sometimes like when asked for sem 4 and branch electronics its showing sem 3 sem 4 or of other branch . I have given sem and branch as required n given few invoking statements even then getting this. Tried even training it manually for free 30s of actions on api.ai no solution please help. Not using any web hook , context , event.
Short answer - check here for screenshots http://imgur.com/a/tVBlD
Long answer - You have two options
1) Create 3 separate custom entities for each branch type (computer science, civil, communication) which you need to attach to your branch parameter
2) Using the sys.any entity and attaching it to your branch parameter; then determining what the incoming parameter value is on a server then sending back a response through a webhook.
If you go the second route, you have to create a webhook and hardcode recognized words like 'computer science' in IF statements which check the incoming parameter (sent through JSON from API.AI). This route will be more difficult but I think you will have to travel it regardless because you will have backend architecture which you access to find and return the syllabus.
Note the second route is what I did to solve a similar issue.
You can also use regex to match an item in a list which limits the amount of hardcoding and if statements you have to do.
Python regex search example
baseurl = "http://mywebsite.com:9001/"
# Parse the document
# Build the URL + File Path and Parse the Document
url = baseurl + 'Data'
xmlLink = urllib.request.urlopen(url)
xmlData = etree.parse(xmlLink)
xmlLink.close()
# Find the number of elements to cycle through
numberOfElements = xmlData.xpath("count(//myData/data)")
numberOfElements = int(numberOfElements)
types = xmlData.xpath("//myData/data")
# Search the string
i = 0
while numberOfElements > i:
listSearch= types[i].text
match = re.search(parameter, listSearch, re.IGNORECASE)
if match is None:
i += 1
else:
# Grab the ID
elementID = types[i].get('id')
i = 0
break
An simple trick would be what i did, just have an entity saved for both branch and semester , use sys.original parameters and an common phrase for provoking each intent saves up the hard work.

Anylogic is assigning the value to all entities instead of only one

My source has the following code in "On at exit" field:
TRUCK.ID_number = parameter;
parameter = parameter + 1;
Then, each truck will receive an ID: 1, 2, 3, ...
The problem is that All the trucks are circulating at the same time and it looks like everytime a new truck is generated and the code runs it resets the ID for all trucks.
For example: When truck 4 (ID = 4) is created at the source all the other trucks receive ID 4 so I cannot know the correct ID of each truck.
What am I doing wrong?
a few things. First, you need to use the keyword agent in the onExit code box. So in your case, agent.ID_number=parameter. Please read up on these specific keywords that pop up everywhere in AnyLogic code boxes. I call it the "magic lightbulb", also see my blog on that topic:
The magic lightbulb
Second, newly created agents automatically get a unique index (if they belong to the same population). You can access that using the getIndex() method inside your truck agent.
The answer is: Use entity.ID_number=parameter

Get details of cells changed from a Google Spreadsheet change notification in a machine readable format

If I have a Google Spreadsheet e.g.
https://docs.google.com/spreadsheet/ccc?key=0AjAdgux-AqYvdE01Ni1pSTJuZm5YVkJIbl9hZ21PN2c&usp=sharing
And I have set up notifications on it to email me immediately whenever a cell changes.
And I make a change to that spreadsheet via the spreadsheet API - i.e. not by hand.
Then I get an email like this:
Subject: "Notification Test" was edited recently
See the changes in your Google Document "Notification Test": Click
here
other person made changes from 10/01/2014 12:23 to 12:23 (Greenwich
Mean Time)
Values changed
If I open the 'Click here' link then I get this URL which shows me the cell that has changed in the spreadsheet:
https://docs.google.com/a/DOMAINGOESHERE/spreadsheet/ver?key=tn9EJJrk6KnJrAEFaHI8E3w&t=1389356641198000&pt=1389356621198000&diffWidget=true&s=AJVazbUOm5tHikrxX-bQ0oK_XEapjEUb-g
My question is:
Is there a way to get the information about which cell has changed in a format that I can work with programmatically- e.g. JSON?
I have looked through the Google Spreadsheet API:
https://developers.google.com/google-apps/spreadsheets/
and at the Drive API Revisions:
https://developers.google.com/drive/manage-revisions
I have also tried setting up an onEdit() event using Google Apps Script: https://developers.google.com/apps-script/understanding_triggers
I thought this last approach would be the answer.
The problem with this approach is that whilst onEdit can be used to email details of changes, it appears to only be fired if the spreadsheet is edited by hand whereas mine is being updated programmatically via the spreadsheet API.
Any ideas?
You could build a function that checks for changes. One way to do this is by comparing multiple instances of the same spreadsheet. If there are differences, you could email yourself. Using the time driven trigger, you can check every minute, hour, day, or week (depending on your needs).
var sheet = **whatever**;//The spreadsheet where you will be making changes
var range = **whatever**;//The range that you will be checking for changes
var compSheet = **whatever**;//The sheet that you will compare with for changes
function checkMatch(){
var myCurrent = sheet.getRange(range).getValues();
var myComparison = compSheet.getRange(range).getvalues();
if(myCurrent == myComparison){//Checks to see if there are any differences
for(i=0;i<compSheet.length;++i){ //Since getValues returns a 'multi-dimensional' array, 2 for loops are used to compare each element
for(j=0;j<compSheet[i].length;++i){
if(myCurrent[i][j] != myComparison[i][j]){//Determines if there is a difference;
//***Whatever you want to do with the differences, put them here***
}
}
myEmailer(sheet.getUrl());//Passes the url of sheet to youur emailer function
compSheet.getRange(range).setValues(myCurrent);//Updates compSheet so that next time is can check for the next series of changes
}
}
Then from Resources>Current project's triggers you can set checkMatch to run every minute.
Also check out https://developers.google.com/gdata/samples/spreadsheet_sample for pulling data as json