Sie sind auf Seite 1von 178

Cloud Computing

Salesforce CRM
Development
By

Capital Info
Solutions
Location :Shyamalal plaza,
Behind huda Mythrivanam,
Ameerpet.
KARUNAKAR XEROX CENTER
Behind Huda Mythrivanam,AmeerPet.
Ph No : 9908116001

This book has been developed especially from the idea of glance look learning. This book
helps for individuals who want to learn things with in short time. From this idea I started
writing this book which will be helpful to the professionals to learn quickly without
missing the things. While writing this book I faced many difficulties in which reduction
of 3000 pages to 200 pages is the main. After all my hard work from the 3 months I was
able to bring this book in front of you to use it responsibly. Bringing easier way of
learning to the students is the idea behind making complex things to simpler. I would like
to thank all the people who inspired and helped me in writing this book.

! "

#$

%&
,

' ( )*
-

+ (

" ./
(
( 0"- 1 -%

1) Customization in cloud22222222222222222222222222222222222222222222222222222222222222222221
2) Introduction to Apex22222222222222222222222222222222--------------------------------------2
3) Access Modifiers And Opps Concepts-------------------------------------------------3
4) Data types----------------------------------------------------------------------------------6
5) Apex Data Manipulation (DML) Operations-----------------------------------------11
6) SOQL and SOSL Difference and Examples------------------------------------------13
7) Collections---------------------------------------------------------------------------------18
8) Loops in Salesforce-----------------------------------------------------------------------22
9) Relationships in Salesforce--------------------------------------------------------------24
10) Standard formats of Relationship Queries---------------------------------------------26
11) Sample Relationship Queries-----------------------------------------------------------30
12) Creating Apex Class ---------------------------------------------------------------------32
13) Sample Apex Classes---------------------------------------------------------------------37
14) Triggers Introduction---------------------------------------------------------------------39
15) Sample Triggers with different scenarios----------------------------------------------42
16) Order Of Execution-----------------------------------------------------------------------66
17) Governors Limits -------------------------------------------------------------------------66
18) Annotations --------------------------------------------------------------------------------67
19) Understanding Testing in Apex----------------------------------------------------------70
20) Test Classes---------------------------------------------------------------------------------72
21) Apex Scheduler ----------------------------------------------------------------------------78
22) Sample Apex Scheduler-------------------------------------------------------------------78
23) Batch Apex---------------------------------------------------------------------------------80
24) Introduction to VISUALFORCE---------------------------------------------------------99
25) Controllers----------------------------------------------------------------------------------26) Tags used to Create VISUALFORCE Pages ------------------------------------------27) Sample VF Pages ---------------------------------------------------------------------------99
28) Force.com Migration Tool----------------------------------------------------------------128
29) Migration with change sets ---------------------------------------------------------------135
30) Migration Using Eclipse ------------------------------------------------------------------141
31) Interview Questions -----------------------------------------------------------------------158
32) Sample Project------------------------------------------------------------------------------168
2

