SlideShare une entreprise Scribd logo
1  sur  35
Télécharger pour lire hors ligne
Coding Apex Triggers on Chatter
Group Members
A case study in coding for collaboration
Carolyn Grabill
Salesforce.com
Software Development Engineer
@CarolynCodes
Safe harbor
Safe harbor statement under the Private Securities Litigation Reform Act of 1995:
This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties
materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results
expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be
deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other
financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any
statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services.
The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new
functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our
operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of any
litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in which we operate, our
relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our
service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to
larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is
included in our annual report on Form 10-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent
fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the Investor
Information section of our Web site.
Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently
available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions
based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these
forward-looking statements.
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Lunchforce brings the power
of Chatter to the real world.
Get the source: http://bit.ly/DF13Lunch
Lunchforce’s moving parts
User joins Lunchforce
Chatter group

Chatter Group
Member Trigger fires

Luncher__c record is
created for that User

Admin schedules
LunchMatch Apex

Scheduled Apex runs
matching algorithm,
posts results to
Chatter

Users see Chatter
posts, meet up for
lunch together
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Lunchforce’s Custom Objects

Junction Object
Junction Object
Records created by matching process

Luncher__c
Location Picker

Luncher__c
Time Picker

Lookup

Lunch_Match__c
Match Record

Lookup
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Chatter Group Member Trigger
CollaborationGroupMember fields
▪ CollaborationGroupId
• The Id of the Chatter group joined

▪ CollaborationRole
• Whether the User is Standard or Admin group member

▪ MemberId
• Id of the User joining the group

▪ NotificationFrequency
• Picklist – Daily, Weekly, Never, Post
Demo
▪ Example CollaborationGroupMember Trigger
• AddNewLunchers

▪ Trigger in action
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Lunchforce’s moving parts
User joins Lunchforce
Chatter group

Collaboration Group
Member Trigger fires

Luncher__c record is
created for that User

Admin schedules
LunchMatch Apex

Scheduled Apex runs
matching algorithm,
posts results to
Chatter

Users see Chatter
posts, meet up for
lunch together
Interfaces
▪ A template that defines methods, but does not implement them
▪ Apex class implements an interface by implementing its methods
▪ Schedulable is an interface built in to Apex
▪ Example:
global class scheduledLunchMatch implements
Schedulable {
global void execute(SchedulableContext ctx) {
goMatchGo();
}
}
Demo
▪ Example Schedulable Class
• ScheduledLunchMatch

▪ Scheduling a job in setup
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Problem: how do you maximize
new matches in a group of people,
when some of them have already
met?
Solution: sort the lunchers by how
many lunches they’ve already had.
Demo
▪ Example Comparable Class
• LuncherWithHistory

▪ Sorting a list of LuncherWithHistory records
• LunchMatcher
Lunchforce Technologies
▪ Using custom junction objects
▪ Triggering on Chatter Group Members
▪ Implementing an interface in Apex
• Schedulable
• Comparable

▪ Posting to Chatter from Apex
Posting to Chatter from Apex using FeedItem
▪ Represents an entry in the feed, such as changes in a record feed,
including text posts, link posts, and content posts.
▪ Example:
FeedItem fi = new FeedItem();
fi.ParentId = [object id]; //user, account, etc.
fi.Body = “Body of the post”;
insert fi;
Demo
▪ Example FeedItem creation
• LuncherWithHistory
▪ Example weekly lunch matchup
▪ Mobile lunch match results
Go meet someone new.
Carolyn Grabill
Salesforce.com
Software Development Engineer
@CarolynCodes

Get the source: http://bit.ly/DF13Lunch
Trigger on CollaborationGroupMember
trigger addNewLunchers on CollaborationGroupMember
(after insert, after delete)
{
if (Trigger.isInsert) {
// When a user joins the group, create a
// Luncher__c record for them
LunchChatter.newLuncherOnGroupJoin(Trigger.new);
} else if (Trigger.isDelete) {
// When a user leaves the group, mark the
// Luncher__c record inactive
LunchChatter.makeLuncherInactiveOnGroupLeave(Trigger.old);
}
}
//create a new luncher when someone joins the lunch chatter group
public static void newLuncherOnGroupJoin(List<CollaborationGroupMember> allNewMembers) {
//get the members that joined the lunch match chatter group
List<CollaborationGroupMember> members = new List<CollaborationGroupMember>();
for (CollaborationGroupMember cgm : allNewMembers) {
if (cgm.CollaborationGroupId == LunchChatter.lunchGroupId) {
members.add(cgm);
}
}
if (!members.isEmpty()) {
//for each member, figure out if we need to create a new luncher or update an existing one
for (CollaborationGroupMember cgm : members) {
if (keySet.contains(cgm.MemberId)) {
userIdsForLunchersToActivate.add(cgm.MemberId);
} else {
userIdsForNewLunchers.add(cgm.MemberId);
}
}
//create new lunchers and add them to the upsert list
if (!userIdsForNewLunchers.isEmpty()) {
for (User u : [SELECT Id, Name FROM User WHERE Id IN :userIdsForNewLunchers]) {
Luncher__c newLuncher = new Luncher__c(
Name = u.Name,
Status__c = 'Active',
User__c = u.Id);
lunchersToUpsert.add(newLuncher);
}
}
//get existing lunchers to update and add them to the upsert list
if (!userIdsForLunchersToActivate.isEmpty()) {
for (Luncher__c l : [SELECT Id, Status__c, User__c FROM Luncher__c where User__c
IN :userIdsForLunchersToActivate]) {
l.Status__c = 'Active';
lunchersToUpsert.add(l);
}
}
//insert new lunchers, if any were created
if (!lunchersToUpsert.isEmpty()) {
upsert lunchersToUpsert;
}
}
}
//mark a luncher inactive when someone leaves the lunch chatter group
public static void makeLuncherInactiveOnGroupLeave(List<CollaborationGroupMember> allDeleted) {
//get the members that are part of the chatter group you actually care about
List<Id> delUserIds = new List<Id>();
for (CollaborationGroupMember cgm : allDeleted) {
if (cgm.CollaborationGroupId == LunchChatter.lunchGroupId) {
delUserIds.add(cgm.MemberId);
}
}
//set status inactive for lunchers with delUserIds
if (!delUserIds.isEmpty()) {
List<Luncher__c> lunchersToUpdate = new List<Luncher__c>();
for (Luncher__c l : [SELECT Id, Status__c, User__c FROM Luncher__c WHERE User__c
IN :delUserIds]) {
l.Status__c = 'Inactive';
lunchersToUpdate.add(l);
}
if (!lunchersToUpdate.isEmpty()) {
update lunchersToUpdate;
}
}
}
global class scheduledLunchMatch implements Schedulable {
global void execute(SchedulableContext ctx) {
goMatchGo();
}
//shortcut for demos, to perform a match on command
public void goMatchGo() {
datetime lunchTime = datetime.now();
LunchMatcher lm = new LunchMatcher();
boolean matchSucceeded = lm.performScheduledMatch(lunchTime);
System.assertEquals(true, matchSucceeded);
}
}
public boolean performScheduledMatch(DateTime lunchDate) {
//get all the active lunchers
List<Luncher__c> activeLunchers = [SELECT Id, Name from Luncher__c WHERE Status__c = 'Active'];
Map<Id, Luncher__c> luncherMap = new Map<Id, Luncher__c>();
//get all the inactive lunchers
List<Luncher__c> inactiveLunchers = [SELECT Id FROM Luncher__c WHERE Status__c = 'Inactive'];
//get all the previous matches
List<Lunch_Match__c> prevMatches = [SELECT Id, Location_Picker__c, Time_Picker__c from
Lunch_Match__c];
//construct a list of lunchers with history that holds all the previous matches and lunchers
// with no matches
Map<Id, Set<Id>> prevMatchMap = getPrevMatchMap(prevMatches, activeLunchers, inactiveLunchers);
List<LuncherWithHistory> lunchersWithHistory = LuncherWithHistory.convertFromMap(prevMatchMap);
//do the matching
List<Id> thirdWheelIds = new List<Id>(); //holds any unmatched lunchers
List<Lunch_Match__c> newLunchMatches = matchup(lunchersWithHistory, lunchDate, thirdWheelIds);
insert newLunchMatches;
//handle the thirdwheels
handleThirdWheels(thirdWheelids, newLunchMatches);
}
/**
* A container class for convenience, representing a single Luncher__c,
* and the set of other Luncher__c's that they have already been matched with,
* based on existing Lunch_Match__c records.
*/
global class LuncherWithHistory implements Comparable {
public Id luncherId;
//id of this luncher
private Set<Id> historySet; //set of ids of other lunchers this luncher has already
//been matched with
//constructor for luncher that does have match history
public LuncherWithHistory(Id luncherId, Set<Id> historySet) {
this.luncherId = luncherId;
this.historySet = historySet;
}
// CompareTo() will return 0 if ids are equal, else, will return 1 if this
// LuncherWithHistory's group size is larger
global Integer compareTo(Object compareTo) {
LuncherWithHistory compareToLuncher = (LuncherWithHistory)compareTo;
if (luncherId == compareToLuncher.luncherId) return 0;
if (historySet.size() > compareToLuncher.historySet.size()) return 1;
return -1;
}
}
//given a list of new Lunch Matches, post to each picker's chatter wall
public static void notifyLunchers(List<Lunch_Match__c> matches) {
//construct maps of match to time picker and match to loc picker
for (Lunch_Match__c lm : matches) {
matchToLuncherLoc.put(lm.Id, lm.Location_Picker__c);
matchToLuncherTime.put(lm.Id, lm.Time_Picker__c);
}
//construct a map of luncher id to user id
Map<Id, Luncher__c> luncherIdToLuncherMap = getLunchersFromMatches(matches);
//build the chatter messages
List<FeedItem> feedItems = new List<FeedItem>();
for (Lunch_Match__c match : matches) {
Luncher__c locPicker = luncherIdToLuncherMap.get(matchToLuncherLoc.get(match.Id));
if (locPicker.Receive_Chatter_Notifications__c) {
FeedItem locFeedItem = buildFeedItem(locPicker);
feedItems.add(locFeedItem);
}
//repeat for time picker
}
insert feedItems;
}