(
.3
-2
* With Force.com developers can customize declaratively or programmatically.
Declarative Customizations can be made point and click in a browser.
Programmatic customizations are made with code.

*Declarative customizations require an understanding of Force.com concepts, without


coding Knowledge.
*Programmatic Customizations require coding skills and allow developers to extend
beyond the declarative Salesforce.com Capabilities.
,
5

- #,

4 2

.3

# ..

Applications
Tabs
Page Layouts
Record Types

Force.Com Pages
Web controls
Sites

User Interface

Workflow
Validation
Rules
Approval
Process

Force.Com Controllers
Business
Logic

Force. Com code


Web Services API

Objects
Fields
Relationships

Web Services API


Meta Data API

Data Models

Declarative Customization

Simplicity + Speed

Programmatic Customization

Control + Flexibility

0 6

.3

25

# ..

Most Complete and rebust solutions actually use a combination of declarative


and programmatic solutions developers should understand how to develop using both
declarative and programmatic features.

(
-+

#
.3

-+

Easy of development

More visual

# ..

.3

Can extend the capabilities of an


standard functionality

Fast

Easy of upgrades

Easy of maintenance

Does not require programmatic


skill set

* Force.com Apex code is a strongly typed programming language that


executes on the Force.com platform. Apex is used to add business logic to applications,
to write data base type triggers, and to program controllers in the user interface layer. It
has a tight integration with the data base and query language, good web service support,
and includes features such as futures and governors for execution in a multitenant
environment.
*Integrated with DML, Inline, SOQL and SOSL and holds the ability to do bulk
processing.
*Data focused.
*Hosted by the Force.com platform and knows multitenancy.
*Automatically upgradeable.
*The architecture is the same for developer and End user perspectives.
-+

"2

Low cost.
Single set of Hardware Resources.
User satisfaction.
Improved Quality.
Customer Retention.
Collaboration and Integration.
Error Free.
Easily Customizable and Upgradable.

(
8

-6

Create Web Services.


Create Email services
Perform complex validation over multiple objects.
Create complex business process that are not supported by workflow.
Create custom transactional logic.
Attach custom logic to another Application.
0 6-

6 49

All Apex runs entirely on demand on the Force.com platform, as shown in the following
architecture diagram.

Force.com Platform

Uncompiled Apex

Compiled apex
Applicatio
n Server

Deloper User
Request
Required

Result

Internet

Meta
Data
Apex
Runti

Apex

me

Compiled

apex
End User
The above diagram describes about the Apex compiled, stored and run entirely on the
Force.com platform.
* When a developer writes and saves Apex code to the Platform, The platform
application server first compiles the code into an abstract set of instructions that can be
understood by the Apex run time interpreter and then saves those instructions as
Metadata.
*When an end user triggers the execution of Apex, perhaps by clicking a button or
accessing a Visual force page the platform application server retrieves complied

(
instructions from the Meta data and sends them through the runtime interpreter before
running the result.
The end user observes no differences in execution time from standard platform requests.
7:5
Apex allows us to use the following modifiers
+
This is the default, and means that the method or variable is accessible only
within the Apex class in which it is defined. If we do not specify an access modifier, the
method or variable is private.
- This means that the method or variable is visible to any inner classes in the
defining Apex class. We can only use this access modifier for instance methods and
member variables. Note that it is strictly more permissive than the default (private)
setting, just like Java.
1
This means the method or variable can be used by any Apex in this application
or namespace.
&
: In Apex, the public access modifier is not the same as it is in Java. This was done
to discourage joining applications, to keep the code for each application separate. In
Apex, if we want to make something public like it is in Java, we need to use the global
access modifier.
This means the method or variable can be used by any Apex code that has
; 1
access to the class, not just the Apex code in the same application. This access modifier
should be used for any method that needs to be referenced outside of the application,
either in the SOAP API or by other Apex code. If we declare a method or variable as
global, we must also declare the class that contains it as global.
&
: We recommend using the global access modifier rarely, if at all. Cross-application
dependencies are difficult to maintain.

) "6

8
# : Use the with sharing keywords when declaring a class to enforce
the sharing rules that apply to the current user.

8
# : Use the without sharing keywords when declaring a class to
ensure that the sharing rules for the current user are not enforced.

An interface is like a class in which none of the methods have been


implementedthe method signatures are there, but the body of each method is empty. To
use an interface, another class must implement it by providing a body for all of the
methods contained in the interface.
6

(
: The abstract definition modifier declares that this class contains abstract
1
methods, that is, methods that only have their signature declared and no body defined.
- : Inheritance concept
Final variables can only be assigned a value once, either when we declare a
variable or in initialization code
: The virtual definition modifier declares that this class allows extension and
*
overrides.
/

: There are two different ways of using the this keyword.

We can use the this keyword in dot notation, without parenthesis, to represent the current
instance of the class in which it appears. Use this form of the this keyword to access
instance variables and methods. For example:
Public class myTestThis {
string s;
{
this.s = 'TestString';
}
}
In the above example, the class myTestThis declares an instance variable s. The
initialization code populates the variable using the this keyword.
Or we can use the this keyword to do constructor chaining, that is, in one constructor, call
another constructor. In this format, use the this keyword with parentheses.

For example:
public class testThis {
// First constructor for the class. It requires a string parameter.
public testThis(string s2) {
}
// Second constructor for the class. It does not require a parameter.
// This constructor calls the first constructor using the this keyword.
public testThis() {
7

(
this('None');
}
}
:The super keyword.can be used by classes that are extended from virtual or
abstract classes. By using super, we can override constructors and methods from the
parent class.
The following are special types of keywords that aren't reserved words and can be used as
identifiers.

: count() returns the number of rows that match the filtering conditions and
count(
) returns the number of rows that match the filtering conditions
and have a non-null value for
. This syntax is newer than COUNT() and
is available in API version 18.0 and later.

::
Apex supports the following OOPS concepts given below
Acquiring the properties of parents by children is what we call as
. We can make use of the same principle under object oriented language and
consume the members of one class under multiple classes by establishing Parent-Child
relationship between classes. This basically provides us
".
. Changing the behavior of entities depending upon input they receive is
known as Polymorphism. This can be implemented in object oriented language using
different approaches like
- Overloading: It is a feature that allows us to define multiple behaviours to a
method
- Overriding: To override parent classes method under child class first in the
parent class the method must be declared as 'Virtual'. Then only child classes can
override the method using
modifier.
1
This is all about Hiding the complexity of a program and providing with a
set of interface to consume the functionalities. Functions and Methods are examples for
Abstraction we never know the logic behind them, what we are is only how to consume
them.
Encapsulation is an Object Oriented Programming concept that binds
together the data and functions that manipulate the data, and that keeps both safe from
outside interference and misuse. Data encapsulation led to the important OOP concept of
- #.

(
It is all about hiding the code to secure the contents of a program. To hide the
code we enclose the members of a program under a container or wrapper known as class.
A wrapper or container class is a class, a data structure, or an abstract data type
whose instances are collections of other objects. In Apex and Visual force this type of
class can be extremely useful
7
- : A function or Method in general referred as Subprogram is a named block of
code which can be reused, when and where is called its get executed
It is also an action that has to be performed
A method can be either value returning or non value returning, use * - to tell the
method non value returning and if it value returning specify the type (primitive or
Sobject data type) of value it was returning using
keyword.
. :

Excludes,first,includes,last,order,after,before
<

) "6 -

"

- .

In Apex all variables and expressions have a data type they are two types of data
types
1. Primitive Data types
2. Sobject Types

. + 5

/"

A primitive data types such as an Integer, Double, Long, Date, Date Time, String,
ID, or Boolean.
* All Primitive date types are passed by value, not by reference.
* All Apex variables, whether they are class member Variables or member variables, are
initialized to null. Make sure that we initialize variables to appropriate values before
using them.
: - Initialize a Boolean Variable to False.
Apex Primitive data types include.
,

A value that can only be assigned true, false, or null.


: - Boolean is Active=True;
9

(
5
2 A value that indicates a particular day. Date values contain no information about
time. Date values must always be created with a system static method.
: - Date myDate= Date.newinstance(2012, 05 , 28);
= is 2012-05-28

00:00:00

/.
- 5 / . These are date types associated with dates and times along with
Date data type. The time data types stores times (hours, minutes, second and
milliseconds). The Date data types stores dates (Year month and day). The Date time data
type stores both dates and times.
Each of these classes has a newInstance method with which we can construct
particular date and time values.
2 Time mytime= newInstance(18,30,2,20);
= is 18:30:02
* We can also create dates and times from the current clock.
Date myDatetime = Datetime.now();
Date today= Date.today();
* The date and time classes also have instance methods for converting from one format to
another.
: - Time t= Datetime.now().time();.

*finally we can also manipulate the values by using a range of instance methods.
- Date myToday = Date.today(0;
Date myNext30 = myToday.addDays(30)
We will get something like this as the output.
2012-05-28 00:00:00
2012-06-29 00:00:00
# ( < #( 5 1
- 5 .
2 To store numeric values in variables, declare
variables with one of the numeric data types. Integer,Long Double and Decimal.
2 A 32-bit number that doesn't include a decimal point. Integers have a
#
minimum value of -2, 147,483,648 and a maximum value of 2,147,483,647.
2 Interger i=1;
10

(
< # 2 A 64 bit number that doesn't include a decimal point longs have a minimum
value of -263 and a maximum value of 263-1;
2 Long l= 2147483648L;
5 1 2 A 64- bit number that includes a decimal Point . Doubles have a minimum
value of -263 and a miximum value of 263-1.
: Double d= 3.14159;
5 . 2 A number that includes a decimal point. Decimal is an arbitrary precision
number. Currency fields are automatically assigned the type decimal.
>- Decimal dec=19.23;
We can use the value of static method to cast a string to a numeric type. For
example, the following creates an Integer from string 10 and then adds 20 to it.
2 Integer CountMe= Omteger.Valueof('10') +20;
& *
1 2 If we declare a variable and don't initialize it with a value, it will be
null. Null means the absence of a value. We can also assign null to any variable declared
with a primitive type.
Both of these statements result in a variable set to null;
Boolean x=null;
Decimal d;
# 2 Strings are set of characters and are enclosed in single quotes. They store text
values such as a name or an address.
2 String myvariable= ' Capital info Solutions';
* We can also create strings from the vales of other types, such as dates, by using the
string static method value of().
;- Date myDate= Date today();
*** String mystring= String value of (myDate);
The o/p of above example should be today's date 2012-05-29
:1!
/"
2 An Sobject, can be a generic SObject or be a specific SObjects, such
as an Account, Contact, or MYcustom__c.
* SObjects (short for "Salesforce Objects") are standard or custom objects that stores
record data in the Force.com database.There is also an SObject data type in Apex that is
the Programmatic representation of these SObjects and their data in code.
* Developers refer to SObjects and their fields by their API names.
11

(
2 Account a= new Account ();
MyCustomObject__c co= new MYCusomobject__c ();
API name of Custom Object.
* The following example creates an invoice statement with some initial values for the
description__c Fields and assigns it to variables of type Invoice-Statement__c, which is a
SObject type also.
2Invoice-statment__c inv- new Invoice-statement__c(Description__c= 'Test Invoice',
Status__c='pending')
* SObject Variables are initialized to null, but can be assigned a valid object reference
with the new operator.
:- Account a = new Account();Account a= new Account
(Name='Osmania University'), billingcity= 'Hyderabad');
(Or)
Account a= new Account ();
a.name='Osmania University';
a.BillingCity= 'Hyderabad';
# :1

- 2 SObject fields can be accessed or changes with simple dot

notation.
2 Account a = new Account ();
a.Name='Capital Info solutions';

Access the account name field and assign it 'Capital Info solutions'.
* System generated fields, such as Created by or last modified by cannot be modified. If
we try, the Apex runtime engine generates an error.
Additionally, formula fields and values for other fields that are read only for the context
user cannot be changed.
2 Contact c=New Contact();
c.count of __c='4':

Formula filed (This statement gives an error)

12

(
Sobject records represent
#
1!
#
2
relationship to other words with two fields an ID and an address that points to a
representation of the associated sobject.
: The contact sobject has both an AccountID field type ID and an Account field of
type accounts that points to the associated sobject record itself.
The ID field can be used to change the account with which the contact is associated,
while the Sobject reference field can be used to access data from the account.
The following Apex code shows how an account and contact can be associated with one
other, and then how the contact can be used to modify a filed on the Account.
2 Account a=new account (Name ='Osmania University')
Insert a;
Inserting the record automatically assigns a value to its ID field
:- Contact c= new contact (Last name='Anil Reddy')
C. Account ID=a.ID
The new contact now points at the new account.

Insert c;
".
, 4 2 An anonymous block is Apex code that does not get stored in the
meta data , but that can be compiled and executed using developer console.
*We can use Anonymous Blocks to quickly evaluate Apex on the fly such as in the
developer console.

1.
2.
3.
4.

Can include user-defined methods and exceptions.


User-defined methods cannot include the keyword "static"
We do not have to manually commit any data base changes
Unlike classes and triggers, anonymous blocks execute as the current user and
can fail to compile if the code violates the user's object and filed level
permissions.

* The developer console is a collection of tools we can use it to analyze and trouble
shoot applications in salesforce organization.
Its a separate window composed of a set of related tools that allows us to access
source code and review how it executes.
* Access the developer console by clicking

13

(
Your Name
Developer console
Click on "click here to enter Apex code" and
give the apex code and
Click on Execute" button
Select the particular Operation
Click on "Open Raw Log" button
Check the result in the USER-DEBUG statement

2
1. Interger i=10;
System debug (i);
2. Integer i=10;
Interger J=20;
System debug (The sum of two numbers'+ (i+j));
# 6

3. String S1='Anil';
String s2='sateesh';
System.debug (names are(s1+s2));
4. Account a =new Account ();
a.name ='capital Info solutions ';
System.debug (a name);

5
7
# # ?57<@ :
2 Use Data Manipulation
Language (DML) Operations to insert, update, delete, and restore data in a database.
We can execute DML Operations using two different forms.

1. Apex DML Statement, Such as


1!

?@>

2. Apex DML database methods, such as


5

% +

?@

A5

? 1!

?@@>

*The following example that inserts a new invoice statement by calling insert and if we
execute in the 'Developer console" that creates a record into the database.
14

(
+

BB

+A

BB ?5

BB AC

C@>
Insert Inv

Inserting the invoice using DML.

After the invoice statement is inserted the sobject variable inv will contain the ID
of the new invoice statement.
* The following example shows the creating records through API for Account object
using Insert DML Operation.
A

?@>

%& . AD: .
%

E +

AD 'F GFG

% .

2 AD

%,

"D>

D>
H#.

"AD0"-

% .D(

1 -D>

> this means assigning the field values to account record

57< :

The following example shows the creating a contact through API using DML operation
(Insert)
A
%

. AD

?@>
D>

5 AD

D>

Override any account id here


//This means assigning account to a contact
>
"

.%- 1 #? @>

For custom Objects;


. BB
%& . AD
%

. BB ?@>

D>

BB AD

D>

API Name of lookup filed or MD field


15

(
>
Customer__c is child object and partner__c is parent object
while inserting the object records the following notes
Certain SObjects cannot be created to insert an object record because the create
permission of the object must be set to true
We must supply a non-null value for all required fields
The insert statement automatically sets the ID value of all new subjects records
We can pass a maximum of 10,000 SObject records by using a single insert
method
:I< - : < I
2

The following table describes about the different between SOQL an


SOSL Queries.
SOSL

SOQL
1. SOQL (Salesforce object Query
Language)
retrieves The records
from the database by using
SELECT keyword
2. By using SOQL,we can know in
which objects or fields the data
resides
3. We can retrieve data from single
object or from multiple objects that
are related to each other
4. We can query on only one table

1. SOSL(sales force object search


language) retrieves the records
from the data base by using
FIND key word
2. By using SQSL,we dont know
in which object or field the data
resides
3. We can retrieve multiple objects
and field values efficiently when
the objects may or may not be
related to each other
4. We can query an multiple tables.

:I< I

"

*A SOQL query is enclosed between square brackets the following query retrieves an
subjects (a record from the database) that has the name field value equal to Osmania
University
AJ
Return type

:7

. AD: .

E +

"DK

Query (Applicable for only one record)

- In the above the a variable stores the ID ,Name of all accounts with
name=Osmania University
:- SOQL Statement evaluate to a list of SObjects single SObjects or an integer for
count method queries.
16

(
1!
< L
" BB AD
. DK>

<
6
#

1!

BB

AJ

BB M
AJ

A J

.
(

BB 8

BB 6

BB

-AD

/" BB A N

DK>
. K>

:I< , - # 2
Square bracketed queries support binding to Apex variable
# ! 1 " AD
/ . D>
<

BB M

AJ

BB 6

" BB A ! 1 " K>


Binding

2 SOSL sales force object search language

: <I

SOSL statements evaluate to a list of lists of SObjects where each list contains the
search results for a particular sobject type.
SOSL queries are only supported in Apex classes and anonymous blocks
We cannot use a SOSL query in a trigger

6 #

2 < L< L
/E & &;
" .%- 1 # ?

1!

MM
(

AJ &5 N/

OD & <<

1!

<5

K>
@>

This query will search the account and contact records that field values starts with test in
all fileds.
The following example returns a list of accounts, contacts, opportunities and leads
that begin with the phrase map.
< L< L 1! MM
A J &5 N. OD & << < 5
/E & &;
? 5( & . @(
(
"( < -K>
" .%- 1 #?
@>

? 5( & . @
- If a SOSL query does not return any records for a specified SObject type, the
search results include an empty list for that SObject

17

(
E -

-:

The update DML operation modifies one or more existing SObject records, DML
(update) statement syntax
Update SObject;
Update Subject[ ];
The following example describes us about an updating an account field through an
existing contact that has also been modified here two update statements are required
// use a SOQL Query to access data for a contact
AJ < /
< 7 / K>
%
%& . A N
%<
. AN
D>

%& .

:7

<

& . AD

D>

The above two statements says that change in fields for both contact and its
associated account
E -

> Updates the

E -

> Updates the

"

.%- 1 # ? @>

"

.%- 1 # ? %

%& . @>

The following example updating account fields through the API


AJ
. (
#( "
:7
8

- AD

DK>

/*This query retrieves the Name, Rating, Industry fields values of one particular
account*/
%& . AD: .
%

"D>

#AD0 D>

% -

"AD

E "

>

D>
/* This DML Operation used for updating an account */

. - 1 # ? @>

/* It is used to check the new values for that account*/

AJ
"

.%- 1 # ? %

& . >
-

:7

-AD

DK>

"@>

No compilation error, but it gives run time error like SObject row was retrieved via
SOQL without querying the requested filed.
18

(
5
:
:- The delete DML operation deletes one or more existing SObject
records, such as individual accounts or contacts, from organizations data.
The DML (Delete) statement syntax is

:1!

:1!

>
J K>

The following example is to delete the account record through the API
//First get the account record which we want to delete
AJ
> /*

5
.
6
& . AD: .
The DML Operation deletes the above record.*/

"D < 7 / K>

Deleting a record places it in the recycle bin from where we can restore it. Records in
the Recycle bin are temporarily stored for 15 days before they are permanently
deleted.
To restore just use the undelete DML statement .Notice that we used the ALL ROWS
keywords in the SOQL query to be able to retrieve the delete record.
AJ < /& .
:7
6
& . AD: .
E +
"D
<< :8 K>
E >

&

..
: - Comments are lines of text that we add to code to describe what it does
comments are not executable code. Its a good practice to annotate code with comments
as necessary.
Apex has two forms of comments
1. The first uses the // token to mark everything on the same line.
2. The second encloses a block of text, possibly across Multiple lines
between the /* and */ tokes
The following example describes only the debug statement runs:
System.debug (capital info solutions ); //This comment is ignored.
/* Hi All, All the Best
From capital info solutions */
+ "2

Apex is case insensitive this means that all apex code, including method names class
names, variable names and keywords, can be written without regard to case
2
# ."+ >
#

7P*

>

both are equivalent statements

19

(
The following statements print out todays date using the System today method when we
execute them in the Developer Console.
"

.%- 1 # ? "

.% - " ?@@>

"

.%- 1 # ? "

.%/ - " ?@@>

"

.%- 1 # ? "

.%/:5 " ?@@>

- A good practice is for class names to start with an uppercase letter and method
names to start with a lowercase letter.
2Collections are the group of similar types Apex has the following types of
Collections
Lists
Maps
Sets
There is no limit on the number of items a collection can hold However there is a
general limit on heap size.
<

A list is an ordered collection of typed primitives SObjects, user-defined objects,


Apex objects or collections that are distinguished by their includes.
40 90
0

52 63
2

70
4

The index position of the first element in a list is always 0


To declare a list, use the list keyword followed by the primitive data, SObject, nested
list, map, or set type within < > characters
< L
# M ."
A 6
L
# M ?@>
This will store the block of memory at the database

< L< L L
# MMM ."
A 6 < L L L
# MMM?@> Nested
List
A list can only contain up to five levels of nested collections inside it.

*The following example describes us about the retrieving 100 accounts stored in variable.
<

AJ

5( & .

:7

< 7 / ''K>

*To access elements in a list, use the system methods provided by Apex.
2< L
# M<A 6< L
# M ?@> Define a new List
< % -- ? G@> adds a second element of value 47 to the end of the list
20

(
#

? @> Retrieves the element at index 1.

A< %#

?'( GQ@> adds the integer 73 to the list at index o

<%
<%

removes all elements from the list

?@>

*Go to the Developer console and execute the following code and check the result by
going through USER-DEBUG
<

#M < A 6 < L

< % -- ?N

D@>

< % -- ?N

D@>

< % -- ?N& #

! D@>

"

#M ?@>

.%- 1 # ?< @> the o/p from this line is


Anil
0

Sateesh

Nagaraju

String name = Li.get (0);


System.debug (name); the o/p from this line is ANIL
Li.set(2, sanjeev);
System debug (Li);

Anil
0

Sateesh
1

the o/p from this line is

sanjeev
2

Li.clear ();

clear all elements in a list

System.debug (li);

the o/p from this line is null.

- In a list, we can add Duplicate values that is duplicate values will be allowed
inside a list.
2 A set is an unordered collection of primitives or SObjects that do not contain any
duplicate elements.To declare a set, use the set keyword followed by the primitive data
type name within < > characters
R 2 set <string> s= new set < string > ();
To access elements in a set use the system methods provided by Apex.
21

(
Define a new set

<Integer> s=new set <Integer>();

Adding an element to the set

S.add (1);
Boolean b= s.contains(1);
1 contains within the set.

It will returns true when the element

s.remove (1);

Remove the element from the set

*Go to the Developer console and execute the following code and check the result by
going through USER-DEBUG();
Set <string> s=new set <string>();
s.add(red);
s.add(bule);
s.add(Black);
s.add('green');
system.debug (s);
This statement gives the o/p below
{Black, blue ,green ,red ]
s.remove ('green');
system.debug (s);
This statement gives the Output as below
{Black, blue, red}
s.add ('red');
system.debug(s)
#### This statement gives the o/p as below
{black, blue, red} because the set will not allow duplicate values inside it
Boolean b= s.contains ('black')
###Returns true when the value 'black' is there within set and it returns "False" when the
value 'black' is not there within set.
*Uniqueness of sobjects is determined by comparing fields
2 If we try to add two accounts with the same name to a set,only one is
added.
//Create two accounts a1 and a2
22

(
Account a1=new account (Name='Test Account');
Account a2=new account (Name='Test Account');
//Add both accounts to the new set
set<Account> acc set = new set <Account > {a1,a2};
system.assertEquals (accset.size(),1);
This statement is used to verify the set only contains one item.
7

A map is a collection of key-value pairs where each unique key maps to a single
value
*Keys can be any primitive datatype while values can be primitive, sobject,
collection type or Apex object.
*To declare a map, use the Map keyword followed by the data types of the value
within < > characters
2Map < string, string> m=new map <string, string> ();
Map<ID, set<string>> m1=new Map<ID, set <string>>();
Map<ID,
Map
<ID,Account
map<ID,Map<ID,Account[]>>m2;

[]>>

m2=new

Similar to lists, map values can contain any collection and can be nested
within one another. A map can only contain up to five levels of nested
collections inside it.
The following example gives the information about how a map of contain and
currencies
Country

currency

Key

Value
Map<string, string> m= new Map<string> ();
m.put (India, 'Rupee);
m.put (us, 'Dollar');

Insert a new key value pair in the map

m.put (uk, 'Pounds');


system.debug (m);

the o/p of this line will be

{India= Rupee, us=Dolar, uk= pounds}


23

(
string currency = m.get('uk'); Retrieve a value given a particular key
system.debug (currency),
system.debug (m.keyset ());
keys in the map.

the o/p of this will be pounds


Return a set that contains all of the

system.debug (m.containkey ('uk'));


This statement gives the true or false whether for particular key have a value or
not.
2 Account a= new Account (Name='capital',Bullingcity='Hyd');

Map<Integer, Account> map1=new map<integer, Account> ();


map1.put (1, a); Insert a new key value pair in the map
Map<Integer, Account >map2=map1.clone ();
###Makes a duplicate copy of the map
system.debug ((map1.get (1) Billingcity));
###This statement gives the Billingcity filed value of the value pair that is
assigned to the key 1.
####Hyd
: <::

Apex supports three variations of the for loop


1. The Traditional for loop
for (i=0; i<=100; i++) {
-------- }
2. The list or set of iteration for loop
for (variable ; List-or-set) {
-}
: List <account > a = {select name from account};
for (Account acc: a)
{

24

(
------- Code block
}
Where variable (acc) must be of the same primitive or SObject n type as
List -or-set.
3. The SOQL for loop:
for (variable: [Soql-query]) { or variable list.
---}
Both variable and variable-list must be of the same SObject type as is returned
by the Soql-query.
for (Account a: [Select Name FROM Account where
id='XXXXXXXXXX']
{
------}
(OR)
for( List <account> acc: [Select Name From account])
{
-------}

<

:I< I

" 2

The following program displays the Account Names by one by one that are
associated with Contact Names.
List <Contact > Lc = [Select Account Id, FirstName,
LastName, account.accountid];
This SOQL query will retrieves the all the Contact records with Account Id,
FirstName and LastName and Last Name filed values.
List > string > accid = new List <string> ();
25

(
For (contact c : lc)
{
accid. add (c. account id);
This statement adds all accountids to the acc id Variable.
System.debug ('The lists of IDs are ' + accid).
List < Account > la = [Select Name from Account where id =: acc
id];
for (Account Acc : la)
{
System.debug (Acc.Name);
}
I
-2 2

2
2

Using the relationships, we can retrive the related Objects data using the SOQL
query.
Contacts --------------<-----------Account
Relationship name = Account
In the child -to-parent Relationship, we can query on Contact and retrieves the
values from Account that is associated.
Ex: Contact C = [Select First Name, LastName, Account.Name, Account
.Industry from Contact where id = 'XXXXX'];
System.debug (c. Account .Name); Prints the Account Name of Contact
System.debug (C. Account. Industry);
account
2 2

Prints the industry field value from

In the parent-to-child relationship. We can query on the parent object and we


will get the details about child records.
Account a = [Select Name, (Select Contact .FirstName,
contact .LastName from Account. Contacts) From Account where id ='xxxxxxx']
26

(
System debug (a); this will give all the Contact for that
account
For (Contact C: a.Contacts)
{
system.debug (C. First Name);
}
This statement displays FirstName of all contacts that are associated with the
account.
When we want to write query on parent to child relationship then we need
to write subquery ( query within another query)
.

2
This selection explains how relationship names for Custom objects and Custom
fields that are
created and used.
*When we use a relationship name in a query. We must use the relationship
names without __c. instead, append an ---r(underscore underscore r).
Daughter__c------------------->--------Mother-of-child__c
Relationship Name =Mother -of-child---r, child -to-parent Relationship.
parent-to-child Relationship, Relationship =Daughter--r
When we use a child-to-parent relationship.
Daughter_ _c D= [Select id, First name _ _C, Mother-of child_
_r.firstname from daughter where LastName_ _C LIKE 'C%']
The above query returns the ID and first name of daughter objects, and the first
name of the daughter's mother if the mothers last Name begins with 'C'
SELECT LastName __c, (Select LastName__c From Daughters --r)
FROM motherof-child __c.
The above query returns the Last name of all mothers, and for each mother
returned, the last name of the mother's daughters.
- ==

.
#

I
-

-S

- - 1!

Child obj name


variable = [select child obj field1, parent obj name.parent obj field1,
parent obj name.parent obj field2 from child obj name where condition];
27

(
System.debug (child obj records are+variable);
System.debug ( parent obj field1+variable .parent obj name.parent obj field1);
System.debug (parent obj field2+variable.parent obj name.parent objfield2);
==

#.

-2

- - 1!

List<Child obj name>


variable = [select child obj field1, parent obj name.parent obj
field1, parent obj name.parent obj field2 from child obj name where condition];
System.debug (child obj records are+variable);
For (child obj name variable1: variable)
{
System.debug ( parent obj field1+variable1 .parent obj name.parent obj field1);
System.debug (parent obj field2+variable1.parent obj name.parent objfield2);
}
==E -

#.

-2

- - 1!

List<Child obj name>


variable = [select child obj field1, parent obj name.parent obj
field1, parent obj name.parent obj field2 from child obj name where condition];
System.debug (child obj records are+variable);
For (child obj name variable1: variable)
{
Variable1.parent obj name.parent obj field1=..
Variable1.parent obj name.parent obj field2=
Update variable1.parent obj name;
System.debug ( parent obj field1+variable1 .parent obj name.parent obj field1);
System.debug (parent obj field2+variable1.parent obj name.parent objfield2);
}
==

#.

- - 1!

List<Parent obj name> variable= [select fieldname1 (select field1, field2 from parent
obj name.childs obj)from parent obj name where condition];
System.debug (parent obj records+variable1);

28

(
For (parent obj name variable1: variable)
{
For (child obj name variable2:variable1.child plural obj name)
{
System.debug (child obj field1+variable2);
System.debug (child obj field2+variable2);
}
}
==E -

#.

- - 1!

List<Parent obj name> variable= [select fieldname1 (select child obj field1, child obj
field2 from parent obj name.child plural obj) from parent obj name where condition];
System.debug (parent obj records+variable1);
For (parent obj name variable1: variable)
{
For (child obj name variable2:variable1.child plural obj name)
{
Variable2.child obj field1='.';
Variable2.child obj field2='.';
update variable2;
System.debug (child obj field1+variable2);
System.debug (child obj field2+variable2);
}
}
==

#.

list<parent obj API name>


field1,child obj field2

. 1!

variable=[select parent obj field1 ,(select

child obj

from parent obj API name.child plural obj name__r) from parent object API name where
condition);

29

(
System.debug (' parent object records'+variable);
for (parent obj API name variable1:variable)
{
For(child obj singular name__c variable2:variable1.child plural obj name__r)
{
Variable2.field1 API name='..';
Variable2.field2 API name='.';
update variable2;
System.debug ('field1'+variable2);
System.debug ('field2'+variable2);
}
}
==

#.

-2

. 1!

list<child obj API name> variable=[select child obj field1,parent obj name __r.field1
from child obj API
name where condition];
system.debug ('child obj records are'+variable);
for( child obj API name variable1:variable)
{
Variable1.parent obj singular name__r.field1 API name='.';
update variable1.parent obj singular name__r;
system.debug('parent obj records'+variable1.parent obj singular name__r.field1
API name);
}
.
E -

I
#

-2

- - :1!

list<Contact> c=[Select LastName, Account.Name From Contact where name like


'%red%'];
30

(
for(Contact ct : c)
{
ct.Account.Industry='Banking';
ct.account.Rating = 'Hot';
update c.account;
}
E -

- - :1!

List<Account>
a
=
[Select
Name,(Select
FirstName,LastName
Account.Contacts) From Account where Name='Account1'];

from

System.debug('The Account Records are' +a);


for(Account acc1:a)
{
for(Contact c:acc1.Contacts)
{
c.FirstName='Anil';
c.lastName='Reddy';
update c;
System.debug ('The Updated Contacts are' +c);
}
}
#

-2

Patient__C pt = [select
id='a0190000002wRdn'];

. :1!
name

medical__r.name

from

patient__C

where

System.debug('Patient Records '+ pt);


System.debug('Doctor Records '+pt.medical__R.Name);
31

(
list<patient__C> pt = [select name , Medical__r.name from patient__C where name like
'sath%'];
System.debug('Patient Records '+ pt);
for(patient__c pt1 :pt)
{
system.debug('medical Records Are ' + pt1) ;
}
E -

-2

. :1!

Patient__C pt = [select
id='a0190000002wRdn'];

name

medical__r.name

from

patient__C

where

System.debug('Patient Records '+ pt);


pt.medical__r.med_quantity__C = 66;
update pt.medical__r;
System.debug('Medical Name '+pt.medical__r.Name);
System.debug('Medical quantity '+pt.medical__r.med_quantity__C);
7

list<patient__C> pt = [select name , Medical__r.name, medical__r.med_quantity__C


from patient__C where name = 'sateesh'];
System.debug('Patient Records '+ pt);
for(patient__c pt1 :pt)
{
pt1.medical__r.med_quantity__C = 99;
update pt1.medical__r;
system.debug('medical Records Are ' + pt1) ;
}
#

. :1!

Medical__c t=[Select Name,(Select Name from patients__r) From Medical__c


where id='a0290000005FUJq'];

32

(
System.debug('XXXXXXXXXXXX'+t);
System.debug('DDDDDDDDDDDDDD'+t.patients__r);
for(medical_ _c s:t.patients__r)
{
System.debug(s.Name);
}
7

List<Training__c> t=[Select Name,(Select Name, Student_fee__c from Students__r)


From Training__c ];
for(Training__c t1:t)
{
System.debug(t1.Name);
}
for(List<Student_ _c s:t1.students_ _r)
{
System.debug('AAAAAAAAAA'+s);
}

#
"

Private | public | global


[Virtual | abstract | with sharing | without sharing | (none)]
Class
[implements
| (none)] [extends
{
// the body of the class

| (none)]

}
To create an Apex class, go to the following path
33

(
Your Name SetupApp setupDevelopclick on Apex classesclick on "New"
button.
*In the editor pane, enter the following code
Public class Helloworld
{
}
Click on Quick save Saves the Apex Code, making it available to be
executedit makes us to add and modify code.
Save
savers the Apex Code, but that classes the class editor and returns to
the Apex classes list.
*Add the static method to the above class Now Apex class become.
Publish class Helloworld {
public static void sayyou( ) {
System.debug ( 'you' );
}
*Now add a instance method. Now the Apex class became
public class Helloworld
{// class creation
Public static void sayyou () { //adding static method to the class
}
Public void sayMe ( ) { //adding instance method to system debug (Me '); the
class

-2

We have created the "Helloworld" class follow these steps to call its methods .
1. Execute the following code in the Developer console to call the Helloworld
class's static method.
***

To call a static method, we don't have to create an instance of the class.


Helloworld say you ();

34

(
Open Raw log, then "You" appears in the USER-DEBUG log.
2. Now execute the following code in Developer's Console to call the
Helloworld classes instance method.
To call an instance method, we first have to create an instance of the
Helloworld class.
Helloworld h= new Helloworld ( );
h.say Me ( );
Open Raw log , then "Me" appears in the USER-DEBUG log.

2
We can also create new Apex classes directly in the Developer Console.
1. Open the Developer Console.
2. Click the repository tab.
3. The setup Entity type panel lists the different items. We can view and edit in
the Developer Console.
4. Click on classes, and then click "New" button .
5. Enter "Message" for the name of the new class and click "ok" bottom.
6.
Add the following static method to the new class public static string
hellowMessage () {
return ( 'welcome to capital info solutions '):
}
7. Click on "Save" button.
.

1. Public class AccountCreation {


Public Account createAccount(String name){
Account a= new Account();
a.Name = name;
insert a;
return a;
35

(
}
}
Go to the Developer console, and execute the following code
Account Creation ac = new Account Creation();
creating an instance for the above class.
ac.CreateAccount('Osmania University');
calling a method
system.debug(ac);
check the account is created or not in the USER-DEBUG Log.
2. The following program is used fetch the Account Name from the account
records by passing phone number.
Public class Fetch_Account_ Name_ From_Phone{
Public set<string> Fetch_ ACC_ Name(String P) {
set <string> s1= new Set<string>();
List<Account> acc= [select id, Name from Account where phone];
for (Account a:acc)
{
String s=a.name;
s1.add(s); }
System.debug('xxxxxxxxx' +s1);
return s1;
}
}
Go to the Developer Console, and execute the following code.
FetchAccountName_ From_Phone ft= new FetchAccountName_from_Phone ();
ft.FetchAccName ('9052');
In the User-Debug Log all the accounts will come that has the phone number is
9052.
36

(
.

Public Class AccountCreation


{
Public List<Account> CreateAccount(String s, String p){
List<Account> a = new List<Account>();
for(Account acc:a)
{
acc.Name=s;
acc.phone=p;
insert all;
}
return a;
}
}
Go to Developer Console and execute the following code:
AccountCreation ac= new AccountCreation();
Ac.CreateAccount(Osmania University, 9052);

4 "6 -

Public Class HelloWorld{


Public static void Method1(){
System.debug('Capital Info Solutions');
}
Public void method2(){
37

(
System.debug('Osmaina University');
}
}

Go to the Developer Console and execute the following


HelloWorld hw= new HelloWorld();
Hw. Method1(); // It gives Error. For static methods we cannot have instant for the class.
HelloWorld.Method1();
Hw.Method2();
+ #

- 1"

-+

.1 @

Public class FetchAccountNameFromPhone


{
Public Set<String> FetchAccName(String p)
{
Set<String> s1= new Set<String>();
List<Account> acc=[Select id, Name From Account where phone];
for(Account a:acc)
{
String s =a.name;
s1.add(s);
}
System.debug('xxxxxxxxx' +s1);
return s1;
}
}
#

(:

"

Public class Acc_Con_Opty_Creation


38

(
{
Public Account CreateAccount(String n)
{
Account a = new Account();
a.Name=n;
insert a;
Contact c = new Contact();
c.LastName='Satti Reddy';
c.AccountId=a.id;
insert c;
Opportunity opp= new Opportunity();
opp.Name='Test Opportunity';
Date d= Date.newinstance(2012, 2, 17);
opp.CloseDate=d;
opp.StageName='Closed Lost';
opp.Accountid=a.id;
insert opp;
return a;
}
}
Go to the Developer Console and execute the following:
Acc_Con_Opty_Creation acoc= new Acc_Con_Opty_Creation();
Acc. CreateAccount(capital info Solutions);
/ ##

2
* Apex can be in invoked through the use of triggers.
* A Trigger are functional actions which gets fired on particular events.
39

(
That is Data can flow into Data.com at any time. Triggers will happen before
records entering into the database and while going out of the database.
&

Each event is the firing Point.

*onclick
*Submit
* A Trigger is Apex code that execute before or after the following types of
operations.
* Insert
* Update
*Delete
* Undelete
We can have a trigger run before an Object's records are inserted into the
database, after records have been deleted, or even after a record is restored from
the Recycle BIN.
* Triggers can be divided into two types.
Before triggers can be used to update or validate record values before they
are saved to the DataBase.
After triggers can be used to access field values that are set by the database,
and to affect changes in other records.
+

2 Each event is the firing point events are formation of

Before Insert

Before Update

Before delete

After insert

After Update

After Delete

:-

After Undelete

*Before insert Trigger are used mainly for validation rules.


Before insert Data screening
Data Insert
*After insert triggers are used mainly for WorkFlow Rules.

/ ##

"

To define a Trigger, use the following syntax


Trigger TriggerName on ObjectName(trigger-events) {
40

(
Code Block;
}
Where trigger-events can be comma- separated list of one or more of the
following events.
Before Insert
After insert
After Update
Before Update
Before delete
After Delete
After Undelete
2 The following code defines a trigger for the before insert and before update
events on the Account object.
Trigger Account _Trigger on Account (before insert, Before Update) {
---------}
/ ##
+
1 2 All triggers define implicit variables that allow
developers to access run time context. These variables are contained in the
system.Trigger class.
Trigger.New:- Trigger.new returns a list of
the new records of the Sobjects which we are going to insert into the
database.
This SObject list is only available in insert and Update triggers,
and the records can only be modified in before triggers.
b.
Trigger.old:- Trigger.old returns a list of old
records of the Sobjects from the database.
:- This Sobject list is only available in update and delete triggers.
c.
Trigger.NewMap:- Trigger newMap returns
a map of IDs to the new records of the Sobjects.
:- This map is only available in before update, After insert, and after
update triggers.
d.
Trigger.OldMap:- Trigger.OldMap returns a
map of ids to the old records of the SObjects.
a.

41

(
e.
f.
g.
h.
i.
j.

Trigger.isAfter context
Trigger.isAfter:variable return true if this trigger was fired after all the records we saved.
Trigger.isBefore:- This context variable
returns true if trigger was fired before any record was saved.
Trigger.is Insert:- This context variable
returns true if the trigger was fired due to an insert operation.
Trigger .is Update:- This context variable
returns true if the trigger was fired due to an update operation.
Trigger .is Delete : - This context variable returns true if trigger was fired
due to a
delete operation.
Trigger is Undelete:- This context variable returns true if trigger was fired
ofte a record
is recovered from the recycle bin

:- Trigger are object specific

&

:-

Trigger.new and trigger.old cannot be used in apex DML operations.


We can use on object to change its own field values using trigger.new, but only in
before triggers. In all after triggers, triggers.new is not saved so runtime exception
is thrown.
Trigger.old is always read-only.
We can not delete trigger.new.
Before insert ==> Trigger.new allowed.
In after insert triggers ==> Trigger.new not allowed.
Trigger.new is not available in before delete triggers.
Trigger.old is not available after undelete triggers.
, 4 / ##

:-

All triggers are bulk triggers by default and can process multiple records at a time.
We should always plan on processing, more than one record at a time.
When we are uploading bulk records using the data loader, then also triggers will
fire for all records at a time.

/ ##

/ ##
Create Top X Designation custom object which is related list to Opportunity (Look up
Relationship). In the Top X Designation object, create the fields 1. Type (Picklist), 2.
Document Attached (Checkbox)
42

(
Create one field Handoff Attached with picklist type with values are Yes, No on
Opportunity Object.
< # If Type (Top X Designation) = "Contract Flow Down/Handoff", and "Document
Attached = True then "Handoff Attached" = True, otherwise false.
trigger UpdateHandoffAttached on Top_X_Designation__c(after insert, after update,
after delete) {
List<Opportunity> listoppUpdate=new List<Opportunity>();
List<Opportunity> listopp=new List<Opportunity>();
Set<Id> setOppId=new Set<Id>();
Set<Id> setOppDelete=new Set<Id>();
map<id,id> mapDocAttchTrue = new map<id,id>();
map<id,id> mapDocAttchFalse = new map<id,id>();
map<id,id> mapDelete = new map<id,id>();
if(Trigger.isInsert || Trigger.isUpdate){
for(Top_X_Designation__c ada:Trigger.New){
if(ada.Document_Attached__c==True && ada.Item_Type__c=='Contract Flow
Down/Handoff'){
mapDocAttchTrue.put(ada.Opportunity,ada.id);
setOppId.add(ada.Opportunity);
}
else
mapDocAttchFalse.put(ada.Opportunity,ada.id);
setOppId.add(ada.Opportunity);
}
}
if(Trigger.isDelete){
for(Top_X_Designation__c ada:Trigger.old){
mapDelete.put(ada.Opportunity,ada.id);
43

(
setOppId.add(ada.Opportunity);
setOppDelete.add(ada.Opportunity);
}
}
listopp = [select id,Handoff_Attached__c from Opportunity where id in: setOppId];
if(listopp.size()>0 && listopp !=null){
for(Opportunity opp:listopp){
if(mapDocAttchTrue.containskey(opp.id)){
opp.Handoff_Attached__c='Yes';
}
if(mapDocAttchFalse.containskey(opp.id)){
opp.Handoff_Attached__c='No';
}
if(setOppDelete.contains(opp.id)){
opp.Handoff_Attached__c='';
}
listoppUpdate.add(opp);
}
}
if(listoppUpdate.size()>0 && listoppUpdate!=null){
update listoppUpdate;
system.debug('LLLLLLLLLLLLLLL'+listoppUpdate);
}
}
/ ##
The following Trigger will fires when we try to create the account with same name i.e
Preventing the users to create Duplicate Accounts

44

(
trigger AccountDuplicateTrigger on Account (before insert, before update)
{
for(Account a:Trigger.new)
{
List<Account> acc=[Select id from Account where Name=:a.Name and Rating=:a.Rating
];
if(acc.size()>0)
{
acc.Name.addError('You Cannot Create the Duplicate Account');
}
}
}
/ ##

The following trigger updates the field called Hello by the value Worldwhenever we
are creating an account or updating an account record. Create the field called Hello on
the Account Object (Data Type = Text)
trigger HelloWorld on Account (before insert, before update)
{
List<Account> accs = Trigger.new;
MyHelloWorld my= new MyHelloWorld(); //creating instance of apex class
my.addHelloWorld(accs);
// calling method from the apex class
}
public class MyHelloWorld
{
public void addHelloWorld(List<Account> accs)
{
for (Account a:accs)
{
if (a.Hello__c != 'World')
{
a.Hello__c = 'World';
}
}
}
}

/ ##

45

(
The following trigger describes about when the leads are inserted into the data base it
would add Doctor prefixed for all lead names. This is applicable for both inserting and
updating the lead records.
trigger PrefixDoctor on Lead (before insert,before update)
{
List<Lead> leadList = trigger.new;
for(Lead l: leadList)
{
l.firstname = 'Dr.'+ l.firstname;
}
}

/ ##

The following trigger adds the Opportunity Owner into the sales team automatically
whenever the Opportunity is created.
trigger OppTeam on Opportunity (after insert) {
List<OpportunityShare> sharesToCreate = new List<OpportunityShare>();
List<OpportunityTeamMember> oppteam = new List<OpportunityTeamMember
> ();
OpportunityShare oshare = new OpportunityShare();
oshare.OpportunityAccessLevel = 'Edit';
oshare.OpportunityId = trigger.new[0].Id;
oshare.UserOrGroupId = trigger.new[0].createdbyid;
sharesToCreate.add(oshare);
OpportunityTeamMember ot = new OpportunityTeamMember();
ot.OpportunityId = trigger.new[0].Id;
ot.UserId = trigger.new[0].OwnerId;
ot.TeamMemberRole = 'Account Manager';
oppteam.add(ot);

if(Oppteam!=null && Oppteam.size()>0)


{
insert Oppteam;
}
if(sharesToCreate!=null && sharesToCreate.size()>0)
{
list<Database.SaveResult> sr = Database.insert(sharesToCreate,false);

46

(
}
}
/ ##
Create the object called Books and create field Price(data type is Currrency) under
this object.
Whenever we enter some amount of money in the Price field and once we click on save
button, the value we entered in the Price field is 10% less than the actual price. This is
applicable for while both inserting and updating records.
trigger DiscountTrigger on Book__c (before insert, before update) {
List<Book__c> books = Trigger.new;
PriceDiscount.applyDiscount(books);
}
public class PriceDiscount {
public static void applyDiscount(List<Book__c> books) {
for (Book__c b :books){
b.Price__c *= 0.9;
}
}
}

/ ##

The following trigger will prevent the users from deleting the Accounts. This is because
System Administrator has all the permissions, we cannot change the permissions.
trigger AccountDelete on Account (before delete) {
for(Account Acc:trigger.old)
{
acc.adderror('You Cannot Delete the Account Record');
}
}

/ ##
Create Custom field called Number of Locations on the Account Object (Data
Type=Number)

47

(
The following trigger creates the number of contacts which are equal to the number
which we will enter in the Number of Locations field on the Account Object
trigger ContactsCreation on Account (after insert) {
list<contact> listContact = new list<contact>();
map<id,decimal> mapAcc=new map<id,decimal>();
for(Account acc:trigger.new){
mapAcc.put(acc.id,acc.Number_of_Locations__c);
}
if(mapAcc.size()>0 && mapAcc!=null){
for(Id accId:mapAcc.keyset()){
for(integer i=0;i<mapAcc.get(accId);i++){
contact newContact=new contact();
newContact.accountid=accId;
newContact.lastname='contact'+i;
listContact.add(newContact);
}
}
}
if(listContact.size()>0 && listContact!=null)
insert listContact;
}

/ ##

48

(
Create the object called Customer Project and create Status field under this object with
picklist data type (Values=Active, Inactive). Create the relationship between this custom
object and Opportunity so that Customer Project is related list to the Opportunity.
Create

field on Opportunity object (Data Type=Checkbox)

The logic is when we create Customer Project for an Opportunity with the Status=Active,
then
+
.
! checkbox on the Opportunity detail page is automatically
checked.
trigger UpdateCPActivenOnOppty on Customer_Project__c (after insert)
{
List<Opportunity> opps=new List<Opportunity>();
for(Customer_Project__c
cp:Trigger.New){
if(cp.Status__c=='Active'){
Opportunity opp= new Opportunity(id=cp.Opportunity__c);
opp.Active_Customer_Project__c = True;
opps.add(opp);
}
}
update opps;
}
/ ##
'
5
We have Stakeholder object that is related list to Opportunity and Contact.
On Contact detail page, we have NPS ID field on the Contact detail page that is look up
to the Voice of NPS object (Customer Object). The following code will get the NPS ID
field value from the Contact detail page in the Stackholders page which we can able to
clickable.
Create NPS Id 1 field on the stackholder object which is the look up to the Voice of NPS
object (Customer Object)
&
we can also get the NPS Id 1 on the Stakeholders page using the formula field but
will not able to clickable.
- ?

-@

triggerUpdateNPSid on Stakeholder__c (before insert, before update){


List<id>ConList=new List<id>();
for(Stakeholder__csh:Trigger.New){
49

(
ConList.add(sh.Contact_Name__c);
}
List<Contact>lc=[Select NPS_Id__c From Contact Where id IN : ConList];
for(Stakeholder__csh:Trigger.New){
sh.NPS_Id1__c=lc[0].NPS_Id__c;
}
}
- ?, 4

-@

trigger UpdateNPSid on Stakeholder__c (before insert, before update){


List<id> ConList=new List<id>();
map<id,id>map_NPS_Cont = new map<id,id>();
for(Stakeholder__c sh:Trigger.New)
{
if(sh.Contact_Name__c!=null)
ConList.add(sh.Contact_Name__c);
}
List<Contact> lc=[Select Id,NPS_Id__c From Contact Where id IN : ConList];
if(lc!=null && lc.size()>0)
{
for(Contact c:lc){
If(c.NPS_Id__c!=null){
map_NPS_Cont.put(c.Id,c.NPS_Id__c);
}
}
for(Stakeholder__c sh:Trigger.New){
if(sh.Contact_Name__c!=null)
sh.NPS_Id1__c = map_NPS_Cont.get(sh.Contact_Name__c);
else
sh.NPS_Id1__c = null;
}
}
}

/ ##

50

(
Create Sales Rep field with data type (Text) on the Account Object.
When we create the Account record, the Account Owner will be automatically added to
Sales Rep field. When we update the Account owner of the record, then also the Sales
Rep will be automatically updated.
triggerUpdateSalesRep on Account (Before insert,Before Update){
Set<Id>setAccOwner=new Set<Id>();
for(Account Acc: trigger.new)
{
setAccOwner.add(Acc.OwnerId);
}
Map<Id,User>User_map = new Map<Id,User>([select Name from User where id
in:setAccOwner]);
for(Account Acc: Trigger.new)
{
User usr=User_map.get(Acc.OwnerId);
Acc.sales_Rep1__c=usr.Name;
}
}
/ ##
Create the field called Contact Relationship checkbox on the Contact Object and Create
the object called Contact Relationship which is related list to the Contacts.(Look Up
Relationship).
Now logic is when we create contact by checking
Contact Relationship will be created automatically for that contact.

checkbox, then

trigger CreateCRonContactCreation on Contact (after insert) {


if(trigger.isAfter)
{
if(trigger.isInsert)
{
ContactMasterHandler ConIns = New ContactMasterHandler();
ConIns.createContactRelationshipByContact(trigger.New);
51

(
}
}
}

Public Class ContactMasterHandler {


public void createContactRelationshipByContact(list<Contact> List_Contacts)
{
list<Contact_Relationship__c> ConList= new list<Contact_Relationship__c>();
for(Contact newconts:List_Contacts)
{
if(newconts.Contact_Relationship__c== true)
{
Contact_Relationship__c CR = new Contact_Relationship__c();
CR.Name=newconts.Lastname;
CR.Contact__c= newconts.id;
ConList.add(CR);
}
}
insert ConList;
}
/ ##

When we change the Owner of the Contact Relationship, then the Owner name will be
automatically populated in the Contact Relationship Name field.
/ ##
trigger ContactRelationshipMasterTrigger on Contact_Relationship__c(before update)
{
if(trigger.isBefore)
{
if(trigger.isUpdate)
{
//call the handler for the before update trigger event
updateCROwnerName ConRelUpd = New updateCROwnerName();
ConRelUpd.updateContactRelationshipNameByOwner(trigger.New);
}
}
}

52

(
Public Class updateCROwnerName{
public void updateContactRelationshipNameByOwner(list<Contact_Relationship__c> co
nt_Rel)
{
map<Id,Id> map_Id_Own = new map<id,id>();
map<Id,string>
map_id_Name = new map<id,string>();
set<id> Idset = new set<id>();
for(Contact_Relationship__c List_recs:cont_Rel)
{
Idset.add(List_recs.Ownerid);
}
list<user> u=[select id,Name from user where id in:Idset];
for(user list_users:u)
{
map_id_Name.put(list_users.Id,list_users.Name);
}
if(u!=null && u.size()>0)
{
for(Contact_Relationship__c List_recs:cont_Rel)
{
if (List_recs.Ownerid!=null)
{
List_recs.Name = map_id_Name.get(List_recs.Ownerid);
}
}
}
}
}
/ ##
Create the field called Contact Relationship checkbox on the Contact Object and Create
the object called Contact Relationship which is related list to the Contacts.(Look Up
Relationship).
Trigger Scenario 12 logic will says that when we create contact by checking Contact
Relationship checkbox, then Contact Relationship will be created automatically for that
contact.
No this logic will for when we delete the Contact, Then Contact Relationship will be
deleted automatically
trigger DeleteCRonContactDeletion on Contact (before delete) {
if(trigger.isBefore)
{
if(trigger.isDelete)
53

(
{
for(Contact c:Trigger.old)
{
Contact_relationship__c CR=new Contact_relationship__c();
CR=[Select Id from Contact_Relationship__c where Contact__c IN:GlobalUtility.getUni
queIds(Trigger.Old)];
delete CR;
}
}
}
}
; 1 E

"

public static set<Id> getUniqueIds(list<SObject> sobs)


{
set<Id> Ids = new set<Id>();
for (SObject sob : sobs) {
Ids.add(sob.Id);
}
return Ids;
T
/ ##

Create the field called Contact Relationship checkbox on the Contact Object and Create
the object called Contact Relationship which is related list to the Contacts.(Look Up
Relationship).
Trigger Scenario 14 will says that when we delete the Contact, Then Contact
Relationship will be deleted automatically
Now the Logic is when we undelete the Contact, then Contact Relationship will be
undeleted automatically
/ ##
trigger UnDeleteCRonContactUnDeletion on Contact (After Undelete) {
if(trigger.isUndelete)
{
54

(
//call the handler for the after undelete trigger event
ContactMasterHandler_Undelete ConIns = New ContactMasterHandler_Undelete(
);
ConIns.undeleteContactRelationshipsByContact(Trigger.New);
}
}

Public Class ContactMasterHandler_Undelete{


public void undeleteContactRelationshipsByContact(list<Contact> List_Contacts)
{
set<Id> ContactIds = New set<Id>();
if(List_Contacts!=null && List_Contacts.size()>0)
{
list<Contact_Relationship__c> List_ConRels= new list<Contact_Relationship__c>(
);
List_ConRels= [select id from Contact_Relationship__c where isDeleted=TRUE and Co
ntact__c in: GlobalUtility.getUniqueIds(List_Contacts)];
undelete List_ConRels;
}
}
}
/ ##
Create field called Count of Contacts on Account Object. When we add the Contacts
for that Account then count will populate in the field on Account details page. When we
delete the Contacts for that Account, then Count will update automatically.
&
The above logic will be applicable when we have look up relationship. But When
we have the Master Detail relationship, then we can create Rollup Summary field to get
the count of child records using Count function.
trigger CountOfContacts on Contact (after insert,after delete) {
set<id> accid=new set<id>();
list<contact> contactlist =new list<contact>();
list<contact> listcon=new list<contact>();
list<account> acclist=new list<account>();
list<account> listAcc=new list<account>();
55

(
map<id,integer> mapCount=new map<id,integer>();
if(trigger.isinsert){
for(contact con:trigger.new){
accid.add(con.accountid);
}
}
if(trigger.isdelete){
for(contact con:trigger.old){
accid.add(con.accountid);
}
}
acclist=[select id,name from account where id in:accid];
contactlist = [select id,name,accountid from contact where accountid in:accid];
for(account acc:acclist){
listcon.clear();
for(contact c:contactlist){
if(c.accountid==acc.id){
listcon.add(c);
mapCount.put(c.accountid,listcon.size());
}
}
}

if(acclist.size()>0){
for(Account a:acclist){
if(mapCount.get(a.id)==null)
a.Count_Of_Contacts__c=0;
56

(
else
a.Count_Of_Contacts__c=mapCount.get(a.id);
listAcc.add(a);
}
}
if(listAcc.size()>0)
update listAcc;

}
/ ##

Create the object called Customer and create the Master-Detail Relationship on
Customer object so that Customer will be the related list to Account record. Create the
field called Account Manager on Customer object which is lookup to the user object.
Now Logic is when we create Customer record for account record, then the user in
Account Manager field will be automatically added to Account Team of that associated
account.
Code:
trigger InsertAccountTeam on Customer__c (after insert) {
List<AccountTeamMember> atm_list=new List<AccountTeamMember>();
AccountTeamMember atm = new AccountTeamMember();
List<AccountShare> newShare = new List<AccountShare>();
if(trigger.isInsert)
{
For(Customer__c c:Trigger.new)
{
if(c.Account_Manager__c!=null){
atm = new AccountTeamMember();
atm.accountid=c.Account__c;
atm.teamMemberRole='Account Manager';
57

(
atm.UserId=c.Account_Manager__c;
AccountShare shares = new AccountShare();
shares.AccountId=c.Account__c;
shares.UserOrGroupId = c.Account_Manager__c;
shares.AccountAccessLevel='Read/Write';
shares.OpportunityAccessLevel = 'Read Only';
shares.CaseAccessLevel='Read Only';
newShare.add(shares);
atm_list.add(atm);
}
}
if(atm_list!=null)
insert atm_list;
if(newShare!=null && newShare.size()>0)
List<Database.saveresult> sr=Database.insert(newShare,false);
}
}
/ ##
The above trigger(Trigger Scenario 17) Logic is when we create Customer record for
account record, then the user in Account Manager field will be automatically added to
Account Team of that associated account.
Now the following trigger logic is when we update the user in the Account Manager,
the Account team will be updated automatically.
Code:
trigger UpdateAccountTeam on Customer__c (before update) {
List<AccountTeamMember> atm_list=new List<AccountTeamMember>();
AccountTeamMember atm = new AccountTeamMember();
List<AccountShare> newShare = new List<AccountShare>();

58

(
if(trigger.isupdate)
{
if(trigger.isbefore)
{
Set<Id> setAccIds1=new Set<Id>();
Set<Id> setDelATM=new Set<Id>();
Map<id,Set<Id>> mapAccMgrs=new Map<id,Set<Id>>();
for(Customer__c c:Trigger.new)
{
if(trigger.oldmap.get(c.Id).Account_Manager__c!=c.Account_Manager__c
&&c.Account_Manager__c!=null )
{
setAccIds1.add(c.Account__c);
}
}
List<Customer__c> listPLAccMgrs=[select id,Account_Manager__c,Account__c
from
Customer__c
where
Account__c
in:setAccIds1
and
id
not
in:trigger.newmap.keyset()];
if(listPLAccMgrs!=null && listPLAccMgrs.size()>0)
{
for(Customer__c c:listPLAccMgrs)
{
Set<Id> idMgrs=mapAccMgrs.get(c.Account__c);
if(null==idMgrs){
idMgrs=new set<Id>();
mapAccMgrs.put(c.Account__c,idMgrs);
}
idMgrs.add(c.Account_Manager__c);

59

(
}
}
Map<id,List<AccountTeamMember>> mapStdAccTeam=new
Map<id,List<AccountTeamMember>>();
List<AccountTeamMember> listStdAcc Team=[select id,UserId,AccountId from
AccountTeamMember where AccountId in:setAccIds1 ];
if(listStdAccTeam!=null && listStdAccTeam.size()>0){
for(AccountTeamMember recAccTeam :listStdAccTeam)
{
List<AccountTeamMember>
listStdAccTeamMap=mapStdAccTeam.get(recAccTeam.AccountId);
if(null==listStdAccTeamMap){
listStdAccTeamMap=new List<AccountTeamMember>();
mapStdAccTeam.put(recAccTeam.AccountId,listStdAccTeamMap);
}
listStdAccTeamMap.add(recAccTeam);
}
}
system.debug('***********'+mapAccMgrs);
for(Customer__c c:Trigger.new)
{
if(trigger.oldmap.get(c.Id).Account_Manager__c!=c.Account_Manager__c
&&c.Account_Manager__c!=null )
{
List<AccountTeamMember>
listAccTeam=mapStdAccTeam.get(c.Account__c);
Set<Id> idMgrs=mapAccMgrs.get(c.Account__c);

if(listAccTeam!=null && listAccTeam.size()>0 )

60

(
{
if(idMgrs!=null
&&
idMgrs.size()>0
!(idMgrs.Contains(trigger.oldmap.get(c.Id).Account_Manager__c)))

&&

{
for(AccountTeamMember recATM:listAccTeam)
{
if(recATM.UserId==trigger.oldmap.get(c.Id).Account_Manager__c)
setDelATM.add(recATM.Id);
}
}
else if(idMgrs==null)
{
for(AccountTeamMember recATM:listAccTeam)
setDelATM.add(recATM.Id);
}
}
atm
=
AccountTeamMember(accountid=c.Account__c,teamMemberRole='Account
Manager',UserId=c.Account_Manager__c);

new

AccountShare shares = new AccountShare();


shares.AccountId=c.Account__c;
shares.UserOrGroupId = c.Account_Manager__c;
shares.AccountAccessLevel='Edit';
shares.OpportunityAccessLevel = 'None';
newShare.add(shares);
atm_list.add(atm);
}
}

61

(
List<AccountTeamMember> listDelATM=[select id from AccountTeamMember
where id in:setDelATM];
if(listDelATM!=null && listDelATM.size()>0 )
delete listDelATM;
if(atm_list!=null)
insert atm_list;
if(newShare!=null && newShare.size()>0)
List<Database.saveresult> sr=Database.insert(newShare,false);
}
}
/ ##
The trigger scenario 17 Logic is when we create Customer record for account record,
then the user in Account Manager field will be automatically added to Account Team of
that associated account.
Now the following trigger gives the logic about when we delete the Customer of that
account, then the user will deleted automatically from the Account Team of that account.
trigger DeleteAccountTeam on Customer__c (before delete) {
List<AccountTeamMember> atm_list=new List<AccountTeamMember>();
AccountTeamMember atm = new AccountTeamMember();
List<AccountShare> newShare = new List<AccountShare>();
if(trigger.isdelete)
{

set<id> setAccids = new set<id>();


Set<Id> setDelATM=new Set<Id>();
Map<id,Set<Id>> mapAccMgrs=new Map<id,Set<Id>>();
for(Customer__c c:Trigger.old)
{
setAccids.add(c.Account__c);
62

(
}
List<Customer__c> listPLAccMgrs=[select id,Account_Manager__c,Account__c from
Customer__c where Account__c in:setAccids and id not in:trigger.oldmap.keyset()];
if(listPLAccMgrs!=null && listPLAccMgrs.size()>0)
{
for(Customer__c c:listPLAccMgrs)
{
Set<Id> idMgrs=mapAccMgrs.get(c.Account__c);
if(null==idMgrs){
idMgrs=new set<Id>();
mapAccMgrs.put(c.Account__c,idMgrs);
}
idMgrs.add(c.Account_Manager__c);
}
}
Map<id,List<AccountTeamMember>> mapStdAccTeam=new
Map<id,List<AccountTeamMember>>();
List<AccountTeamMember> listStdAccTeam=[select id,UserId,AccountId from
AccountTeamMember where AccountId in:setAccids];
if(listStdAccTeam!=null && listStdAccTeam.size()>0){
for(AccountTeamMember recAccTeam :listStdAccTeam)
{
List<AccountTeamMember>
listStdAccTeamMap=mapStdAccTeam.get(recAccTeam.AccountId);
if(null==listStdAccTeamMap){
listStdAccTeamMap=new List<AccountTeamMember>();
mapStdAccTeam.put(recAccTeam.AccountId,listStdAccTeamMap);
}
listStdAccTeamMap.add(recAccTeam);
63

(
}
}
for(Customer__c c:Trigger.old)
{
List<AccountTeamMember>
listAccTeam=mapStdAccTeam.get(c.Account__c);
Set<Id> idMgrs=mapAccMgrs.get(c.Account__c);
if(listAccTeam!=null && listAccTeam.size()>0 )
{
if(idMgrs!=null
&&
idMgrs.size()>0
!(idMgrs.Contains(trigger.oldmap.get(c.Id).Account_Manager__c)))

&&

{
for(AccountTeamMember recATM:listAccTeam)
{
if(recATM.UserId==trigger.oldmap.get(c.Id).Account_Manager__c)
setDelATM.add(recATM.Id);
}
}
else if(idMgrs==null)
{
for(AccountTeamMember recATM:listAccTeam)
setDelATM.add(recATM.Id);
}
}
}

List<AccountTeamMember> listDelATM=[select id from AccountTeamMember


where id in:setDelATM];

64

(
if(listDelATM!=null && listDelATM.size()>0 )
delete listDelATM;
}
}
/ ##

'

When we create the Opportunity with the Probability=20, then the opportunity owner will
be automatically added to Account Team of the associated account for that Opportunity.
trigger UpdateATMwithOwneronOptyCreate on Opportunity (after insert,after update) {
List<AccountShare> list_share= new List<AccountShare>();
List<AccountTeamMember> list_atm=new List<AccountTeamMember>();
for(Opportunity opp:Trigger.New)
{
if(opp.Probability==20)
{
AccountTeamMember atm=new AccountTeamMember();
atm.accountid=opp.accountid;
atm.teamMemberRole='Account Manager';
atm.UserId=opp.Ownerid;
AccountShare share = new AccountShare();
share.AccountId=opp.Accountid;
share.UserOrGroupId = opp.OwnerId;
share.AccountAccessLevel='Read/Write';
share.OpportunityAccessLevel = 'Read Only';
share.CaseAccessLevel='Read Only';
list_atm.add(atm);
list_share.add(share);
}
}
if(list_atm!=null)
insert list_atm;
if(list_share!=null && list_share.size()>0)
List<Database.saveresult> sr=Database.insert(list_share,false);

/ .

#"

65

(
In the above triggers

OpportunityTeamMember is backend name of Sales Team


For creation of Account Team we need to create Account Share which will be
there at the backend
For creation of Sales team, we need to create Opportunity Share which will be
there at the backend

&
For more clarity, go to the Data Loader and click on the Export operation
and click on the select Show all Salesforce Objects checkbox, then we can able to
see Account Share and Opportunity Share.
: - :
:- When we save a record with an insert update, or upsert statement
salesforce performs the events in order because when the event happens, Order of
Execution is very important because they are multiple things tield to a single event and
when the event gets fired we need to know which processes is running first and which
processes is running last.
The order of execution is in the following order.
1.
2.
3.
4.
5.
6.
7.
8.
9.

Executes all before triggers.


System validations are performed.
Custom validations are performed.
Saves the record but does not commit
Executes all after triggers.
Executes assignment rules
Executes auto response rules
Executes workflow rules
If the record was updated with workflow field updates, fires before and after
triggers are more time in addition to standard validations. Custom validation rules
are not run again.
10. Executes escalation rules
11. Commits to the database.

; +

< . :Because apex runs in a multitenant environment. The apex runtime engine strictly
enforce a number of limits its that runaway apex. These limits are called Governor
limits.
If some apex code ever exceeds a limit, the associated governor issues a runtime
exception that can not be handled.
Polymorphic Application

66

(
Runtime
Engine

Tenant-Specific Metadata common metadata.

Shared Database
Metadata The data which is .xml format.

If we create anything like fields objects then these data will be stored as metadata
(.xml format) into the database.
:

Total number of SOQL queries issued 100


Total number of records retrieved by SOQL Queries 50,000
Total number of SOSL queries issued 20
Total number of records retrieved by single SOSL query 200
Total number of DML statements issued 150
Total heap size 6 MB
Total number of methods with the future annotation allowed per apex 10
Total number of classes that can be scheduled concurrently 25
2
An apex annotation modifies the way a method or class is used similar to annotations in
Java

Annotations are defined with an initial @ symbol, followed by the appropriate


keyword.
To add an annotation to a method, specify it immediately before the method or
class definition.
67

(
2
Public class classname @ future
Public static void methodname (String Name)

Apex supports the following annotations

1.
2.
3.
4.
5.

@ Deprecated
@ Future
@ Is test
@ Read-only
@ Remote action

Use the deprecated annotation to identify methods classes exceptions enums,


interfaces or variables that can no longer be referenced in subsequent releases of
the managed package in which they reside.
This is useful when we are refactoring code (clearing the code) in managed
packages.
The following code shows a deprecated method. The same syntax can be used to
deprecate classes, exceptions, nums, interfaces or variables

@depreacated
Public void methodname (string a) {}
:- Unmanaged packages cannot contain code that uses the deprecated keyword.

&

We can not remove the deprecated annotation to undepricated something in apex


after we have released a package version where that item in apex is deprecated.

& :- Unmanaged package editable by developer and installer cannot be upgraded. In


managed package certain components are locked and changes are not allowed.
:

Use the future annotation to identify methods that are executed asynchronously.
When we specify future, method executes when salesforce had available
resources.
Methods with the future annotation must be static methods and can only return a
void type
To make a method in a class execute asynchronously define the method with the
future annotation.

68

(
2
Public class classname { @future
Static void methodname (String a, integer I) { // Apex code
:-

&

Methods with the future annotation cannot take subjects or objects as arguments.
Methods with the future annotation cannot be used in visual force controllers in
either getmethodname or setmethodname methods, not in the constructor.
The parameters specified must be primitive datatypes, arrays of primitive
datatypes, or collection of primitive datatypes.
2

Use the istest annotation to define classes or individual methods that only contain
code used for testing application. The istest annotation is similar to creating
methods declared a testmethod

&
2 Classes defined with the istest annotation don't count against organization limit of
2MB for all apex code individual methods defined with the istest annotation do count
against organization limits.

Classes and methods defined as istest can be either Private or Public classes
defined as istest must be top level classes.

The following is the example of a public test class that contains two test methods.
@istest
Public class Testclassname {static testmethod void methodname 1( )
{
// Apex code
}
Static testmethod void methodname 2 ( )
{
// Apex code
}
69

(
}
/

For Apex code using the IsTest(see All Date= true) Annotation to grant test
classes and individual test methods access to all data in the organization,
including pre-existing data that the test did not create.
Test methods doesn't have access by default to pre-existing data in the
Organization If a test class is defined with the IsTest(See All Data= True)
Annotation, this annotation applies to all its test methods whether the test methods
are defined with the @IsTest annotation or the test Method Keyword.
The following example shows how to define a test class with the
IsTest(seeAllDate=true) annotation all the test methods in this class have access
to all data in the organization.

@isTest( SeeAllDate = true)


Public class classNameTest {
Static testmethod void method1(){
// Apex code
}
}
E -

- #/

Testing is the key to successful long term development and is a critical component of the
development process. And testing is key to the success of application particularly if
application to be deployed to customers.
If we validate that application works as expected, that there are no unexpected behaviors,
then application will run for longtime.
There are two ways of testing an application.

One is through the salesforce user interfaces (testing with a single record)

the other way is to test for build functionality i.e testing with bulk records by
using apex data loader up to 200 records can be passed through code.

Before we can deploy code or package into production, the following must be
true.

70

(
75 % of apex code must be covered by unit tests. All of those tests must
complete successfully.
When deploying to a production organization we need to have 75% of apex
code covered by tests.
&
:- Our focus should not be on the percentage of code that is covered instead we
make sure that every use of application is covered including positive and negative cases,
as well as bulk and single record. This should lead to 75% or more of code being covered
by unit test.
&

2
1. Calls to system debug are not counted as part of apex code coverage.
2. When we deploying apex code from one sandbox to another sandbox then we no
need of any apex code coverage, i.e no need to write any test classes.

When we deploying apex code from one sandbox to production organization then we
need to have at least 75% of code coverage, i.e we need to write test classes with
minimum code coverage of 75%.
8
test.

2 Salesforce.com recommends the following components need to

1. Single records
2. Bulk records
3. Positive scenarios
4. Negative scenarios
5. Restricted user
1. Single Records 2
This includes testing to verify that a single record produces the correct, expected result
2. Bulk Records:Any apex code, whether a triggers, a class or on extension may be used for 1 to 200
records we must test not only the single record case, but the bulk cases as well.
3. Positive scenarios:This type of component testing expect a system to save a record without error.
4. Negative scenarios:71

(
This type of component testing expect a system to give error.
5. Restricted User:Test whether a user with restricted access to the objects used in code sees the expected
behavior, i.e whether they can run the code or receive error messages.
8

"

#%

# :-

Testing each components individually is called unit testing it is a job of developer.


#

#:-

This is the testing which is combination of unit testing.


"

#:-

Once the integration testing complets system testing is the testing after rectifying some of
errors in integration testing.
.

/
% /

/ ##

@isTest
Public Class UpdateHandoffAttachedTest{
Static testMethod void HandoffAttached(){
Account a = new Account();
a.Name='Test Account';
a.phone='8686864286';
a.Rating='Hot';
insert a;
//Create a new Opportunity
Opportunity opp=new Opportunity();
opp.Name='Test Oppty';
Opp.StageName='Prospecting';
Date myDate = Date.newinstance(2012, 2, 17);
opp.CloseDate=myDate;
opp.Accountid=a.id;
insert opp;
//Create Top X Designation with Positive scenario
Top_X_Designation__c t = new Top_X_Designation__c();
t.Type__c='Contract Flow Down/Handoff';
t.Document_Attached__c=True;
t.Opportunity__c=opp.id;
72

(
insert t;
Opportunity o1 = [Select Handoff_Attached__c from Opportunity where id=:opp.id ];
System.assertEquals('Yes',o1.Handoff_Attached__c);
//Update Top X Designation with Negative scenario
t.Type__c='Contract Flow Down/Handoff';
t.Document_Attached__c=False;
t.Opportunity__c=opp.id;
Update t;
Opportunity o2 = [Select Handoff_Attached__c from Opportunity where id=:opp.id ];
System.assertEquals('No',o2.Handoff_Attached__c);
delete t;
Opportunity o3 = [Select Handoff_Attached__c from Opportunity where id=:opp.id ];
System.assertEquals(null,o3.Handoff_Attached__c);
}
}
% /

/ ##

@isTest
public class DuplicateAccountTestClass {
public static testMethod void testAccountDuplicateTrigger() {
String addError;
Account a1= new Account(Name='Test Account');
insert a1;
Account a2= new Account(Name='Test Account');
insert a2;
System.assertequals('You Cannot Create the Duplicate Account', addError);
try {
insert a2;
}
catch (Exception e) {
System.debug('We want to see this. This means the trigger is working.');
}
}
}
Q% /

/ ##

@isTest
private class HelloWorldTestClass {
static testMethod void validateHelloWorld() {
Account a = new Account(name='T1 Account');
// Insert account
insert a;
// Retrieve account
a = [SELECT hello__c FROM account WHERE Id =:a.id];
73

(
// Test that HelloWorld program correctly added the value
// "World" to the Hello field
System.assertEquals('World', a.hello__c);
}
}
% /

/ ##

@isTest
Public Class PrefixDoctorTest{
Public static testMethod void PreDoctor(){
Lead l=new Lead();
l.LastName='Anil';
l.company='Wipro';
l.Status='Open - Not Contacted';
insert l;//inserting a single record
}
}
F% /

/ ##

@isTest
Public Class OppTeamTest{
static testMethod void CreateOppOwnerintoSalesTeam(){
//inserting an opportunity record
Opportunity opp= new Opportunity();
opp.Name='Test Opportunity';
Date myDate = Date.newinstance(2012,6,24);
opp.CloseDate=myDate;
opp.StageName='Prospecting';
insert opp;
Opportunity opty=[Select OwnerId from Opportunity where id=:opp.id];
OpportunityTeamMember otm=[Select UserId from OpportunityTeamMember where Op
portunityId=:opp.id];
System.assertEquals(opty.OwnerId,otm.UserId);
}
}

% /

/ ##

@isTest
Public Class DiscountTriggerTest{
74

(
Public static testMethod void Discount(){
Book__c b = new Book__c();
b.Name='Test';
b.Price__c=100;
insert b;
Book__c b2 = [Select Price__c From Book__c where id=:b.id];
System.assertEquals(90,b2.Price__c);
}
}
G% /

/ ##

@isTest
Public Class ContactsCreationTest{
static testMethod void CreateContacts(){
Account a = new Account();
a.name='Test Account';
a.phone='9052757414';
a.Rating='Hot';
a.Number_of_Locations__c=4;
insert a;
List<Contact> lc=[Select id from Contact where AccountId=:a.id];
System.assertEquals(a.Number_of_Locations__c, lc.size());
}
}
% /

/ ##

@isTest
Public Class UpdateCPActivenOnOpptyTest{
static testMethod void updateCustomerProjectOnopty(){
//Inserting first Opportunity
Opportunity opp1= new Opportunity();
opp1.Name='Test Opportunity 1';
Date myDate = Date.newinstance(2012,6,24);
opp1.CloseDate=myDate;
opp1.StageName='Prospecting';
insert opp1;
//Inserting a Customer Project with Status equal to Active for above opp1
Customer_Project__c cp1=new Customer_Project__c();
cp1.Name='Test 1';
cp1.Status__c='Active';
cp1.Opportunity__c=opp1.id;
insert cp1;
Opportunity o1=[Select Active_Customer_Project__c from Opportunity where id=:opp1.i
75

(
d];
System.assertEquals(true,o1.Active_Customer_Project__c);
//Inserting first Opportunity
Opportunity opp2= new Opportunity();
opp2.Name='Test Opportunity 1';
Date d = Date.newinstance(2012,6,24);
opp2.CloseDate=d;
opp2.StageName='Prospecting';
insert opp2;
//Inserting a Customer Project with Status equal to Inactive for above opp2
Customer_Project__c cp2=new Customer_Project__c();
cp2.Name='Test 2';
cp2.Status__c='Inactive';
cp2.Opportunity__c=opp2.id;
insert cp2;
Opportunity o2=[Select Active_Customer_Project__c from Opportunity where id=:opp2.i
d];
System.assertEquals(false,o2.Active_Customer_Project__c);
}
}
% /

/ ##

@isTest
Public Class CreateCRonContactCreationTest{
static testMethod void CreateContact(){
//Inserting Contacts with Postive Scenario
Contact c1 = new contact();
c1.LastName='Anil Reddy';
c1.Contact_Relationship__c=True;
insert c1;
List<Contact_Relationship__c> ConRel1 = [SELECT Id FROM Contact_Relationship__
c WHERE Contact__r.Id =:c1.id];
//verify that Contact Relationship was created for above contact
System.assertEquals(1,ConRel1.size());
// Inserting Contacts with Negative Scenario
Contact c2=new Contact();
c2.lastName='Sateesh Reddy';
c2.Contact_Relationship__c=false;
insert c2;
List<Contact_Relationship__c> ConRel2 = [SELECT Id FROM Contact_Relationship__
c WHERE Contact__r.Id =:c2.id];
System.assertEquals(0,ConRel2.size());
}
}
76

(
'% /

/ ##

@isTest
Public Class UpdateCROwnerNameTest{
static testMethod void updateCROwnerName(){
//inserting a user
Profile pId= [select id from Profile where name =: 'System Administrator'];
User u= new User();
u.LastName = 'Test User ';
u.Alias = 'ta';
u.Isactive =true;
u.Username = 'testuseraccount@test.com';
u.Email = 'testuser@test.com';
u.CommunityNickname= 'TestCN';
u.TimeZoneSidKey = 'America/Los_Angeles';
u.LocaleSidKey='en_US';
u.EmailEncodingKey= 'ISO-8859-1';
u.ProfileId = pId.Id;
u.LanguageLocaleKey = 'en_US';
insert u;
//inserting a Contact
Contact c = new Contact();
c.LastName='Anil';
insert c;
//inserting a Contact Relationship
Contact_Relationship__c cr= new Contact_Relationship__c();
cr.Name='Test Contact Relationship';
cr.Contact__c=c.id;
insert cr;
//updating the Owner Name
Contact_Relationship__c cr1=[Select OwnerId from Contact_relationship__c where id =:
cr.id];
cr1.Ownerid=u.id;
update cr1;
Contact_Relationship__c cr2=[Select OwnerId from Contact_relationship__c where id =:
cr1.id];
System.assertEquals(u.id,cr2.OwnerId);
}
}

%/

/ ##

77

(
@isTest
Public Class InsertAccountTeamTest{
static testMethod void AccountMangerInsertIntoAccountTeam(){
//inserting a user
Profile pId= [select id from Profile where name =: 'System Administrator'];
User u= new User();
u.LastName = 'Test User ';
u.Alias = 'ta';
u.Isactive =true;
u.Username = 'testuseraccount@test.com';
u.Email = 'testuser@test.com';
u.CommunityNickname= 'TestCN';
u.TimeZoneSidKey = 'America/Los_Angeles';
u.LocaleSidKey='en_US';
u.EmailEncodingKey= 'ISO-8859-1';
u.ProfileId = pId.Id;
u.LanguageLocaleKey = 'en_US';
insert u;
//Inserting an Account
Account a = new Account();
a.Name='Test Account';
insert a;
//inserting Customer for above account
Customer__c c=new Customer__c();
c.Name='Test';
c.Account__c=a.id;
c.Account_Manager__c=u.id;
insert c;
AccountTeamMember atm=[Select UserId from AccountTeamMember where AccountId
=:a.id];
System.assertEquals(u.id,atm.UserId);
}
}
-

:-

Apex scheduler is helpful to invoke apex classes to run at specific times, first implenent
the schedulable interface for the class, then specify the schedule using either the
schedule apex page in the salesforce user interfaces, or the system schedule method.
& :- Salesforce only adds the process to the queue at the scheduled time actual
execution may be delayed based on service availability.

We can only have 25 classes scheduled at one time we can evaluate current by
viewing the scheduled jobs page.

78

(
Go to the following path to view the scheduled jobs.
Your NameSetupAdministration setupMonitoringSchedule Jobs
.

:-

To schedule an apex class to run at regular intervals, first write an apex class that
implements the interface schedulable (Salesforce Provided)
The Schedulable interface contains one method that must be implemented execute
2 Global void execute (Schedulable Context sc) {
}
The following example implements the schedulable interface for a class called helloworld
2 Global class schedule helloworld implements schedulable { global void execute
(schedulable context sc)
{
Helloworld hw = new helloworld ( ) ;
}
}
/

1 ! 1

:-

Click your Name setup


Apex classes
1. Click on schedule apex button
2. Specify the name of a class that we want to schedule
3. Specify the how often the apex class is run.
For Weekly Specify one or more days of the week the job is to run ( such as Monday
and Wednesday )
For Monthly Specify either the date the job is to run or the day ( such as second
Saturday of every month)

79

(
Specify the start and end dates for the apex scheduled class. If we specify a single day the
job only runs once.
4. Specify a preferred start time. The exact time the job starts depends on
what jobs are in the queue at that time.
5. Click Save button.
Standard Apex Schedular with Account Creation Class :
global class CreateAccountSchedule implements Schedulable
{
global void execute(SchedulableContext SC)
{
Account_Creation ac = new Account_Creation();
ac.Create_Account('Osmania University', '9052');
}
}
,
To use batch Apex, we must write an Apex class that implements the Salesforce-provided
interface Database.Batchable, and then invoke the class programmatically.
The Database.Batchable interface contains three methods that must be implemented:

The start method is called at the beginning of a batch Apex job. Use the start method
to collect the records or objects to be passed to the interface method execute. This
method returns either a Database.QueryLocator object or an iterable that contains
the records or objects being passed into the job.
Use the Database.QueryLocator object when we are using a simple query (SELECT)
to generate the scope of objects used in the batch job. If we use a querylocator
object, the governor limit for the total number of records retrieved by SOQL queries
is bypassed. For example, a batch Apex job for the Account object can return
aQueryLocator for all account records (up to 50 million records) in an organization.
Another example is a sharing recalculation for the Contact object that returns
aQueryLocator for all account records in an organization.

80

(
The execute method is called for each batch of records passed to the method. Use
this method to do all required processing for each chunk of data.
This method takes the following:
A reference to the Database.BatchableContext object.
A list of sObjects, such as List<sObject>, or a list of parameterized types.
If we are using a Database.QueryLocator, the returned list should be used.
Batches of records are not guaranteed to execute in the order they are received from
the start method.
Sample syntax :
Global Void execute(Database.BatchableContext BC, List<P>){}

The finish method is called after all batches are processed. Use this method to send
confirmation emails or execute post-processing operations.
Syntax : global void finish(Database.BatchableContext

){}

Each execution of a batch Apex job is considered a discrete transaction. For example, a
batch Apex job that contains 1,000 records and is executed without the
optional
parameter from Database.executeBatch is considered five transactions of
200 records each. The Apex governor limits are reset for each transaction. If the first
transaction succeeds but the second fails, the database updates made in the first
transaction are not rolled back.

# .

Global class UpdateOpportunityLeader implements Database.Batchable<SObject>


{
Public String Query=['Select Id,Leader__c,(Select Id,opportunityId,UserId,TeamMemb
erRole From OpportunityTeamMembers where TeamMemberRole=\'Lead Qualifier\' Ord
er by CreatedDate Desc Limit 1) from Opportunity'];
Global Database.QueryLocator Start(Database.BatchableContext BC)
{
System.Debug(Database.getQueryLocator(query));
return Database.getQueryLocator(query);
}
Global void Execute(Database.BatchableContext BC,List<Opportunity> opportunities)
{
List<Opportunity> opp =new List<Opportunity>();
for(Opportunity objOpp:opportunities)
81

(
{
if(objOpp.OpportunityTeamMembers.Size()>0)
{
for(OpportunityTeamMember team :objOpp.OpportunityTeamMembers)
{
if(team.UserId !=null)
{
if(team.TeamMemberRole=='Lead Qualifier')
objOpp.Leader__c =team.UserId;
opp.add(objOpp);
}
}
}
else
{
objOpp.Leader__c =null;
opp.add(objOpp);
}
}
update opp;
}
Global void finish(Database.BatchableContext BC)
{
AsyncApexJob a = [Select Id, Status, NumberOfErrors, JobItemsProcessed,
TotalJobItems, CreatedBy.Email
from AsyncApexJob where Id =:BC.getJobId()];
// Send an email to the Apex job's submitter notifying of job completion.
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {ABC@gmail.com,xyz@gmail.com'};
mail.setToAddresses(toAddresses);
mail.setSubject('Test Batch ' + a.Status);
mail.setPlainTextBody
('The batch Apex job processed ' + a.TotalJobItems +
' batches with '+ a.NumberOfErrors + ' failures.');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}

82

(
5 * <: &; * E < :

?*

Salesforce.com has created a comprehensive platform for building on demand applications .like other sophisticated application developer's platform's the
force.com platform offer's separate tools for defining.
The structure of data

DATA MODEL

The rules that detail how the data can be manipulated

BUSINESS

LOGIC
The layout that specifies how data should be displayed THE USER
INTERFACE
This splitting up application development tools based on the above is known as MVC
(Model View Control) application development pattern.
Model

data model

View

user interface

Controller

Business logic

While the tools for building the data model and business logic for applications are
powerful solutions that run natively on force.com platform servers, the existing tool's for
defining user interface's have certain limitations.
/

<.

# < "
Its a point and click tool that allows applications developer to organic
fields, buttons and related lists on record detail pages, doesn't provide much flexibility in
how sets of information can be displayed.
<4

ield must always appear above related lists


Button's must appear below the fields (above)
And S.Control's and custom link's can only be placed in particular areas.

# %

E ?E

#@

The tool that allows application developers to display custom links (HTML) in a
detail page or custom tab, this provides more flexibility for the fields and page layouts.
But
Executes from within a browser, causing poor performance if displaying or
updating values for more than a few records at a time.

83

(
Do not provide an easy way to give custom UI elements the same look-and-feel as
standard SF pages.
Require developer to enforce field uniqueness and other metadata dependencies on
their own.
&
S.control's are suppressed by VF pages (Visual Force).After March 2010
organizations that have never created S.Control's as well as new organizations, won't be
allowed to create them
Existing S.Control's will remain and can still be edited.
These are the reasons why VF pages came in to existence; these are nextgeneration solutions for building sophisticated user interfaces on the Force.com platform.
8

VF is a frame work that allows developer's to build sophisticated, custom user interfaces
that can be hosted natively on the Force.com platform.
This includes a tag based markup language, similar to HTML.
In VF markup language each VF tag corresponds to a coarse or fine-gained users
interface components such as
Section of page
A related list or a field.
The behavior of VF components can be controlled by the same logic that is used in
standard SF pages, or developer can associated their own logic with a controller class
written in APEX.

:-Tag in VF are

<apex:page>
<apex:page Block>
<apex:page Block Buttons>
<apex: page Block section>

<apex:page Block section Item>


<apex:page Block Table>

Tags related to a page tags

84

(
Input field tags:

Select tags:

<apex:inputcheckbox>

<apex:selectioncheckbox>

<apex:inputField>

<apex:Selection list>

<apex:input File>

<apex:selectoption>

<apex:inputHidden>

<apex:select options>

<apex:inputsecret>

<apex:select Radio>

<apex:input text >

<apex:variable>

<apex:input text area>

<apex:vote>

Output field Tags:


<apex:output Field>
<apex:output label>
<apex:output link>
<apex:output pannel>
<apex:output text>
Like this there are around 90 tags in VF and each tag full fills request such as defining a
page, page block field, toolbar these tags can be divided into
Input tags
Output tags
Select tags
Form tags
Page tags and so on
Using these tags developers can create a VF page definition. It consists of two
primary elements.
VF Markup

A VF

Controller

85

(
Visual force Markup consists of VF tags, HTML, JavaScript and many
* 7 4
other web-enabled code embedded within a single <apex: page>tag.
This defines the user interface components that should be include on the
pages, and the way they should appear.
*
VF controller is a set of instructions that specifies what happens when a
user interacts with UI components specified by VF markup, (such as when user clicks on
the button on link).controller also provides access to the data that should be displayed on
the page, and can modify component behavior.
A developer can use a standard controller consists of the same functionality and
logic that is used for a standard salesforce page.
: If we use the standard Account controller, clicking a save button in VF page
results in same behavior as clicking save button on Account edit page
Using page layouts, we cannot have access to the objects in standard field, and display's
an error called as insufficient privileges error message, we can avoid this by checking the
user's accessibility for an object and displaying component approximately.
1. A standard list controller enables us to create VF pages that can display an act on
a set of records like list pages, related lists, and mass action pages.
2. Custom controller: its a class written in Apex that implements all page's logic,
without leveraging a standard controller, if we define this, we have to define new
navigation elements or behaviours, but we must implement any functionality that
was already provided in a standard controller.
3. Controller extension: class written in Apex that adds to or overrides behaviour in
a standard or custom controller.
Extensions allow us to leverage the functionality of another controller while
adding your own logic.
*

Developer can use VF pages to


Override standard buttons, such as NEW button for accounts, save button for
contacts.....
Define custom tab.
Embed components in detail page layout.
Create dashboard components on custom help pages.
Customize, extend on integrate the sideboards in the services cloud console (custom
console components)

86

(
*

/ # U/

@L
# M This is a very important tag of a VF. This says that a single VF page
and all the components must be wrapped inside this single page.
Attributes of <apex: page> tag are:
: This invokes when this page is requested by the server, here we must use a

expression language to reference an action method in APEX


Action= {! do action} Must be defined in APEX class.
action= {! int} or action= {!redir}

re directions the page to new page

referred
Initializes

Its a string type and the name given here must be implemented in an
Apex class, controller means an custom controller, this cannot be used if we use standard
controller.
<apex: page

Controller="class name implemented in APEX">

Extension: This is used to extend the custom controllers we can have any extension
for an custom controller, this is used to add extra functionality.
<apex: page controller: string" extension="string">
ID: Its a string, gives an identification for tag, we can specify any name, but it should
not be a duplicate, its generally used to refer this page by other components in the page.
Record setvar: its a string; this attribute indicates that the page users a set of records
oriented by a standard controller only.
Used to handle multiple records, this attribute converts a controller to a list controller.
Render As: its a string the name of any supported content converter, we can change
the display in to a 'PDF' or another type currently its only a 'PDF' format.
<apex: page render as='PDF'> displays a page in a pdf format
Renderd: it's a Boolean type, related to the displaying of a page by default its a
'TRUE', if we keep it false the page will not be displayed.
Setup: it's a Boolean type; it specifies whether the page should implement standard
salesforce.com setup if its true.It will not implement by default if its "FALSE"
Show header: it's a Boolean type, displays or hides the salesforce header if true or false
respectively.
Sidebar: it's a Boolean type, displays or hides the sidebar of standard salesforce site.
87

(
standard controller: it's the sales force object that's used to control the behaviour of
this page, this attribute cannot be specified if custom controller is used.
<apex: page standard controller="Account">
Standard style sheets: it's a Boolean type; it decides whether the standard salesforce
style sheets are added to the generated page header if the showheader attribute is set false,
if its set true the standard style sheets are by default, added to the generated page header.
The other important tags are tab style title, help URL & help title.
@
% .: A section of a VF page that allows users to enter o/p and then submit it
with an <apex: command Button> or <apex :command link>
The body of the form determines the data that is displayed and the way it is
processed.
1

it's a string type, the text to display as a tooltip when the user's mouse pointer
hovers over this component.
:Its a string type, its a comma separated list of characters encoding that a
server processing this form can handle.
5 its a string type, it specifies the directions such as RTL & LTR (Right to left or left
to right), that should display the components in the form of a VF page(position).
Onclick, anddblclick, onkeydown, on keypress, onkeyup, onmousedown, onmouseout,
onmousemove, onmouseup, onreset, onsubmit
These are the general attributes must be used within the form tag, all related when
we use JAVASCRIPT in our design, when this JAVASCRIPT should be invoked either
on one click, double click, onkeydown, press, up, down, move..............
On-reset and on submit are important, here the JavaScript is invoked when an event such
as reset/submit occurs, if the user clicks on reset/submit buttons.
Q@
# 1 4 it's an area of a page that uses styles similar to the appearance of a
salesforce detail page, without any default content.
In detail page we can see only the components in 2 column's here we can
make it to any number of columns using page Block section. And we can create instances
rather than full names of objects
i.e.

<apex:pageblock value="{!account}" var="AC">


</apex:pageBlock>

88

(
1
5

Direction of display 'RTL/LTR'

it's a string type, the text in title will be displayed when a user hovers the
mouse over the help link for the pageblock. We must use this in relation with helpURL
E < it's a string type, the URL of a webpage that provides help for the page block.
Here also we can perform the same actions which can be performed using the form tag,
the Java script enabled tag attributes are like the following.
Onclick, onclick, onkeydown, onkeypress, onkeyup...........
@L
%
. M This is an tag which is used to mention the column name of the
column and this will overrides the attributer properties of the <apex:pageblock> section
like JavaScript enabled attributes, title, help text, help URL,.......
And the column component can be added in both ways i.es the header and footer.
The components that appear at the bottom of the page block.
0 - : The components that appear as a header of the page block.
F@
# , 4
This tag can be used to create sections within a page block
to categorize different fields into different sections.
Its similar to adding a section by using a edit page layout assignment.
These sections spans of two cells. One for the field label, and another for its
value. Each component found in the body of an <apex: pageblock section> is placed into
the next cell in a row until the no. of columns is reached.
To add fields, and objects to this <apex: pageblock section> we use
<apex:inputfield> or <apex:outputfield> component each of these component
automatically displays with the field's associated label.
1
it's a Boolean type, it specifies whether the page block section can be
1
expanded and collapsed by a user, by default its "TRUE"
it's an integer type, it specifies the no. of columns that can be included in a
.
single row of a pageblock section, a single column can span two cells-one for field
label, and another for its value.
5

Direction RTL or LTR

It's a Boolean type variable, value that specifies whether the page block
6
section title is displayed, if it's true.

89

(
@

# 1

A single piece of data in an <apex: pageblocksection> that takes keep up one


column in one row.
An <apex:pageBlocksection Item> component can include up to two child components,
If no content is specified, the content spans both cells of the column.
If two child components are specified , the content of the first is rendered
in left, "label" cells of the column, while the content of the second is rendered in the
right , "data' cell of the column.
: if we include an <apex:outputfield> or an <apex:inputfield>component in an
<apex:pageblockitem>, these components do not display with their label or custom help
text as they do when they are children of an <apex:pageblockitem>
And these components cannot be rendered, rerender the child components instead.
1

(DIr, helptext,ID)

< 1 " Its a string type, these style used to display the content of the left label" cell
of the page block section column and uses all JavaScript enabled tags (discussed above)
G@L

# 1

41

A set of buttons that are styled like standard salesforce buttons the component must be a
child component of an <apex: pageblock>
This tag creates buttons and places them in the page block title area and footer area.
Here we can specify the location of the button's in a section it can be either
"Top/Bottom"
Attributtes: Dir,
<
it's the area of the page block where the buttons should be rendered.Possible
values are "top/bottom" or "both". This can be overridden when we use facet
(header/footer)
By default it's set to both.
A button that is rendered as an HTML o/p element with the
@
.. - 1
type attribute set to "submit" , "rest" or "image" depending on the <apex: command
button> tags specified values
The button executes an action the child of an <apex: form> component
:<apex:commandbutton action="{!save}" value="save" id="the button"/>

90

(
1
4 " it's a string type, it's a keyboard accesskey that puts the command button in
focus.
action: Apex page. Action this can be invoked by AJAX request to the server uses
merger-field syntax to reference the method.
Action="{! save}" references save method written in controller. If action is not
specified, the page simply refreshes.
5

5 5

1 -

. # it's a string type, the absolute or relative URL of image displayed as this button,
if specified; the type of the generated HTML input element is set to "image"
Supports all Java script enabled attributes.
- -: its Boolean type, value that specifies whether the component is rendered on
the page. If not specified, by default its true.
- The type is Object, the ID of one or more components that are redrawn when
the result of an AJAX update request return to the client.
its an integer type, the amount of time (in milliseconds) before an AJAX
/.
update request should time out.
its an object type, text displayed on the Command Button as its label.

*
@L
page.

This tag can be used to display custom error messages on a VF

# M

If this is not mentioned then the errors can be displayed only in debug log;
'@L

# M

All messages that were generated for all components on the current page.(standard
salesforce style error messages)
Default name is "error"
@L

# .

# M

This component should be used for presenting custom messages in the page using the
salesforce pattern for errors, warnings and other type of messages for a given severity.
1
5

it's a string type, the detailed description of the errors information.

+ " it's a string type, values supported by this are confirm, 'info', warning', 'error'.
We can display the severity of the error messages generated.
91

(
it's an integer type, its the strength of the message, this controls the visibility
#
and size of icon displayed next to the message.
Use 0 for no image, or 1-3 (highest strength, largest icon)
.. "

it's a string type, the summary message.

@L

# .

# M

This component displays all messages that were generated for all components on the
current page, presented using the SF styling.
1
: its Boolean type, A Boolean value whether, sensitive HTML, and XML
characters should be escaped in the HTML old generated by this component.
65
It's a Boolean type, specifies whether it displays the detail position of the
messages, by default its false.
Q@ L

This is a self sustained tag, this is a very powerful tag, this displays details page of a
particular object.
This component includes attributes for including or excluding the associated related lists,
related lists hover links, and title bar that appear in the standard SF API.
1
-

It's a Boolean type, controls whether the component supports inline editing

or not.
-<
It's Boolean type, which specifies whether the related lists are included in
the rendered component.
It's a Boolean type that specifies whether the related list hover links
+
are included in the rendered component.
Enable Related List Hover Links: Selected under setup/Customize /user interface.
5 It's a string type, indentifies that allows the detail component to be referenced by
other component in the page.
- -: It's a Boolean value that specifies whether the component is rendered on the
page, by default its true.
It's an object type, the ID of one or more components that redrawn when the
result of an AJAX updates requested returns to the client.
***This will only works if inline Edit or show chatter are set to true.
92

(
@ L
%
, M This tag creates a panel bar on a VF page which can
accommodate multiple panels.
***This can include up to 1, 0000 >apex: panel Bar Item> tags.
This tag creates a pannel bar on a VF page which can accommodate multiple panels.
Attributes:
0 #
It's a string type, the height of the pannel bar when expanded, expressed either
as a percentage of the available vertical space height="50" or height "200 px"s
6
"
Bar Items.

It's a string type, the implementation method for switching between Pannel

The possible values include; "client", "server" and ajax .


The value; it's an object type the ID of the Pannel Bar is displayed.
*
It's a string type, the name of the variable that represents one element in the
collection of data specified by the item attribute. We can then use this variable to display
the element. Itself in the body of the Pannel Bar. Component tag.
Controls the width of the pannel bar, expressed either in percentages of the
8available horizontal space or as a number of pixels. If not specified default is ="100%".
F@ L

.M

It's a section of <apex: Pannel Bar > That can expand or retract when a user clicks the
section header, when expanded the header and the content of the <apex: Panel Bar Item>
is displayed, when retracted, only the header of the <apex: Panel Bar Item> displays.
1
- - It's a Boolean type, that specifies whether the content of this : Panel Bar Item
is displayed.
< 1
It's a string type, the text displayed as the header of the Panel Bar Item
component.
It's a string type, JavaScript invoked when the Panel Bar Item is not selected
:
and the user clicks on the component to select it.
:
+
Item.
@L

It's a string type, JavaScript invoked when the user selects a different Panel Bar
/ 1

A page area that displays as a set of tabs. When is a user clicks a tab header, the tabs
associated content displays binding the content of others tabs.
Creates a Panel, which can accommodate multiple tabs.
93

(
1
+
1
It's a string type its a style classes used to display a tab header in the
tab panel when it is selected, used primarily to designate, which css styles are applied
when using an external css style sheet.
An HTML style name which controls the look and feel of the tab that is currently
selected.
+ / 1

Controls the look and feel of inactive tabs.

- / 1 Name of the tab that should be first selected on displayed to the user when
the page is first open .
it will be the default tab when the page loads.
Header Alignment: Left/Right. And we can adjust the spacing b/w tabs through header
spacing.
G@ L

/ 1M

This component must be a child of an <apex: tab panel>


1
- It's a string type, an identifier that allows the tab component to be referenced by other
component in the page.
It's a Boolean type, specifies whether the action associated with this
.. component happen's immediately, without processing any validation rules associated
with the fields on the page. If set to true, the action happen's immediately and validation
rules are skipped, by default it's false.
and support s all Java enabled tags such as onclick, on doubleclicks....
:E/ E/ / ;
18) <Apex: Output field value = "{!-----}"/>
19) <Apex: Output label value = "{!
20) <Apex: Output label value = "{!

}"/>
}"/>

21) <Apex: Output text value = "www.google.com" > <Apex: Output link>
To displays views:
22) <Apex: List view value ="Standard/custom object"/>
23) <Apex: enhanced list type ="Standard/custom object"/>
24) < Apex: Sectioned header>:
94

(
A tittle bar for a page. In a standard salesforce.com page the title bar is a colored header
displayed directly under.
1

the tab bar.

5
: It's a string type, description text for the page that displays just under the
colored title bar.
: It's a string type, the URL is printable view.
The text displayed just under the main title in the colored title bar.

1
25@ L

41

> These are elements, displayed in a table.

1
4 " It's a string type, the keyboard access key that puts check boxes component in
focus.
It's a string type, the method for which check boxes should be displayed in the

< "
table.

Possible values are: "Lines direction". Check boxes are horizontal "page direction"
placed vertically.
By default its value is "line direction"
It's an object type, a merge field that references the controllers class variable that
*
is associated with this select checkboxes component.
i.e.

Ex: Value = "{!my checkboxes selections}".

@ L
M A list of options that allows users to select only one value or
multiple values at a time, depending on the value of its multiselect attribute.
1
It's a Boolean type, specifies whether the user's can select only one or more
7
items from a list.
It's a string type, the order in which this select list component is selected
** 1 compared to other page components when a user presses the tab key repeatedly.
The value is an integer from 0-32767.
G@ L

The values are provided from <apex: selected checkboxes > or <apex: Select List> or
<apex : select radio> component.
It must be a child of one of the above component.

95

(
The no. of checkboxes/Radio buttons/List values that are declared in logic (method apex)
in the controller part.
Uses attributes discussed above.
@L

M%

Only we have 3 attributes: id, render, value


Q'@ L

- M

A set of related radio button input elements, displayed in a table, unlike checkboxes, only
one radio button can ever be selected at a time.
Tags used to invoke Java script using AJAX request (A synchronous Java script and
XML).
And the tags are .
@L

A component that provides support for invoking controller action method directly
from
JavaScript code using an AJAX request. An <apex: action function> it must be a child of
<apex: from>.
<apex: action support>, supports invoking controllers action method from
5
other VF components. (referenced by other components)
<apex: action function> defines New JavaScript function which can then be called from
within a block of JavaScript code. (within JavaScript )>.
1
This is Apex Pages. Action, type, the action method invoked when the action
Function is called by a JavaScript event elsewhere in the page markup. We use merge
field syntax to reference the method.
If an action is not specified, the page simply refreshes.
& .
It's a string type, the name of the JavaScript function, that when invoked yes,
elsewhere in the page Markup, causes the method specified by the action attribute to
execute. When the action method components specified by the rerender attributes will be
refreshed.
- : It's an object type, the ID of one or more components that are redrawn when the
result of the action method returns to the client.

96

(
The component which are redrawn when-separated lists of ID's, or a merge filed
expression for a list or collection of ID's (These are displayed after the execution of the
method).
Render before execution
Render after execution}

component displayed

It's a string, the ID of an associated component that displays the status of an


AJAX: update request.
Its an integer type, the amount of time (in milliseconds) before an AJAX
/.
update request should time out.
.. A Boolean value that specifies whether the action associated with this
component should happen immediately, w/o passing any validation rule associated with
the fields on the page, if set to true. (Validations are skipped) by default its false.
:
.
Its a string type, this provides us with a name of the JavaScript file
invoked when an event occurs. When AJAX request is processed.
@L
M It does a partial page refreshment based on time interval. The
times sends an AJAX update request to the server according to a time interval that we
specified.
(don't use this with enhanced listing)
<apex :action poller> is ever re-rendered as the request of another action, it resets itself.
It should be within the <apex: action region>.
1
ApexPage. Action, invoked by the periodic AJAX update request from the
***
component, can use merge field syntax to reference a method.
"{!increment counter}"
controller.

reference the incrementcounter () method in the

If action is not mentioned the page simply refreshes.


Time interval between AJAX update request, in seconds here the updation can
+
be done for multiple fields at a time. This can be written in action logic.
Q@L

This tag helps us to create a set of components which can be displayed whenever some
Ajax up date is performed on a VF page.
An area of a VF page that demonstrates which components should be processed by the
Force.com server.
97

(
Only the components inside <apex: action region> are processed by the server during an
AJAX request. But it doesn't define the area (s) of the pages (s),( rendered) when the
request completes .
To controls the behavior, use the rerender attribute on an <apex: action support>
<Apex: action Poller >
<Apex: Command Button>
<apex: Command Link>
<apex: tab
<apex: tab Pannel>.
1
- It's a string type, it indentifies that allows the component to be referenced by other
component in the page.
#
" It's a Boolean type, a Boolean value that specifies whether AJAXinvoked behaviour outside of the action region should be displayed when the action
region is processed, if true.
By default its set to TRUE
@L
M
A component that displays the status of AJAX update
request. An AJAX request can either be in progress or complete.
Message can be anything like inserting, updating completed, done -----etc.
1
It's a string type, the status text displayed at the start if AJAX request. the
message to be displayed once the action is invoked or before the action is completed.
This is a string type, the ID of an action region component for which the status
indicator is displaying status.
- allows the action status components to be referenced by other components in the
page.
/
F@ L

The status text displayed when an AJAX request completes.


M

A component that adds AJAX support to another component, allowing the component to
be refreshed asynchronously by the server when a particular event occurs, such as button
click or mouse over.
1
(creates a set of components displayed whenever some update is
performed on VF pages).
98

(
It's a string type, this is an JavaScript event that generates the AJAX request
+
possible values are ("on blur", on change", "on click", "on bl click", "on focus", "on key
down", "on key press'---------)
The id of the component that is in focus after the AJAX request completes.
AJAX

It's a string type, the ID of an associated component. That displays the status if
update
request.

*
*

Create the Visualforce page called Opportunity Viewwith the following code and
override with the New button on Opportunity Object.Result would be like once we
click on the Opportunity tab and click on New button
<apex:pagestandardController="Opportunity" sidebar="false" showHeader="true">
<apex:form>
<apex:pageBlock title="Opportunity Detail">
<apex:pageBlockButtons>
<apex:commandButton value="Save The Opportunity" action="{!Save}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection
title="Opportunity
Information
1"
columns="2"
collapsible="false">
<apex:inputField value="{!Opportunity.Name}"/>
<apex:inputField value="{!Opportunity.Active__c}" required="true"/>
<apex:inputField value="{!Opportunity.DeliveryInstallationStatus__c}"/>
<apex:inputField value="{!Opportunity.TrackingNumber__c}"/>
<apex:inputField value="{!Opportunity.CloseDate}"/>
</apex:pageBlockSection>
<apex:pageBlockSection
title="Opportunity
Information
2"
columns="2"
collapsible="true">
<apex:inputField value="{!Opportunity.Description}"/>
<apex:inputField value="{!Opportunity.LeadSource}"/>
<apex:inputField value="{!Opportunity.NextStep}"/>
<apex:inputFieldvalue="{!Opportunity.Type}"/>
<apex:inputField value="{!Opportunity.StageName}"/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

99

Now click on the Opportunity tab and click on New button

100

(
*
8

#
+

+ 6

/ 1

<apex:pagestandardController="Account" showHeader="true" tabStyle="account">


<style>
activeTab {background-color: #236FBD; color:white;background-image:none}
inactiveTab { background-color: lightgrey; color:black;background-image:none}</style>
<apex:tabPanelswitchType="client" selectedTab="tabdetails"
id="AccountTabPanel" tabClass="activeTab" inactiveTabClass="inactiveTab">
<apex:tab label="Details" name="AccDetails" id="tabdetails">
<apex:detailrelatedList="false" title="true"/>
</apex:tab>
<apex:tablabel="Contacts" name="Contacts" id="tabContact">
<apex:relatedList subject="{!account}" list="contacts" />
</apex:tab>
<apex:tablabel="Opportunities" name="Opportunities" id="tabOpp">
<apex:relatedList subject="{!account}" list="opportunities" />
</apex:tab>
<apex:tablabel="Open Activities" name="OpenActivities" id="tabOpenAct">
<apex:relatedList subject="{!account}" list="OpenActivities" />
</apex:tab>
<apex:tab label="Notes and Attachments" name="NotesAndAttachments"
id="tabNoteAtt">
<apex:relatedList subject="{!account}" list="NotesAndAttachments" />
</apex:tab>
</apex:tabPanel>
</apex:page>
Create the button called Tabbed Account on the Account object. While creating button,
select OnClick Java Script as the Content Source and write the following code

?V=
&

%6 - 6%
=
-<

%
/ 15

"9 -AWX

% -TV@>

RelatedListAsTabsDisplay --Visualforce Page Name

101

Once we click on Tabbed Button, we will get the following screen.


Click on Details tab to open Detail page
Click on Contacts tabto open the Contacts related list and
same for Opportunities, Open Activities and
Notes and Attachments

In
the
1st
step
starts
with
pagetag,
here
it
includes
standardController=ACCOUNT, and the header will be enabled, and tab style
will be of account.
<Style> is used to include STYLE SHEETS, here we used them to disply the
ACTIVE AND INACTIVE tabs. ACTIVE is: BLUE COLRED And INACTIVE:
Grey in color.
We are taking a tab panel which consists of all the tabs of account
SwitchType: The implementation method for switching between tabs specifies the
general operation is between CLIENT and Server.
SELECTED TAB:The name of the default selected tab when the page loads.
<apex:tab> defines the tab name, label and id.
<apex;detail/> this is a self sustained tag gives the detail page of each account tab
selected and the attribute RELATED list can be a Boolean one.
<apex:related list> in this we used SUBJECT and LIST.
The attribute Subject specifies the parent record from which the data or the related
list has to be mentioned in your case its ACCOUNT.
LIST: name of the child that should be appeared on the tab CHILDS of account..
102

(
&

Redirecting the visualforcepage to the listviewpage using single tag.


L
Y:1!

#
/" %

AVWXE < : ?Y

%<

@TV=M

This can be used for all the objects. i.e. Y


contacts

shows the list of

We can use the same for custom object


.
1!
. % andobjecttype.custom object API name will give the list view of the
custom object.

The followingvisualforce page displays the Contacts for particular account in a separate
window as the table (format is standard salesforce page)
Page Name=ContactsForAccount
<apex:pagestandardController="Account">
<apex:pageBlock title="Hello {!$User.FirstName} {!$User.LastName}!">
We are viewing the Contacts for this <b>{!account.name}</b> Account.
</apex:pageBlock>
<apex:pageBlock title="Contacts">
<apex:pageBlockTable value="{!account.Contacts}" var="con">
<apex:column value="{!con.Name}"/>
<apex:column value="{!con.Lastname}"/>
<apex:column value="{!con.Phone}"/>
<apex:column value="{!con.Title}"/>
</apex:pageBlockTable>
</apex:pageBlock>
103

(
</apex:page>
Create the button called ContactsForAccount on Account Object and override above
visualforce page with this button.

104

(
Starting tag for a visualforcepage is <apex:page> and this follows standard object
ACCOUNT.
Forming a new page block which gives the user name and Account holder name.
Forming a new page block with title as CONTACTS.
And then retrieving the contact fields using account and the field label are shown
as column headers.
*
Create the Visualforce page with the following code. This is the example for custom
controller.
Page Name=PageReference
<apex:page controller="MyCustomController" tabStyle="Account">
<apex:form>
<apex:pageBlock title="Account Detail">
<apex:pageblockSection title="Account Information" >
<apex:inputField value="{!account.Name}"/>
<apex:inputField value="{!account.Phone}"/>
<apex:inputField value="{!account.Industry}"/>
<apex:inputField value="{!account.Rating}"/>
<apex:inputField value="{!account.Website}"/>
<apex:inputField value="{!account.Active__c}"/>
</apex:pageblockSection>
<apex:pageblockSection title="Account Detail" >
<apex:inputField value="{!account.BillingCity}"/>
<apex:inputField value="{!account.BillingCountry}"/>
<apex:inputField value="{!account.Description}"/>
<apex:inputField value="{!account.Fax}"/>
<apex:inputField value="{!account.ShippingCity}"/>
<apex:inputField value="{!account.ShippingCountry}"/>
<apex:inputField value="{!account.AnnualRevenue}"/>
</apex:pageblockSection>
<apex:pageBlockButtons>
<apex:commandButton action="{!saveMethod}" value="Save the Page"/>
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
7"

public class MyCustomController{


Public Account acc;
public MyCustomController(){
105

(
acc = [select id,Name,Phone,Industry,Website,Active__c,Rating,BillingCity,De
scription,Fax,
ShippingCity,AnnualRevenue,BillingCountry,ShippingCountry from Account
where
id=:ApexPages.currentPage().getParameters().get('Id')];
}
public Account getAccount() {
return acc;
}
public PageReference saveMethod() {
update acc;
PageReference pageRef = new ApexPages.StandardController(acc).view();
return pageRef;
}
}
Create the Detail Page Link with the name PageReference on Account Object. While
creating select Execute JavaScript as the behavior and onClick JavaScript as the
Content Source
%6 - 6%

?V=

9 -AWX

% -TV@>

Add the PageReference link to the Account Layout

106

Update the field values then click on Save the Page button in the above window,we
will get the Standard Account detail page
*

Create the Visualforce page with the following code. This is the example for custom
controller.
Page Name=WithoutPageReference

<apex:page controller="MySecondController" tabStyle="Opportunity">


<apex:form>
<apex:pageBlock title="Opportunity Detail">
<apex:pageBlockButtons>
<apex:commandButton value="Save The Opportunity" action="{!saveMethod}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection
title="Opportunity
Information"
columns="2"
collapsible="false">
<apex:inputField value="{!Opportunity .Name}"/>
<apex:inputField value="{!Opportunity .DeliveryInstallationStatus__c}"/>
<apex:inputField value="{!Opportunity .TrackingNumber__c}"/>
<apex:inputField value="{!Opportunity .CloseDate}"/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

7"

107

(
public class MySecondController {
Public Opportunity opp;
public MySecondController(){
opp= [select id,Name,DeliveryInstallationStatus__c,TrackingNumber__c,CloseDate fr
om Opportunity where id=:ApexPages.currentPage().getParameters().get('Id')];
}
public Opportunity getOpportunity () {
return opp;
}
public PageReference SaveMethod() {
update opp;
return null;
}
}
Create the Detail Page Link with the name WithoutPageReference on Opportunity
Object. While creating select Execute JavaScript as the behavior and onClick
JavaScript as the Content Source
Follow the java script to call a visualforce page

?V=

%6 - 6%
=8

%
#

9 -AWX:

"% -TV@>

108

(
Go to Opportunity detail page and click on the WithoutPageRef link

Update the field values in the following window and click on Save The Opportunity
button, then values will be updated but redirects to the same page but not to the
opportunity detail page

*
Before we have written trigger saying that when the Contact is created by checking
Contact Relationship checkbox, then Contact Relationship will be created for that contact
automatically.
Create the visualforce page with the following code. Create the button called "Create
Multiple Contact Relationship "on Account object and once we click on this button on
account detail page, then Contacts will be populated which don't have Contact
Relationships.
*

# & . AV

<apex:pagestandardController="Account"
extensions="MultipleContactRelationships"
sidebar="false"
showHeader="false">
<apex:form>
<apex:pageBlock>
<apex:sectionHeader title="Contacts" />
<center>
<apex:commandButton value="Create Contact Relationship"/>
</center>
<apex:pageBlockTable value="{!Conres}" var="CR" cellPadding="40">
<apex:columnheaderValue="Action" >
<apex:facet name="header">Action</apex:facet>
109

(
<apex:inputCheckbox>
</apex:inputCheckbox>
</apex:column>
<apex:column>
<apex:facet name="header">Contact Name</apex:facet>
<apex:outputText value="{!CR.Name}" />
</apex:column>
<apex:column>
<apex:facet name="header">Title</apex:facet>
<apex:outputText value="{!CR.Title}" />
</apex:column>
<apex:column>
<apex:facet name="header">Email</apex:facet>
<apex:outputText value="{!CR.Email}" />
</apex:column>
<apex:column>
<apex:facet name="header">Phone</apex:facet>
<apex:outputText value="{!CR.Phone}" />
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
7
public with sharing class MultipleContactRelationships {
public MultipleContactRelationships(ApexPages.StandardController controller) {
}
public List<Contact> ContactList{get;set;}

Public List<Contact>getConres()
{
Contact c = new Contact();
ContactList=[select id, Name,Title,Email,Phone from Contact where Accountid=:ApexPa
ges.currentPage().getParameters().get('id') and Contact_Relationship__c=true ];
system.debug('********'+ ContactList);
return ContactList;

110

(
}
}
,
Create the button called "Create Multiple Contact Relationship" on Account Object with
the following Java Script
%6 - 6%

?V=

9 -AWX

% -TV@>

The following window will come when we click on "Create Multiple Contact
Relationship" on the above window

G
111

(
The following visualforce code will automatically prompts to the "My Contacts" once we
click on Contacts tab.
Override the following Visual force page with the Contacts tab
*

<apex:pagetabStyle="Contact_Relationship__c" >
<script type="text/javascript">
window.onload = function() {
parent.document.location.href = "/a07?fcf=00B900000031bax";
}
</script>
</apex:page>
ID of the My Contacts list view

*
Create the visualforce page with the following code.
Note: EnablingSectionsonPicklistValues
*

<apex:page
standardController="Account"
extensions="SelectPicklist"
showHeader="true" sidebar="true">
<apex:form >
<apex:pageBlock title="Page Details">
<apex:pageBlockSection >
<apex:selectList label="Year of Passing" value="{!YearValue}" size="1"
multiselect="false" >
<apex:actionSupport event="onchange" action="{!Picklist}"/>
<apex:actionStatus startText="Applying value........">
</apex:actionStatus>
<apex:selectOptions value="{!Yearlist}"/>
112

(
</apex:selectList>
</apex:pageBlockSection>
</apex:pageBlock>
<apex:outputPanel id="pd" rendered="{!YearValue1}">
<apex:pageBlock title="2010 Hiding Details">
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Name">
</apex:outputLabel>
<apex:inputField value="{!Account.Name}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Industry">
</apex:outputLabel>
<apex:inputField value="{!Account.Industry}"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:outputPanel>
<apex:outputPanel rendered="{!YearValue2}">
<apex:pageBlock title="2011 Hiding Details">
<apex:pageBlockSection >
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Phone">
</apex:outputLabel>
<apex:inputField value="{!Account.Phone}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Type">
</apex:outputLabel>
<apex:inputField value="{!Account.Type}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Description">
</apex:outputLabel>
<apex:inputField value="{!Account.Description}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Account Rating">
</apex:outputLabel>
<apex:inputField value="{!Account.Rating}"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:outputPanel>
</apex:form>
113

(
</apex:page>
4
public class SelectPicklist {
public SelectPicklist(ApexPages.StandardController controller) {
}
public String YearValue{set;get;}
public Boolean YearValue1{set;get;}
public Boolean YearValue2{set;get;}
public List<SelectOption> getYearlist () {
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('','--None--'));
options.add(new SelectOption('1','2010'));
options.add(new SelectOption('2','2011'));
return options;
}
public void Picklist(){
if(YearValue=='1')
YearValue1 = true;
else
YearValue2 = True;
}
}
Create the button called Hiding Sections and override Enabling Sectionson
Picklist Values visualforce page

114

(
,

Once we click on Hiding Sections button, it will prompts to the following window have
the field called Year of Passing and values are 2010 and 2011

Once we select 2010 from the above picklist, then 2010 Hiding Details section will be
populated automatically

115

(
Once we select 2011 from the above picklist, then 2011 Hiding Details section will be
populated automatically

*
Create the Visualforce page with following code
Page Name:
*

+ 6:
-

<apex:page Controller="InterviewOne_controller" sidebar="false">


<apex:form >
<apex:sectionHeader title="Interview One" />
<apex:pageBlock title="All Accounts" tabStyle="Interview_One__tab">
<apex:pageBlockTable value="{!listAccounts}" var="a">
<apex:column headerValue="Account Name" value="{!a.name}"/>
<apex:column
value="{!a.BillingState}"/>

headerValue="Billing

State/Province"

<apex:column headerValue="Phone" value="{!a.Phone}"/>


<apex:column headerValue="Website" value="{!a.Website}"/>
</apex:pageBlockTable>
</apex:pageBlock>
116

(
</apex:form>
</apex:page>
+ 6:

public class InterviewOne_controller{


public list<Account> listAccounts{get;set;}
public InterviewOne_controller(){
list<Account>=new list<Account>();
listAccounts = [select name,BillingState ,phone,Website from Account];
}
}
Create the Visualforce tab called
with this tab

+ 6 :

and override the above visualforce

Once we click on the Interview One tab, then all the accounts will be populated in table
format which are not clickable.

117

'

Create the Visualforce page with following code


Page Name:
*

+ 6 /6
-

<apex:page controller="InterviewTwo_controller" sidebar="false">


<apex:form >
<apex:sectionHeader title="Interview Two" />
<apex:pageBlock mode="edit">
<apex:pageBlockSection title="Search" >
<apex:inputText label="Search" value="{!searchString }"/>
<apex:commandButton value="Search" action="{!displayAccounts}"/>
</apex:pageBlockSection>
<apex:pageBlockSection title="Results" rendered="{!showmsg==true}">
<apex:pageMessages rendered="{!showmsg}" >
</apex:pageMessages> <br/>
<apex:pageBlockTable
value="{!listAccounts}"
var="a"
headerClass="headerclass" >
<apex:column headerValue="Account Name" value="{!a.name}"/>
<apex:column
headerValue="Billing
State/Province"
value="{!a.BillingState}"/>
<apex:column headerValue="Phone" value="{!a.Phone}"/>
<apex:column headerValue="Website" value="{!a.Website}"/>

118

(
</apex:pageBlockTable>
</apex:pageBlockSection>
<apex:pageBlockSection title="Results" rendered="{!showmsg==false}">
<apex:pageBlockTable value="{!listAccounts}" var="a">
<apex:column headerValue="Account Name" value="{!a.name}"/>
<apex:column
headerValue="Billing
State/Province"
value="{!a.BillingState}"/>
<apex:column headerValue="Phone" value="{!a.Phone}"/>
<apex:column headerValue="Website" value="{!a.Website}"/>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
+ 6/6 B
public class InterviewTwo_controller{
public list<Account> listAccounts{get;set;}
public string searchString {get;set;}
public boolean showmsg{get;set;}
public InterviewTwo_controller(){
listAccounts=new list<Account>();
showmsg=false;
}
public pagereference displayAccounts(){
String AccountQuery = 'select id, name,BillingState,Phone,Website from Account';
if(searchString != '' && searchString != null)
AccountQuery = AccountQuery + ' where name LIKE \'%' + searchString+'%\' ';
listAccounts=database.query(AccountQuery);
if(listAccounts.size()>0 && listAccounts!=null)
showmsg=false;
else{
ApexPages.Message errMsg = new ApexPages.Message(ApexPages.Severity.Warni
ng,'No Accounts Found');
ApexPages.addMessage(errMsg);
showmsg=true;
}
return null;
}
119

(
Create the Visualforce tab called
with this tab

+ 6 /6 and override the above visualforce

Click on the Interview Two tab

Enter the string Osmania in Search box and click on the Search button, then all the
accounts started with the Osmania will be automatically populated in the Results
section

120

(
*
Create the Visualforce page with following code
Page Name:
*

+ 6B/
-

<apex:page controller="showSelectdAccounts" sidebar="false">


<apex:form >
<apex:sectionHeader title="Interview Three"/>
<apex:pageblock >
<apex:pageblockButtons >
<apex:outputPanel >
<apex:CommandButton value="Show Selected Accounts" status="status"
action="{!ShowSelected}" rerender="spblock" />
</apex:outputPanel>
<apex:actionStatus startText="Please Wait..." id="status" />
</apex:pageblockButtons>
<span ><b> All Accounts </b> </span>
<span style="padding-left:550px;"><b> Selected Accounts </b></span>
<apex:pageblockSection columns="2">
<apex:pageblockTable value="{!lstWrapper}" var="Ewrap">
<apex:Column headervalue="Selected">
<apex:inputCheckbox value="{!Ewrap.selected}"/>
</apex:Column>
<apex:Column headervalue="Account Name">
<apex:outputfield value="{!Ewrap.Acc.name}"/>
</apex:Column>
<apex:Column headervalue="Phone">
<apex:outputfield value="{!Ewrap.Acc.phone}"/>
</apex:Column>
</apex:pageblockTable>
<apex:pageblockTable value="{!selectedAcc}" var="EAcc" id="spblock" >
<apex:Column headervalue="Account Name">
<apex:outputfield value="{!EAcc.name}"/>
</apex:Column>
<apex:Column headervalue="Phone">
<apex:outputfield value="{!EAcc.phone}"/>
</apex:Column>
</apex:pageblockTable>
</apex:pageblockSection>
</apex:pageblock>
</apex:form>
</apex:page>

121

(
6

public with sharing class showSelectdAccounts {


public list<Account> lstAcc{get;set;}
public list<Account> selectedAcc{get;set;}
public list<wrapper> lstWrapper{get;set;}
public boolean noAcc{get;set;}
public showSelectdAccounts(){
lstWrapper = new list<Wrapper>();
noAcc = false;
lstAcc = [select id,name,phone from Account];
wrapper objwrap;
for(Account objA:lstAcc){
objwrap = new Wrapper();
objwrap.Acc = objA;
lstWrapper.add(objwrap);
}
}
public void ShowSelected(){
selectedAcc = new list<Account>();
selectedAcc.clear();
for(Wrapper objWrap:lstWrapper){
if(objWrap.selected){
noAcc = true;
selectedAcc.add(objWrap.Acc);
}
}
if(!noAcc){
system.debug('8888888'+noacc);
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO,'No
Account Selected'));
}
}
public class wrapper{
public boolean selected{get;set;}
public Account Acc{get;set;}
}
}
Create the Visualforce tab called
with this tab

+ 6/

and override the above visualforce

122

Click on Interview Three tab

Check the checkbox in the selected column and click on Show Selected Accounts
button, then those selected accounts will be automatically populated in the Selected
Accounts section

123

(
*
Create the Visualforce page with following code
Page Name:
*

+ 6B
-

<apex:page controller="InterviewFourClass" sidebar="false">


<apex:form >
<apex:sectionHeader title="Interview Four"/>
<apex:pageblock tabstyle="Contract" title="Accounts with Contacts">
<apex:pagemessages />
<apex:repeat value="{!lstAcc}" var="EAcc" >
<apex:pageblockSection title="{!EAcc.name}" columns="1">
<apex:pageblockTable value="{!EAcc.Contacts}" var="Econ"
columnswidth="25%,25%,25%,25%">
<apex:column headerValue="First Name">
<apex:outputText value="{!Econ.firstname}" />
</apex:Column>
<apex:column headerValue="Last Name">
<apex:outputText value="{!Econ.lastname}" />
</apex:Column>
<apex:column headerValue="Phone Name">
<apex:outputText value="{!Econ.phone}" />
</apex:Column>
<apex:column headerValue="Email">
<apex:outputText value="{!Econ.Email}" />
</apex:Column>
</apex:pageblockTable>
</apex:pageblockSection>
</apex:repeat>
</apex:pageblock>
</apex:form>
</apex:page>
+ 6
public with sharing class InterviewFourClass {
public list<Account> lstAcc{get;set;}
public InterviewFourClass(){
lstAcc = new list<Account>();
lstAcc = [select id,name,(select id,lastname,phone,firstname,email from Contacts),p
hone from Account];
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO,'this pa
ge was created ONLY one Query'));
124

(
}
}

Create the Visualforce tab called


with this tab

+ 6

and override the above visualforce

Click on Interview Four tab and which gives the list of accounts and all the contacts
that are associated with a that account.

125

(
*

Create the Visualforce page with following code


Page Name:
*

+ 6B +
-

<apex:page controller="InterviewFifthClass" sidebar="false" >


<apex:form >
<apex:pageBlock >
<apex:pageMessages />
<apex:sectionHeader title="Interview Five"/>
<apex:pageBlock title="All Accounts">
<apex:pageBlockTable value="{!lstacc}" var="l" >
<apex:column headerValue="AccountName" >
<apex:commandLink value="{!l.name}" action="{!click}"/>
</apex:column>
<apex:column
headerValue="Billing
State/Province"
value="{!l.BillingState}">
</apex:column>
<apex:column headerValue="phone" value="{!l.phone}">
</apex:column>
<apex:column headerValue="website" value="{!l.website}">
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:pageBlock>
</apex:form>
</apex:page>
InterviewFifthClass Code:
public with sharing class InterviewFifthClass {
public pagereference click() {
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO,'you clic
ked on Name...'));
return null;
}
public InterviewFifthClass (){
lstacc = [select id, name, BillingState,phone,website from account];
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.INFO,'Sele
ct an Account by Clicking its Name.'));
}
public List<account> lstacc { get; set;}
126

(
}
Create the Visualforce tab called
with this tab

+ 6

+ and override the above visualforce

Once we click on the Interview five tab, then all the accounts will be populated in table
format which are we can clickable.

127

(
7;

/ :&

Document ID: DOC0001


Author(s):

Capital Info Solutions

Reviewer(s): Capital Info Solutions


Approver(s): Sateesh Reddy M
% .7#

The Force.com Migration Tool is a Java/Ant-based command-line utility for


moving metadata between a local directory and a Salesforce organization.
Migration tool is useful for migrating large scale or repetitive changes between
environments.
7#

Development projects where we need to populate a test environment with large amounts
of setup changesmaking changes with an automated script is far faster than entering
them by hand.
Deployments where we need to change the contents of files between organizations.
Multi-stage release processesa typical development process requires iterative building,
testing, and staging before releasing to a production environment
We can retrieve metadata from sourceenvironment, make changes, and deploy our
changes to destination environment. If we need to repeat this process, it is as simple as
calling the same deployment target again.
Prerequisites
Prerequisites for using Force.com Migration Tool:
Before using Force.com Migration Tool, Java and Ant must be installed correctly.
Installations
Installing Java:
In a Web browser, navigate to http://java.sun.com/javase/downloads/index.jsp and
install the latest version of the Java JDK.
Verify Java Installation:
To see if we have Java installed:
In command prompt, type java -version and press Enter.

128

(
The output should look something like the following:
java version "1.5.0_01"
Java(TM) SE Runtime Environment (build 1.5.0_01-b06)
Java HotSpot(TM) Client VM (build 1.5.0_01-b06, mixed mode)
The Force.com Migration Tool works with Z + +
%F%
have an earlier version, we will need to installJava 1.5.x or later.
Ant Installation:

. If we

Download Apache Ant +


% %
. http://ant.apache.org/bindownload.cgi.
This directory will be known as ANT_HOME.
Add the bin directory to your path. (Only the bin and lib directories are required
to run Ant.)
If we are using a Windows operation system, create an ANT_HOME environment
variable and set the value to where we have installed Ant. Also create a
JAVA_HOME environment variable and set the value to the location of your
JDK.
Verify Ant Installation
% In the command prompt, type

2+

and press Enter.

The output should look something like the following:


Apache Ant version 1.8.2 compiled on December 13 2006
Installing the Force.com Migration Tool:
To download and install the Force.com Migration Tool:
% Log into a Salesforce organization on your deployment machine.
% Click
>
>5 +
>/
, and then click
% .
7#
/ .
Q% Save the .zip file locally and extract the contents to the directory of your
choice.
% Copy ant-salesforce.jar and paste into your Ant installation's lib directory. The
lib directory is located in the root folder of your Ant installation.
Go to control panel and click on System
In System properties window, goto Advanced tab and click on Environment
variables.
Create the following two environment variables if they are not existing.
ANT_HOME value is (your apache-ant-1.8.2 installed path)
JAVA_HOME value is (your jre1.6.0_02 installed path)

129

GeneralSteps
The general procedure we will follow when using the Force.com Migration Tool
to copy metadata from one Salesforce organization to another is:
1. Enter credentials and connection information for source Salesforce organization
in build.properties
2. Create retrieve targets in build.xml
3. Construct a project manifest in package.xml
4. Run the Force.com Migration Tool to retrieve metadata files from Salesforce
5. Enter credentials and connection information for destination Salesforce
organization in build.properties
6. Run the Force.com Migration Tool to deploy metadata files or deletions to
Salesforce
Fetching Data
/
.
+
.
Create a folder say some Migration folder and create the following in it.
1) build.properties.txt
2) build.xml
3) Create a new folder with the name say retrieveSource.
.
4) In the retrieveSource folder, create an xml file with the name package.xml.

1) Build.properties file should look like this


Give userid, password, server url like below
username = user@gehc.amer.sprintdev

130

(
password = password12jSZQVS7erefdUMfjcoFSgr7Mqx
serverurl = https://test.salesforce.com

2) Build.xml file should have the following


LX22
+
.
<target name="retrieve">
<mkdir dir="retrieveMetadata"/>

22M

<setproxy proxyport="80" proxyHost = your proxy proxyuser =


'username' proxypassword = 'password' />
<sf:retrieve
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}"
retrieveTarget="retrieveMetadata"
unpackaged="retrieveSource/package.xml"
pollWaitMillis="10000"
maxPoll="100"/>
</target>

LX22 5

"

22M

<target name="deploy">
<setproxy proxyport="80" proxyHost = your proxy proxyuser =
'username' proxypassword = 'password' />
<sf:deploy
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}" deployRoot="retrieveMetadata" />
</target>

LX22 5

. -

22M

<target name="remove">
<setproxy proxyport="80" proxyHost = your proxy proxyuser =
'username' proxypassword = 'password' />
<sf:deploy
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}" deployRoot="remove" />
</target>

Finally the build.xml file should look like below.

131

3) Package.xml file should contain all the metadata information like objects, classes,
triggers etc that needs to be migrated or retrieved.
In the source environment, just create a new field or class or trigger to verify the
migration is successfully taken place in the destination environment.
In the below example, the following are created in the source environment
1) MigrationTest_Field --- a text field in account object
2) MigrationTestClass --- a new class
3) Top_X_Designation__c --- custom object
Keep all the data that needs to be retrieved from source environment in <types>
like this.
<types>
<members>Account.MigrationTest_Field__c</members>
<name>CustomField</name>
</types>

To retrieve all the triggers or classes, put *. Like this


<types>
<members>*</members>
<name>ApexTrigger</name>
</types>
Finally the package.xml file should look like this

132

We need to go to the command prompt and type the commands to do the following
1) Retrieve to retrieve the data from source environment
2) Deploy to deploy the data in to the destination environment
Go to folder directory in the command prompt where the Migration folder is created.
Type the following command
Type the command [
+ $ to fetch the data from the source environment in to
the folder.
After the executing the above command, the below details are visible in the command
prompt.

133

Go to the source folder and verify whether all the data mentioned in the package.xml is
fetched from the source environment. We will find a folder called retrieveMetadata that
contains all the retrieved data from the source environment.

Now, give the credentials of the destination environment in the build.properties file. And
type the following command.
Deploying Data
/ "
+
Type Ant deploy in the command prompt

Now after the files are deployed, we will get the following info in the command prompt.

Now go to the UI and check whether all the files are migrated to the destination
environment.
With this example, we can see all the above provided data will be migrated and available
in the destination environment.

134

(
Integrating with Subversion
Using the Subclipse IDE we can login to SVN repository and checkout the branch which
we have latest code and metadata in to a local directory.
As mentioned in the Fetching data section we can run deploy command to deploy the
contents which are mentioned in the package.xml will get deployed to destination
environment.

Once we run the command , the following screen will illustrate the data being copied to
the destination path.

7#

Login into Source Sanbox and go to the followng path


Your name
App Setup
Deploy
Click on the Outbound Change Sets Click on New button

135

2. Enter the Name, Description of Change set and click on Save button

3. Click on Add button in the Change Set Components section to add the
Components

136

4. Choose the Component type and select the components which we want to
migrate by clicking on checkbox and click on Add to Change Set button

5. If we want to migrate the apex triggers, then select the component called
Apex Trigger from the component type drop down list

137

6. All the triggers in the Organization will be automatically populated, select the
checkbox beside the trigger name which we want to migrate into another sanbox and
click on Add to Change Set button

7. Click on the Upload button

138

(
8. Select the Target Organization (Destination Organization) and click on
Upload button

9. Once we click on the upload button in the above window, then the salesforce
will intimate to the user saying that Your Outbound change set has been successfully
uploaded through an email

Sorce

After getting the above email, login into destination organization and go to the following
path
Your name
App Setup
Deploy
Click on the Inbound Change Sets

1. Click on the Change Set Name from the following window which we uploaded
in the Source Organization
139

2. Click on Validate button to validate the deployment

3. Click on the Deploy button if the validate succeeded for deploying into
destination organization

140

The following window will give the status as Succeeded in the Deployment History
section if the deployment was successful.

7#
&

Before doing all the following things, Install Java JDK or JRE into computer
% .

#
141

(
Double click on eclipse.exe file and Go to Help Software Updates

Click on the Add Site button in the following screenshot

Click on Add
Site button

Add the URL "http://www.adnsandbox.com/tools/ide/install/" in the Location, then click


"OK."

142

(
After we add the site, Eclipse will download the list of available plugins and display them
in the Available Software dialog.

Check the box next to the Force.com IDE plugin then click "Next"

In the Install Details dialog, click "Next," then accept the terms and click "Finish."
Eclipse will download and install the Force.com IDE and any required dependencies.
When installation is complete, Eclipse will prompt to restart. Click "Yes."
Once Eclipse restarts, select 8 - 6 M :
"Force.com", then click "OK."

M :

and select

143

/ 4 #

% .

Go to the Navigator and click on right click button and follow the path below:
New Click on Force.com Project

144

Enter the following details and click on the Next button


1.
2.
3.
4.
5.
6.

Project Name
User name
Password
Security Token(Note: We have to enter only Security token)
Environment Select Production/Developer Edition or Sandbox
Give Proxy Settings(Select Direct Connection to the Internet)

145

Choose the option Selected metadata components and click on the Choose button

Click on the Select All button to get all the metadata components and click on OK
button

146

(
Click on Select
All button
1

2
Click on OK
button

Click on Finish button in the following screen shot

147

Once we click on Finish button, a small window will come that gives the Progress
Information
After completing all the above steps, we can able see all the metadata components that
are there in developer edition.
The following screen shot gives the information about the all the metadata components. It
will display all the objects, page layouts, triggers, Vf pagesetc that we have created in
Developer edition
Note: Click on + symbol to get all the components under that section
Ex: Click on + symbol beside the Objects to get all the standard and custom objects in
the developer edition

148

7#

# .

-1

-1
Select the metadata component (Ex: Objects) from one sandbox(i.e Source Sanbox).
Click on the Right Click button and go the following path
Force.com Deploy to Server.

149

Enter the following Destination Sandbox details in the next screenshot


1.
2.
3.
4.

User Name
Password
Security Token
Select the Environment

Note: I have taken the project with the user name: anilreddym11@gmail.com (Source
Sandbox) and I am migrating the metadata from this sanbox to sandbox with the user
name: anil.male@wipro.com (Desination sandbox)
Click on the Next button

150

Enter the Destination


sandbox details here
1

2
Click on Next
button here

Uncheck Destination archive check box and click on the Next button

151

(
Q The following screenshots displays all the objects
Green colour marked indicates that those objects are not there in the desination
environment
Yellow colour marked indicates that those objects is already there in destination
environment and it will ask for overwrite.
Click the Validate Deployment button to validate the deployment, if it success then
Then click on Next button

Click on the Finish button


#

7#

#.

-1

-1

1"

We need to take the two projects (i.e Sandboxes). First one is Source Sandbox and
second one is destination sandbox
Anil Dev 1=Source Sanbox
Anil Dev 2=Destination Sanbox

152

Select two projects and click on right click button and go to the following path
Compare with Click on Each Other

The following screenshot gives the all the components that are different each other
(i.e the components that are different from source sandbox and destination sandbox)
Click on symbol + sign beside any component (Ex: Objects) for seeing all objects

153

1. Double click on component (Ex: Account Object)

The following screenshot says us about the differences from source sandbox to
destination sandbox for Account Object
The blue colour marked content shows that the component that are there in Anil Dev
1 and which is not there in Anil Dev 2

154

Use the following buttons at right side of Text Compare window for moving the data
from left to right and figuring the differences from top to bottom or vice versa.

Copy all from left to right

Copy all non-conflicting changes from left to right

Copy current change from left to right

Copy current change from right to left

To move into Next Difference


155

To get the Previous Difference

To move into Next Change

To move into Previous Change


The following screen shot shows that the Object called Customer that is there in Anil
Dev1 sandbox. And moving that object into Anil dev 2 sandbox

Click on the

button to copy current change from left to right.

156

Click on Ctrl+S to save the differences into Anil Dev 2 sandbox.


The following window shows the Progress Information

After Completion of above progress, make sure that no errors found then login into the
Anil Dev 2 sandbox and check the Customer object is created or not.
&

E
-1

#
-

( 6
.5

. +

-1

.
-1

-1
%

,
157

(
+ 6I
% 8
"
9
Ans: We have three types of the controllers
I.
Standard Controller
II.
Custom Controller
III.
Controller Extensions
A Visualforce controller is a set of instructions that specify what
happens when a user interacts with the components specifiedin associated Visualforce
markup, such as when a user clicks a button or link.
Controllers also provide access to the data thatshould be displayed in a page, and can
modify component behavior.
- A standard controller consists of the same functionality and logic
that is used for a standard Salesforce page. For example, if we use the standard Accounts
controller, clicking a Save button in a Visualforce page results in the same behavior as
clicking Save on a standard Account edit page.
.
A custom controller is a class written in Apex that implements all of
a page's logic.
If we use a custom controller, we can define new navigation elements or behaviors, but
we must also reimplement anyfunctionality that was already provided in a standard
controller.
A controller extension is a class written in Apex that adds to or
overrides behavior in a standard or custom controller.Extensions allow us to leverage the
functionality of another controller while adding our own custom logic.
% 8

.
A custom controller is a class written in Apex that implements
all of a page's logic.
If we use a custom controller, we can define new behaviors, but we must also
reimplement anyfunctionality that was already provided in a standard controller.
Q% 8
1 6
8 4 6 +
9
Workflow Rules and Approval Processes can be used together
8 4 6
Are triggered upon Save
Consist of one set of criteria and actions

Can be modified or deleted

+
Are triggered only when a user clicks
Submit for Approval button
Consist of multiple steps
Have an entry criteria, step criteria and
step actions
Have Initial submission actions, rejection
and approval actions and actions for each
step
Some attributes cant be modified ,
processes must be deactivated before they
can be deleted
158

(
% 8
- /" 9
Ans: Record types used to display different picklistvalues and page layouts to
different users based on their profiles
F% 0 + "
. .
- /"
"
! 9
Yes, we have created Record Types and we have done Page Layout Assignment
also

% 0 6 . 4
- "
9
By using the Profiles.
Go to the particular profile and by using Record Type Settings we can make the
Record Type as a default
G% 8
.
9
Customer Portal: A salesforce.com Customer portal similar to a Self Service
Portal in that it provides an online support channel for your customers allowing
them to resolve their inquires without contacting a customer service representive
% / .
; +
<. 9
Total number of SOQL queries issued
Total number of records retrieved by
SOQL queries
Total number of records retrieved by
SOQL queries
Total number of records retrieved by a
single SOSL query
Total number of DML statements issued

200
50000
20
200
150

% 8
9
Ans: An Apex annotation modifies the way a method or class is used, similar to
annotations in Java.
@Deprecated
@Future
@IsTest
@ReadOnly
@RemoteAction
'% 8
H /
9
Ans: Use the isTest annotation to define classes or individual methods that only
contain code used for testing your application.
%0 6. "
6
9
Ans: Any number of controller extensions
%8
9
Lists
Maps
Sets
159

(
Q% 8
1 6
-7 9
Ans: A set is an unordered collection of primitives or sObjects that do not contain
any duplicate elements.
A map is a collection of key-value pairs where each unique key maps to a single
value. Keys can be any primitive data type, while values can be a primitive, sObject,
collection type or an Apex object.
%8
"
6
#+
) " -*
7 9
Keys Primary Data Types
Values Primitive, sObject, Collection Type or an Apex object
F% 8
"
-1
" D
#9
Full Sanbox and Configuration only Sanbox
Full Sanbox is Production environment
Configration Sanbox Test Sanbox
%8
1 6
6
#
- 6
#
4 "6 - 9
Ans: Use the with sharing keywords when declaring a class to enforce the sharing
rules that apply to the current user.
Use the without sharing keywords when declaring a class to ensure that the sharing
rules for the current user are
enforced
G% 8
1 6
/ ## % 6 - / ## % -9
Ans: Trigger.new : Returns a list of the new versions of the sObject records
Note that this sObject list is only available in insert and update triggers, and the
records can only be modified in before triggers
Trigger.old:
Returns a list of the old versions of the sObject records
Note that this sObject list is only available in update and delete triggers.
%8
.
#9
Ans: custom setting that provides a reusable set of static data that can be accessed
across your organization. There are two types of custom settings
I.
List Custom Settings
II.
Hierarchy Custom Settings
%8
1 6
< 4
-7
29
Lookup Relationships
Master Detail Relationships
We can create upto 25 lookup We can create 2 Master Detail
Relationships
relationships
Lookup can be create if records already Master Detail cannot be created if
exists
records already exists
If we deletes the Parent record, then the If we deletes the Parent record, then
Childs will not be deleted
the Childs will be deleted
automatically
Mandatory
Optional

160

(
'% 8

1 6
9
A collection of settings and permissions that define how a user accesses
records. Profiles Control a users permissions to perform different functions in
Salesforce.
A profile can have many users, but a user can have only one profile.
Controls the level of visibility that users have to an organization's data

6
6
# #
9
Ans: No, because while creating the user, selection of profile is mandatory thing
%0 6. "6 " 6
. 4
- \
-9
Ans: There are three ways to make the field required
While creating the field
Using Page Layouts
And using validation Rules
FLS(doubt)
Q% 0 6 . " 6 " 6
*
# 9
Ans: There are the two ways to create a Visualforce page
By using the URL
By using the path Setup ->Develop Pages
%8
# .
9
Ans: Assignment Rules are used to automate organizationslead generation and
support processes.
Lead Assignment Rulesspecify how leads are assignedto users or queues as
they are created manually, captured from theweb, or imported via the lead import
wizards.
Case Assignment RulesDetermine how cases are assignedto users or put into
queues as they are created manually, using Web-to-Case.
F% 8
"
9
Master Detail
Lookup
Many to Many
Hierarchical
%
6 E
.
9
Ans: As per now, Salesforce doesnot allow to delete any user, however we can
deactivate the user
G% 0 6
7 " 7 "
1 6
1! 9
Ans: Create one custom object, which should have autonumber as unique
identification and create two Master - Detail relationships for this object. And this
Object is called as Z
1! %
%8
:1!
. 9
Ans: Cross-object formulas can reference merge fieldsfrom a master (parent)
object if an object is on thedetail side of a .
2. we can
reference fieldsfrom objects that are up to ten relationships
We can able to insert related Object data into a formula
%0 6
- / 1
E
Ans: By profiles we can hide a tab for a user
161

(
Use Tab Hidden setting for tab hide
Q'% 8
59
Ans: External IDs are used when we interacting with an external systems. It will
act as unique record identifier. We can define 3 external ID fields per object.
These are the data types of fields
Number
Text
Email
Q %0 6 . # 6
# #
/ "
9
Ans: Click on the Tab and go to the Tools section, we can find the Merge option

Click on
MergeAccounts

Q %0 6. "6 " 6
- ". 9
Ans: There are three ways to do deployment
a. By using Change Sets
b. By using Force.com IDE tool(Eclipse)
c. By using Force.com Migration toolkit

QQ% 8

"

#6

- #9

a. Bulkify your Code: Bulkifying Apex code refers to the concept of making
sure the code properly handles more than one record at a time. When we
try to load the bulk of the records using the Data Loader, then we make
sure that code will satisfy.
b. Avoid SOQL Queries inside FOR Loops: When queries are placed inside
a for loop, a query is executed on each iteration and the governor limit is
162

(
easily reached. Instead, move the SOQL query outside of the for loop and
retrieve all the necessary data in a single query.
c. Avoid Multiple Triggers on the Same Object: Write the Single trigger on
the each object and write the logic in the classes and call that classes in the
triggers.
d. Use of the Limits Apex Methods to Avoid Hitting Governor Limits
e.
Q %8

+ -0 - - # 5
7* -

% .9

Model view controller (MVC) design pattern is the one of the most popular design
pattern which contains three modules.
a. Model
b. View
c. Controller
7 What schema and data does salesforce uses to represent the system
completely. In salesforce, we can say that sObjects are the model. Ex: Sobjects,
Apex Classes
* 6 How the schema and data is represented. Visualforce is used to present the
data to users.
Ex: Pages, Components
How the interface actions. Controllers are used to perform the actions
whenever users interact with Visualforce. Ex: Standard, Custom(Apex)
QF% 0 6 . "
- 6
"
9
Ans: Any number of records
Q %8
5
.
5 1 Ans: The following are the Data Components in the dashboards
Horizontal Bar Chart
Vertical Bar Chart
Line Chart
Pie Chart
Donut Chart
Funnel Chart
Gauge Chart
Metric
Table
Notes: 1.The Components of the dashboard that use the Grand Totals is 7
; #
QG% 0 6

# 9

163

(
Ans: We have a attribute called action in the <apex:commandbutton> tag in the
VF page.
<apex:commandButton action="{!save}" value="Save" id="theButton"/>
Q %0 6.
+ # 6
/
9
Ans: 75%
Q %8
.
-9
Ans: A read-only field that derives its value from a formula expression which we
define. The formula field is updated when any of the source fields change.
'% 7
.
- 9
Ans: Accounts, Contacts, Opportunities, Leadsetc (all standard and custom
objects)
%8
8 4 69
Ans: Task
Email Alert
Field Update
Outbound Messages
%
6 #
8 4 69
Ans: No
Q% 8
* 9
Ans: Validation Rules verify that the data a user enters in a record meets
the standards we specify before the user can save the record
Validation rule also includes the error message to display to the user when
the rule returns a value of true due to an invalid value
% 6 - D
+ GF] + # (
6 . +
.
-1
-1 9
Ans: Yes, we can move a class from one sandbox to another sandbox. But if we
want to move a class from sandbox to production environment we need to have a
Test Class with a minimum of code coverage should be 75%
F%
6
+ 59
Ans: No
%8
.
.
#
-9
Ans: getAll()
G% 8
+
1
/ ## 9
Ans: Trigger.new, Trigger.old
Trigger.NewMap, Trigger.OldMap
isInsert, isUpdate, isDelete, isBefore, isAfter, isUndelete
%8
, 4 / ## 9
Ans: All the triggers are bulk triggers by default, and can process multiple records
at a time. We should always paln on processing more than one record at a time.
%8
1 6
#+ # 6
#
- 6
#
6
#
9
Ans: The class with sharing means we are enabling the access to the profiles
The class without sharing means we are disabling the access to the profiles.
F'%
6
7 9
Ans: Yes, we can put list in the Map. Please find the code below
Map<Id, List<Opportunity>> MapList=New Map<Id, List<Opportunity>>();
164

(
F %8
.. "
-9
Ans: A read-only field that displays the sum, minimum, or maximum value of a
field in a related list or the record count of all records listed in a related list.
F %0 6
6 . .
% .9
Ans: In force.com we have a concept of scheduling the apex. We can write a
block of code which can be scheduled at particular point of time in a week
FQ% 8
"
##
+
9
Ans: An event in a trigger refers to a situation when the trigger gets fired.
,
Before inserting the record into the database, the trigger will be
fired.
,
E Before updating a record which is fetched from database, the
trigger will be fired.
,
5
Before deleting the record, trigger will be fired.
After inserting a newly entered record into database, the trigger will
be fired.
E After modifying the record and once it is saved to database, the
trigger will be fired.
5
After deleting a record, if user needs to perform any action, he can
fire the trigger using this after delete event
E Once the record gets deleted, it will be sent to recycle bin. So, a
trigger can be fired when user is moving back from recycle bin to its respective
object and the transaction is done.
F %8
"
/ ## 9
Ans: There are two types of triggers.
Bulk Triggers
Recursive Trigger
+ / ## A Trigger that creates a new record as part of its processing logic;
however, that record may then cause another trigger to fire, which in turn causes another
to fire, and so on.
FF% 8
Ans:

1 6
- (
9
- components in visual force page can show or hide by using render
If we want to refresh partial page in Visual force page we have to use
rerender
By using this we can convert entire visual force into PDF, The syntax
is
Render as = pdf
F %8
1 6
/ ##
- 8 4 69
Ans: 8 4 6 Inbuilt functionality, used on single object
/ ##
Used for complex business process in which multiple Objects can
handle.
Ex: Using Workflow, Based on the criteria we mentioned on the parent record, we
can do field update on the parent only but not on child object
Using Triggers, Based on the criteria we mentioned on the parent record, we can
do field update on child also

165

(
FG% 0 6 . "
6
.
-9 8
6
6
. 9
Ans: we can enter upto 3900 characters in the formula field. If we exceed the
limit, then it will give the compilation error.
F %
6
.
-6
.
-9 8
1
3 9
Ans: Yes, we can include one formula field with in another formula field. It will
calculate the formula field characters which we included in formula field.
F %8
*
# 9
Ans: L
M A component that provides support for invoking
controller action methods directly from JavaScript code using an AJAX request.
An < apex:actionFunction > component must be a child of an < apex:form >
component.
&
L
M This component Is used for displaying different
values depending on whether its in progress or completed.
L
M A component that adds AJAX support to another
component, allowing the component to be refreshed asynchronously by the server
when a particular event occurs, such as a button click or mouseover.
L
M This componentspecifies a timer that sends an Ajax update
request to Force.com according to a time interval that we specify.
'% 8

1 6
,< &) ?@ - &E<< ?@9
Both Determines if an expression has a value and returns TRUE if it does
not. If it contains a value, this function returns FALSE
,< &) ?
@ The expression allows both number and text fields.
,
.1
&E<<?
@ Here the expression allows only number fields.
: " .1
-

%8

6
a.
b.
c.
d.
e.

#5

<

- 9

Insert
Update
Upsert
Delete
Export

%8

. . . 3
5 #
*
1
9
Ans: The maximum response size when creating a PDF must be below 15
MB,
being rendered as a PDF.
Q% 8
: 9
Ans: The order of execution gives the what are the events that Salesforce
performs in order.
Executes all before triggers
System validations are performed.
166

(
Custom Validations are performed
Saves the record but doesnt commit.
Executes all after triggers
Executes the assignment rules
Executes the workflow rules.
Commits to the database
%
6
#
"
. < 4
.
2 9
Ans: Yes, we can change the Lookup relationship to master- detail relationships.
F% 8
7
25
-"
1! 9/
6
+
9
Ans: First we have to create the lookup relationship. Next update the existing
records with some value in the look up field. Now change the data type from
lookup to master-detail
%8
1 6
% . % .9
Ans: Force.com is the platform used to develop the applications in the salesforce
Salesforce.com is keyword used to search anything.
G% 8
1 6
5
< - .
8 3 -9
5

<

83 -

It supports all the Standard Objects It Supports Accounts/Contacts, Leads,


and Custom Objects
Solutions and Custom Objects
Supports upto 1 million records

Supports upto 50,000 records

Duplicates will be allowed

Duplicates will not be allowed

Have Batch Size

Dont have any batch size

%8
:85D 9
Ans: OWDs is used for restrict the access.Organization-wide default sharing
settings give you a baseline level of access for each object and enable you to
extend that level of access using hierarchies
%8
#
9
Sharing rules represent the exceptions to your organization-wide default
settings. Using sharing rules we can extend the access for the records.
G'%
+ 6
.
6 .
#+
:85D 6 49
View All and Modify All permissions
G %8

.
9
A permission set is a collection of settings and permissions that give users
access to various tools and functions. The settings and permissions in permission
sets are also found in profiles, but permission sets extend users' functional access
without changing their profiles.

167

(
.

Develop a sample project which is useful to Educational system with following modules
and make the relationship between these modules as per your requirement.
Here I am providing a high level document for this application, prepare a business
requirement document and develop the application
!
%

: 8 4

%0# < +
Q% .
%

= 7

: 8 4
The App runs on Cloud setup.
This application can be capable of handling number of transactions that updates
the data.
This application will send SMS/VMS/Emails and online chat through Chatter
Integration.

%0# < +
\
.
Following are the high level modules identified in Web Application:
\

-7 -

2.1) Student Module


2.2) Academic Performance Module
2.3) Extra-Curricular Activities Module
2.4) Attendance Record Module
2.5) Fee Module
2.6) Library Information Module
2.7) Parent/Guardian Information Module
2.8) Staff Information Module
2.9) Staff Performance Analysis Module
2.10) Attendance Management Module
2.11) Fee Management Module
2.12) Financial Accounting Module
2.13) Payroll & Leaves Processing Module
2.14) Inventory Module
2.15) Library Management Module
2.16) Gate Security Module
2.17) Front Office/Reception Module
2.18) Exams Management Module
2.19) Curriculum Management Module
2.20) Operational features Module
168

(
2.21) Automatic Timetable Builder Module
2.22) Certificate Designer/Document Mail Merge Module
2.23) Scheduler Module
2.24) Hostel/Cafeteria/Mess Module
% 0#

7 -

Comprehensive personal profile including citizenship details for foreign/NRI


students, special abilities
Information required/mandated by Boards of Education, information captured
during admission procedure
Details of previous institution(s)/academic performance
Certificates submitted, details of certificates issued, duplicates, etc.
% 0#

- .

7 -

Current academic year results for all exams, performance analysis across exams
Complete student history (across multiple academic years)
Charts and graphs to give better picture of students performance in various
subjects and also with respect to other students
Detailed/ Summary reports for term/ semester/ month/ year
Graphs
Drill-down analysis
%Q 0 #

7 -

(Sports performance, special talents, hobbies, awards, etc.)


% 0#

-7 -

Fast attendance capture (Daily/Weekly/Monthly update options)


Period, Subject, Day-Wise attendance options
Detailed/Summary reports for term/semester/month/year
Leave history with complete details including submission of leave letter, type of
leave availed, eligibility, etc.
Graphs
%F 0 #

7 -

Fee collection and payment history


Special fees, detailed break-up, transport fees, etc.
Dues statement, Concessions and other charges
Medical Records
Complete Medical Records
169

(
Illnesses or details of special attention required, allergies, etc.
Emergency numbers (personal physician/hospital) to contact for special care
% 0#

<1

"

7 -

Complete track of students borrowings and returns


Analysis of reading habits
Online Public Access Catalog (OPAC)
Dues, fines, etc. linked to fees

%G 0 #

=;

7 -

Comprehensive information regarding local guardian/contact person and parents


including
multiple addresses, citizenship details, financial information,
professional details and other information useful for profile analysis
% 0#

7 -

Unlimited user-defined grouping facility to categorize staff according to function


(Teaching/Non-teaching/Driver, etc.)
Comprehensive bio data including detailed career record, past assignments
Fast attendance capture (Daily/Weekly/Monthly update options)
Day attendance marking (via PIN/batch mode)
Detailed/Summary reports for term/semester/month/year
Leave history with complete details including submission of leave letter, type of
leave availed, eligibility, etc.
Dashboards
Detailed reports for late-coming/tardiness/absence
Fingerprint-based biometric attendance (optional at extra cost)
Complete Payroll with categorized allowances and deductions (including standard
deductions), Leave management
Tracking loans to employees
Group/Other insurance
% 0#

"

7 -

Comprehensive analytical reporting on various parameters inclusive of


performance of students under tutelage to gauge performance of teaching staff,
staff appraisal reports
170

(
% '0#

# .

7 -

Fast attendance management (daily/weekly/monthly updates) both online and


offline
Option to show attendance details in Progress Card for students
PIN-based attendance marking for staff
Linked to Payroll and Leave Management for automatic update of permissions,
leave status, loss of pay, etc.
%

0#

# .

7 -

User-defined payment schedules and collection modes


Unlimited heads of fee
Slab-wise collection option
Class/category/student-specific fee settings
Linked to accounts (post consolidated to single account or individually to multiple
accounts)
Configurable fee heads/categories
Receipt Tracking
Single point entry and reference
Defaulters list (class/section, category, all)
Challan/Payment Advice printing
Comprehensive reporting

0#

#7 -

Supports all voucher types (including self-balancing journal)

Bank Reconciliation
Trial Balance
Profit and Loss (Income and Expenditure)
Balance Sheet
MIS reporting including month-wise income/expenditure comparisons

Unlimited ledgers, accounts and sub-accounts


Cost Center Reporting
Consolidated books across multiple organizations
Linked to Payroll, Fees, Inventory
Drill-down view
Multi-level Ledger
Blocking of post-dated/back-dated entries/Auto-freeze

% Q0#

"

U< +

#7 -

171

Unlimited staff categories


Category-wise rules and defaults
Category-wise allowances and deductions
Category-level default settings
Employee-level overrides for all settings
IT reports/documents including Form 16
Professional Tax
Allowances/Deductions as percentage of Basic/flat rate with ceiling options

Pay-slip printing
All Statements (Salary/Bank/Insurance/Professional Tax/PF)
Leave encashment
Configurable Permissions/Late penalties/Leave management rules

0#

"7 -

Indents
Purchase Requisitions
Quotations
Purchase Orders
Inwards and Outwards
Department-wise maintenance/Inter-departmental transfer
Item Tracing/Servicing
Stock Register and other standard reports
Linked to Security for Gate Pass/DC
Perishables/Consumables
Reorder reports
Categorized items

% F0#

<1

"7

# .

7 -

Tracking Issues/Receipts to Staff/Students/Other


Reservations
Unlimited types of Media/Categories
Support for standard Accession Number
Types of issue: Normal/Reference Only/Journals
Tracking late submissions/pending and penalties automatically appended to fees

Budgeting
Multiple Issue Cards
Journals/Subscriptions Tracking missing issues/renewals
%

0#

"7 -

Vehicle Log
Inward/Outward (Returnable/Non-returnable)
Issue/Track Gate Passes/Challans
Duty Register/Guard Register/Shifts
172

(
Keys
Events
% G0#

7 -

Correspondence Register
Follow up of absentees and recording reasons
Visitors/Appointments tracking
Complaints Register

0#

. 7

# .

7 -

Fast exam marks data entry (multiple filters/sorts)


Subjects with marks excluded from total
Combinations of marking schemes (including sub-exams)
Progress Card/Analytical performance reports
Benchmarking performance
Evaluate to Marks/Grades
Optional subjects
Ranking
Teachers observations and remarks
Toppers/Weak students
Comprehensive reporting
Print Hall Tickets

0#

.7

# .

7 -

Staff Lesson Plans (Daily/Weekly/Term/Yearly)


Tracking progress of Lesson Plans
% '0#

7 -

Staff Training/Self-appraisals
Master On Duty
Parent/Teacher Meetings
Minutes of Meetings
Parent/Child Events (Permission Slips/participants tracking)

0#

/.

1 ,

7 -

Constraints definition (Staff/Class-subject/Resource)


Combined classes
Manual editing with constraint checks
Daily substitution timetable for absentee staff (linked to attendance)

173

(
%
0#
7 -

=5

7 #

Design and print certificates with multiple fonts and colors


Create letters/documents and send to multiple recipients (students only, staff only,
parent/ guardians only, selected recipients, all)
ID Card Designer
Create ID cards for students and staff

Corporate Logo
Contact information, Emergency Numbers
Blood group
Multi-color high resolution (printer dependent)

% Q0#

7 -

Automatic reminders, meeting schedules


Notify self, selected list of users, or all users when a scheduled event occurs
Automatic scheduler activity includes tracking birthdays, posting follow-ups for
overdue
certificates, vehicle insurance reminders, etc.
Keep track of complete details pertaining to own/contracted student/staff transport
vehicles
Automatic reminders for payments/ renewals such as Insurance, Road Tax, and
Pollution check, etc.
Servicing and fuel costs analysis
Analytical reports to help with costing and budgeting
%

0#

Q% .

=7

7 -

Expense tracking
Resource utilization reports
Warden information
Rooms and availability
Link to Inventory for procurements/consumption-based reporting
= 7

Send Emails/SMS messages to parents/suppliers/other (SMS requires hardware at


extra cost)
Ad hoc messages/notifications
Fee due notices
Progress Card
174

Sample Explanation of student Module

Click on
results

175

(
Results
Page

176

Das könnte Ihnen auch gefallen