Contenu connexe

Tendances

Ict in banking
Ict in bankingIct in banking
Ict in banking
aixoo
 
Future of Off-Premise Dining - Emerging View.pdf
Future of Off-Premise Dining - Emerging View.pdfFuture of Off-Premise Dining - Emerging View.pdf
Future of Off-Premise Dining - Emerging View.pdf
Future Agenda
 

Tendances (15)

Final e bay
Final e bayFinal e bay
Final e bay
 
online marketplace report
online marketplace reportonline marketplace report
online marketplace report
 
Consumer-To-Consumer Food Delivery System on Salesforce.
Consumer-To-Consumer Food Delivery System on Salesforce.Consumer-To-Consumer Food Delivery System on Salesforce.
Consumer-To-Consumer Food Delivery System on Salesforce.
 
Ec2009 ch02 e marketplaces
Ec2009 ch02 e marketplacesEc2009 ch02 e marketplaces
Ec2009 ch02 e marketplaces
 
Airbnb Strategic Analysis
Airbnb Strategic Analysis Airbnb Strategic Analysis
Airbnb Strategic Analysis
 
Swiggy clone app
Swiggy clone appSwiggy clone app
Swiggy clone app
 
Shopify case study
Shopify case studyShopify case study
Shopify case study
 
Ict in banking
Ict in bankingIct in banking
Ict in banking
 
Future of Off-Premise Dining - Emerging View.pdf
Future of Off-Premise Dining - Emerging View.pdfFuture of Off-Premise Dining - Emerging View.pdf
Future of Off-Premise Dining - Emerging View.pdf
 
Airbnb
Airbnb Airbnb
Airbnb
 
online food restaurants and ecommerce
online food restaurants and ecommerceonline food restaurants and ecommerce
online food restaurants and ecommerce
 
Marketing strategy of bikroy.com for creating competitive advantage
Marketing strategy of bikroy.com for creating competitive advantage Marketing strategy of bikroy.com for creating competitive advantage
Marketing strategy of bikroy.com for creating competitive advantage
 
MARKETING ENVIRONMENT OF UBER
MARKETING ENVIRONMENT OF UBERMARKETING ENVIRONMENT OF UBER
MARKETING ENVIRONMENT OF UBER
 
Augmented Reality for Travel: A Business Model
Augmented Reality for Travel: A Business ModelAugmented Reality for Travel: A Business Model
Augmented Reality for Travel: A Business Model
 
E commerce website Project Presentation
E commerce website Project PresentationE commerce website Project Presentation
E commerce website Project Presentation
 

Similaire à Coding Apex Triggers on Chatter Group Members

Spring '14 Release Developer Preview Webinar
Spring '14 Release Developer Preview WebinarSpring '14 Release Developer Preview Webinar
Spring '14 Release Developer Preview Webinar
Salesforce Developers
 

Similaire à Coding Apex Triggers on Chatter Group Members (20)

Best Practices for Team Development in a Single Org
Best Practices for Team Development in a Single OrgBest Practices for Team Development in a Single Org
Best Practices for Team Development in a Single Org
 
Summer '13 Developer Preview Webinar
Summer '13 Developer Preview WebinarSummer '13 Developer Preview Webinar
Summer '13 Developer Preview Webinar
 
Advanced Automation with Flows and Custom Metadata Types
Advanced Automation with Flows and Custom Metadata TypesAdvanced Automation with Flows and Custom Metadata Types
Advanced Automation with Flows and Custom Metadata Types
 
Reusable Build Scripts for Managed Package Development (October 14, 2014)
Reusable Build Scripts for Managed Package Development (October 14, 2014)Reusable Build Scripts for Managed Package Development (October 14, 2014)
Reusable Build Scripts for Managed Package Development (October 14, 2014)
 
Manage Salesforce Like a Pro with Governance
Manage Salesforce Like a Pro with GovernanceManage Salesforce Like a Pro with Governance
Manage Salesforce Like a Pro with Governance
 
Sandboxes: The Future of App Development by Evan Barnet & Pam Barnet
Sandboxes: The Future of App Development by Evan Barnet & Pam BarnetSandboxes: The Future of App Development by Evan Barnet & Pam Barnet
Sandboxes: The Future of App Development by Evan Barnet & Pam Barnet
 
Staying Ahead of the Curve with Lightning - Snowforce16 Keynote
Staying Ahead of the Curve with Lightning - Snowforce16 KeynoteStaying Ahead of the Curve with Lightning - Snowforce16 Keynote
Staying Ahead of the Curve with Lightning - Snowforce16 Keynote
 
Developing Offline Mobile Apps with Salesforce Mobile SDK SmartStore
Developing Offline Mobile Apps with Salesforce Mobile SDK SmartStoreDeveloping Offline Mobile Apps with Salesforce Mobile SDK SmartStore
Developing Offline Mobile Apps with Salesforce Mobile SDK SmartStore
 
REST API: Do More in the Feed with Action Links
REST API: Do More in the Feed with Action LinksREST API: Do More in the Feed with Action Links
REST API: Do More in the Feed with Action Links
 
Dreamforce 2017: Salesforce DX - an Admin's Perspective
Dreamforce 2017:  Salesforce DX - an Admin's PerspectiveDreamforce 2017:  Salesforce DX - an Admin's Perspective
Dreamforce 2017: Salesforce DX - an Admin's Perspective
 
Salesforce Spring'15 release overview
Salesforce Spring'15 release overviewSalesforce Spring'15 release overview
Salesforce Spring'15 release overview
 
SFDC 3.0 RESUME
SFDC 3.0 RESUMESFDC 3.0 RESUME
SFDC 3.0 RESUME
 
Spring '14 Release Developer Preview Webinar
Spring '14 Release Developer Preview WebinarSpring '14 Release Developer Preview Webinar
Spring '14 Release Developer Preview Webinar
 
ISV Tech Talk: Trialforce (October 15, 2014)
ISV Tech Talk: Trialforce (October 15, 2014)ISV Tech Talk: Trialforce (October 15, 2014)
ISV Tech Talk: Trialforce (October 15, 2014)
 
Hands-On Workshop: Introduction to Coding for on Force.com for Admins and Non...
Hands-On Workshop: Introduction to Coding for on Force.com for Admins and Non...Hands-On Workshop: Introduction to Coding for on Force.com for Admins and Non...
Hands-On Workshop: Introduction to Coding for on Force.com for Admins and Non...
 
Planning Your Migration to the Lightning Experience
Planning Your Migration to the Lightning ExperiencePlanning Your Migration to the Lightning Experience
Planning Your Migration to the Lightning Experience
 
From Sandbox To Production: An Introduction to Salesforce Release Management
From Sandbox To Production: An Introduction to Salesforce Release ManagementFrom Sandbox To Production: An Introduction to Salesforce Release Management
From Sandbox To Production: An Introduction to Salesforce Release Management
 
Automating the Impossible: End to End Team Development for ISVs (October 14, ...
Automating the Impossible: End to End Team Development for ISVs (October 14, ...Automating the Impossible: End to End Team Development for ISVs (October 14, ...
Automating the Impossible: End to End Team Development for ISVs (October 14, ...
 
Df14 Maintaining your orgs setup for optimal efficiency for dist
Df14 Maintaining your orgs setup for optimal efficiency for distDf14 Maintaining your orgs setup for optimal efficiency for dist
Df14 Maintaining your orgs setup for optimal efficiency for dist
 
Our API Evolution: From Metadata to Tooling API for Building Incredible Apps
Our API Evolution: From Metadata to Tooling API for Building Incredible AppsOur API Evolution: From Metadata to Tooling API for Building Incredible Apps
Our API Evolution: From Metadata to Tooling API for Building Incredible Apps
 

Plus de Salesforce Developers

Plus de Salesforce Developers (20)

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component Performance
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base Components
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer Highlights
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX India
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local Development
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web Components
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer Highlights
 
Live coding with LWC
Live coding with LWCLive coding with LWC
Live coding with LWC
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and Testing
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura Interoperability
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce data
 
Lightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionLightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An Introduction
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCP
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in Salesforce
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data Capture
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DX
 
Get Into Lightning Flow Development
Get Into Lightning Flow DevelopmentGet Into Lightning Flow Development
Get Into Lightning Flow Development
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS Connect
 

Dernier

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 

Coding Apex Triggers on Chatter Group Members

  • 1. Coding Apex Triggers on Chatter Group Members A case study in coding for collaboration Carolyn Grabill Salesforce.com Software Development Engineer @CarolynCodes
  • 2. Safe harbor Safe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services. The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of any litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site. Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
  • 3. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 4. Lunchforce brings the power of Chatter to the real world. Get the source: http://bit.ly/DF13Lunch
  • 5. Lunchforce’s moving parts User joins Lunchforce Chatter group Chatter Group Member Trigger fires Luncher__c record is created for that User Admin schedules LunchMatch Apex Scheduled Apex runs matching algorithm, posts results to Chatter Users see Chatter posts, meet up for lunch together
  • 6. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 7. Lunchforce’s Custom Objects Junction Object Junction Object
  • 8. Records created by matching process Luncher__c Location Picker Luncher__c Time Picker Lookup Lunch_Match__c Match Record Lookup
  • 9. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 11. CollaborationGroupMember fields ▪ CollaborationGroupId • The Id of the Chatter group joined ▪ CollaborationRole • Whether the User is Standard or Admin group member ▪ MemberId • Id of the User joining the group ▪ NotificationFrequency • Picklist – Daily, Weekly, Never, Post
  • 12. Demo ▪ Example CollaborationGroupMember Trigger • AddNewLunchers ▪ Trigger in action
  • 13. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 14. Lunchforce’s moving parts User joins Lunchforce Chatter group Collaboration Group Member Trigger fires Luncher__c record is created for that User Admin schedules LunchMatch Apex Scheduled Apex runs matching algorithm, posts results to Chatter Users see Chatter posts, meet up for lunch together
  • 15. Interfaces ▪ A template that defines methods, but does not implement them ▪ Apex class implements an interface by implementing its methods ▪ Schedulable is an interface built in to Apex ▪ Example: global class scheduledLunchMatch implements Schedulable { global void execute(SchedulableContext ctx) { goMatchGo(); } }
  • 16.
  • 17. Demo ▪ Example Schedulable Class • ScheduledLunchMatch ▪ Scheduling a job in setup
  • 18. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 19. Problem: how do you maximize new matches in a group of people, when some of them have already met?
  • 20. Solution: sort the lunchers by how many lunches they’ve already had.
  • 21. Demo ▪ Example Comparable Class • LuncherWithHistory ▪ Sorting a list of LuncherWithHistory records • LunchMatcher
  • 22. Lunchforce Technologies ▪ Using custom junction objects ▪ Triggering on Chatter Group Members ▪ Implementing an interface in Apex • Schedulable • Comparable ▪ Posting to Chatter from Apex
  • 23. Posting to Chatter from Apex using FeedItem ▪ Represents an entry in the feed, such as changes in a record feed, including text posts, link posts, and content posts. ▪ Example: FeedItem fi = new FeedItem(); fi.ParentId = [object id]; //user, account, etc. fi.Body = “Body of the post”; insert fi;
  • 24. Demo ▪ Example FeedItem creation • LuncherWithHistory ▪ Example weekly lunch matchup ▪ Mobile lunch match results
  • 26. Carolyn Grabill Salesforce.com Software Development Engineer @CarolynCodes Get the source: http://bit.ly/DF13Lunch
  • 27.
  • 28. Trigger on CollaborationGroupMember trigger addNewLunchers on CollaborationGroupMember (after insert, after delete) { if (Trigger.isInsert) { // When a user joins the group, create a // Luncher__c record for them LunchChatter.newLuncherOnGroupJoin(Trigger.new); } else if (Trigger.isDelete) { // When a user leaves the group, mark the // Luncher__c record inactive LunchChatter.makeLuncherInactiveOnGroupLeave(Trigger.old); } }
  • 29. //create a new luncher when someone joins the lunch chatter group public static void newLuncherOnGroupJoin(List<CollaborationGroupMember> allNewMembers) { //get the members that joined the lunch match chatter group List<CollaborationGroupMember> members = new List<CollaborationGroupMember>(); for (CollaborationGroupMember cgm : allNewMembers) { if (cgm.CollaborationGroupId == LunchChatter.lunchGroupId) { members.add(cgm); } } if (!members.isEmpty()) { //for each member, figure out if we need to create a new luncher or update an existing one for (CollaborationGroupMember cgm : members) { if (keySet.contains(cgm.MemberId)) { userIdsForLunchersToActivate.add(cgm.MemberId); } else { userIdsForNewLunchers.add(cgm.MemberId); } }
  • 30. //create new lunchers and add them to the upsert list if (!userIdsForNewLunchers.isEmpty()) { for (User u : [SELECT Id, Name FROM User WHERE Id IN :userIdsForNewLunchers]) { Luncher__c newLuncher = new Luncher__c( Name = u.Name, Status__c = 'Active', User__c = u.Id); lunchersToUpsert.add(newLuncher); } } //get existing lunchers to update and add them to the upsert list if (!userIdsForLunchersToActivate.isEmpty()) { for (Luncher__c l : [SELECT Id, Status__c, User__c FROM Luncher__c where User__c IN :userIdsForLunchersToActivate]) { l.Status__c = 'Active'; lunchersToUpsert.add(l); } } //insert new lunchers, if any were created if (!lunchersToUpsert.isEmpty()) { upsert lunchersToUpsert; } } }
  • 31. //mark a luncher inactive when someone leaves the lunch chatter group public static void makeLuncherInactiveOnGroupLeave(List<CollaborationGroupMember> allDeleted) { //get the members that are part of the chatter group you actually care about List<Id> delUserIds = new List<Id>(); for (CollaborationGroupMember cgm : allDeleted) { if (cgm.CollaborationGroupId == LunchChatter.lunchGroupId) { delUserIds.add(cgm.MemberId); } } //set status inactive for lunchers with delUserIds if (!delUserIds.isEmpty()) { List<Luncher__c> lunchersToUpdate = new List<Luncher__c>(); for (Luncher__c l : [SELECT Id, Status__c, User__c FROM Luncher__c WHERE User__c IN :delUserIds]) { l.Status__c = 'Inactive'; lunchersToUpdate.add(l); } if (!lunchersToUpdate.isEmpty()) { update lunchersToUpdate; } } }
  • 32. global class scheduledLunchMatch implements Schedulable { global void execute(SchedulableContext ctx) { goMatchGo(); } //shortcut for demos, to perform a match on command public void goMatchGo() { datetime lunchTime = datetime.now(); LunchMatcher lm = new LunchMatcher(); boolean matchSucceeded = lm.performScheduledMatch(lunchTime); System.assertEquals(true, matchSucceeded); } }
  • 33. public boolean performScheduledMatch(DateTime lunchDate) { //get all the active lunchers List<Luncher__c> activeLunchers = [SELECT Id, Name from Luncher__c WHERE Status__c = 'Active']; Map<Id, Luncher__c> luncherMap = new Map<Id, Luncher__c>(); //get all the inactive lunchers List<Luncher__c> inactiveLunchers = [SELECT Id FROM Luncher__c WHERE Status__c = 'Inactive']; //get all the previous matches List<Lunch_Match__c> prevMatches = [SELECT Id, Location_Picker__c, Time_Picker__c from Lunch_Match__c]; //construct a list of lunchers with history that holds all the previous matches and lunchers // with no matches Map<Id, Set<Id>> prevMatchMap = getPrevMatchMap(prevMatches, activeLunchers, inactiveLunchers); List<LuncherWithHistory> lunchersWithHistory = LuncherWithHistory.convertFromMap(prevMatchMap); //do the matching List<Id> thirdWheelIds = new List<Id>(); //holds any unmatched lunchers List<Lunch_Match__c> newLunchMatches = matchup(lunchersWithHistory, lunchDate, thirdWheelIds); insert newLunchMatches; //handle the thirdwheels handleThirdWheels(thirdWheelids, newLunchMatches); }
  • 34. /** * A container class for convenience, representing a single Luncher__c, * and the set of other Luncher__c's that they have already been matched with, * based on existing Lunch_Match__c records. */ global class LuncherWithHistory implements Comparable { public Id luncherId; //id of this luncher private Set<Id> historySet; //set of ids of other lunchers this luncher has already //been matched with //constructor for luncher that does have match history public LuncherWithHistory(Id luncherId, Set<Id> historySet) { this.luncherId = luncherId; this.historySet = historySet; } // CompareTo() will return 0 if ids are equal, else, will return 1 if this // LuncherWithHistory's group size is larger global Integer compareTo(Object compareTo) { LuncherWithHistory compareToLuncher = (LuncherWithHistory)compareTo; if (luncherId == compareToLuncher.luncherId) return 0; if (historySet.size() > compareToLuncher.historySet.size()) return 1; return -1; } }
  • 35. //given a list of new Lunch Matches, post to each picker's chatter wall public static void notifyLunchers(List<Lunch_Match__c> matches) { //construct maps of match to time picker and match to loc picker for (Lunch_Match__c lm : matches) { matchToLuncherLoc.put(lm.Id, lm.Location_Picker__c); matchToLuncherTime.put(lm.Id, lm.Time_Picker__c); } //construct a map of luncher id to user id Map<Id, Luncher__c> luncherIdToLuncherMap = getLunchersFromMatches(matches); //build the chatter messages List<FeedItem> feedItems = new List<FeedItem>(); for (Lunch_Match__c match : matches) { Luncher__c locPicker = luncherIdToLuncherMap.get(matchToLuncherLoc.get(match.Id)); if (locPicker.Receive_Chatter_Notifications__c) { FeedItem locFeedItem = buildFeedItem(locPicker); feedItems.add(locFeedItem); } //repeat for time picker } insert feedItems; }