Case Milestones not created when testing apex class - unit-testing

Recently I stumbled upon problem getting code coverage for Apex code that evaluates case milestones by their target date values. When trying to create case in test class it does not create case milestone for it after insert although all the criteria is being met what is defined in entitlement process.
Also by reading articles - like this about entitlements it seems like I have created everything.
The Entitlement process is Active, Entitlement with associated Account that is linked to Case is created and linked to Case, Business Hours are valid, Entitlement process is linked to Entitlement. Case entry criteria matches what is defined in Entitlement Process for Milestones, but still in test class milestones are not created.
System.debug('case milestones = '+ cmss); statement returns empty list and logic that relies on case milestone target date cannot be covered. Is there something missing in test data?
Example of test class:
#IsTest
private class GetCaseTest {
#TestSetup
static void createTestData(){
Profile p = [SELECT Id FROM Profile WHERE Name='Customer Service Lightning'];
UserRole role = [SELECT ID, Name FROM UserRole WHERE Name Like 'NO%' LIMIT 1];
System.debug('#role: ' + role);
User u = new User(
Alias = 'standt',
Email='testmail#test.com',
EmailEncodingKey='UTF-8',
FirstName='Test',
LastName='Testing',
LanguageLocaleKey='en_US',
LocaleSidKey='en_US',
ProfileId = p.Id,
UserRoleId=role.Id,
TimeZoneSidKey='America/Los_Angeles',
UserName='testmail#test.com'
);
insert u;
Group g = new Group(
Name='NO CS',
Type = 'Queue'
);
insert g;
queuesobject q1 = new queuesobject(SObjectType = 'Case', queueid=g.id);
insert q1;
GroupMember member = new GroupMember();
member.UserOrGroupId = u.Id;
member.GroupId = g.Id;
insert member;
}
#isTest
static void getCaseFuture(){
User u = [SELECT Id, Email FROM User WHERE Email = 'testmail#test.com'].get(0);
System.runAs(u){
Id accRecType = Schema.SObjectType.Account.getRecordTypeInfosByName().get('B2B Account').getRecordTypeId();
Account acc = new account(name='Test Account', RecordTypeId= accRecType, OwnerId = u.Id);
insert acc;
Contact oContact = new contact(firstname='John',lastname='Doe',email='test#test.com',accountid=acc.id, OwnerId = u.Id);
insert oContact;
Entitlement entl = new entitlement(name='NO Entitlement',accountid=acc.id, StartDate=Date.valueof(System.now().addDays(-2)), EndDate=Date.valueof(System.now().addYears(2)));
insert entl;
List<SlaProcess> lstEntitlementProcess = [SELECT Id, Name FROM SlaProcess WHERE Name='NO Entitlement Process 1.3' and IsActive = true LIMIT 1];
System.debug('lstEntitlementProcess= '+lstEntitlementProcess);
entl.SlaProcessId = lstEntitlementProcess[0].id;
update entl;
BusinessHours bhours = [SELECT Id, Name FROM BusinessHours WHERE Name = 'NO Customer Service'].get(0);
Id recordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Card Administration').getRecordTypeId();
Group g = [SELECT Id FROM Group WHERE Type = 'Queue' AND Name = 'NO CS'].get(0);
Case c2 = new Case(
Subject = 'To be distributed from queue',
Status = 'In Progress',
Case_Re_opened__c = false,
OwnerId = g.Id,
CurrencyIsoCode = 'EUR',
Country__c = 'NO',
Case_Category__c = 'Card Block',
RecordTypeId = recordTypeId,
AccountId = acc.Id,
ContactId = oContact.Id,
EntitlementId = entl.Id,
slaStartDate=system.now(),
BusinessHoursId = bhours.Id
);
insert c2;
List<CaseMilestone> cmss = [SELECT Id, CaseId FROM CaseMilestone WHERE CaseId =: c2.Id];
System.debug('case milestones = '+ cmss);
System.debug('c2 = '+ c2);
System.debug('c2.OwnerId=> '+ c2.OwnerId);
}
Test.startTest();
GetCase.findCase();
// GetCase.findCase();
Test.stopTest();
}
}

Related

Why is Microsoft Dynamics GP getting multiple distribution lines when creating a sales invoice?

I’m using Microsoft Dynamics GP. First of all, I am a programmer by job title. I have no training and only limited usage on using the Dyanmics GP product. I wrote a program that uses the GP Web Services to create a sales invoice. The sales invoice includes 2 distribution lines. However, when the accountants look at GP, they see 4 distribution lines; each of the lines my program adds has been duplicated. What am I doing wrong? Any other ideas on why this is happening?
Here’s the code for adding the distribution lines (GL codes have been hidden for privacy issues):
//Adds the Distributions - where it hits the GL Accounts
salesInvoice.Distributions = new SalesDistribution[2];
SalesDistribution apSalesDistribution = new SalesDistribution();
apSalesDistribution.GLAccountKey = new GLAccountNumberKey() { Id = "xx-xx-xxxx" };
apSalesDistribution.CreditAmount = new MoneyAmount() { Currency = "USD", Value = itemsReceived.CostEach };
apSalesDistribution.DistributionTypeKey = new DistributionTypeKey() { Id = 1 };
salesInvoice.Distributions[0] = apSalesDistribution;
SalesDistribution salesDistribution = new SalesDistribution();
salesDistribution.GLAccountKey = new GLAccountNumberKey() { Id = "yy-yy-yyyy" };
salesDistribution.DebitAmount = new MoneyAmount() { Currency = "USD", Value = itemsReceived.CostEach };
salesDistribution.DistributionTypeKey = new DistributionTypeKey() { Id = 2};
salesInvoice.Distributions[1] = salesDistribution;
On this page, there should be 2 lines based on the code above, but there are 4 lines:
Here’s the full code for creating the sales invoice (again, identifying information has been removed):
CompanyKey companyKey;
companyKey = new CompanyKey();
Context context;
SalesInvoice salesInvoice;
SalesDocumentTypeKey salesInvoiceType;
CustomerKey customerKey;
customerKey = new CustomerKey();
BatchKey batchKey;
SalesInvoiceLine salesInvoiceLine;
ItemKey invoiceItem;
Quantity invoiceCount;
Policy salesInvoiceCreatePolicy;
salesInvoiceCreatePolicy = new Policy();
string salesInvoiceNumber = "";
try
{
logger.Info("Creating sales invoice.");
// Create an instance of the service
DynamicsGPClient wsDynamicsGP = new DynamicsGPClient();
// Create a context with which to call the service
context = new Context();
// Specify which company to use (sample company)
companyKey.Id = ((parms.liveMode) ? x : y);
// Set up the context object
context.OrganizationKey = (OrganizationKey)companyKey;
// Create a sales invoice object
salesInvoice = new SalesInvoice();
// Create a sales document type key for the sales invoice
salesInvoiceType = new SalesDocumentTypeKey();
salesInvoiceType.Type = SalesDocumentType.Invoice;
// Populate the document type key for the sales invoice
salesInvoice.DocumentTypeKey = salesInvoiceType;
// Create a customer key
customerKey.Id = "xxxx-xxx";
// Set the customer key property of the sales invoice
salesInvoice.CustomerKey = customerKey;
salesInvoice.PostedDate = parms.endDate;
// Create a batch key
batchKey = new BatchKey();
batchKey.Id = "CSA_" + salesOrderDate.ToString("yyMMdd");
// Set the batch key property of the sales invoice object
salesInvoice.BatchKey = batchKey;
// Create a sales invoice line to specify the invoiced item
salesInvoiceLine = new SalesInvoiceLine();
// Create an item key
invoiceItem = new ItemKey();
invoiceItem.Id = itemsReceived.GPPartNumber;
logger.Info("SalesInvoiceCreator.cs createGPSalesOrder() GP part number used for sales invoice: " + invoiceItem.Id);
// Set the item key property of the sales invoice line object
salesInvoiceLine.ItemKey = invoiceItem;
// Create a sales invoice quatity object
invoiceCount = new Quantity();
invoiceCount.Value = itemsReceived.Quantity;
logger.Info("SalesInvoiceCreator.cs createGPSalesOrder() Quantity used for sales invoice: " + invoiceCount.Value);
// Set the quantity of the sales invoice line object
salesInvoiceLine.Quantity = invoiceCount;
MoneyAmount unitCost = new MoneyAmount()
{
Value = itemsReceived.CostEach
};
logger.Info("SalesInvoiceCreator.cs createGPSalesOrder() Cost used for sales invoice: " + unitCost.Value);
salesInvoiceLine.UnitPrice = unitCost;
// Create an array of sales invoice lines
// Initialize the array with the sales invoice line object
SalesInvoiceLine[] invoiceLines = { salesInvoiceLine };
// Add the sales invoice line array to the sales line object
salesInvoice.Lines = invoiceLines;
//Adds the Distributions - where it hits the GL Accounts
salesInvoice.Distributions = new SalesDistribution[2];
SalesDistribution apSalesDistribution = new SalesDistribution();
apSalesDistribution.GLAccountKey = new GLAccountNumberKey() { Id = "xx-xx-xxxx" };
apSalesDistribution.CreditAmount = new MoneyAmount() { Currency = "USD", Value = itemsReceived.CostEach };
apSalesDistribution.DistributionTypeKey = new DistributionTypeKey() { Id = 1 };
salesInvoice.Distributions[0] = apSalesDistribution;
SalesDistribution salesDistribution = new SalesDistribution();
salesDistribution.GLAccountKey = new GLAccountNumberKey() { Id = "yy-yy-yyyy" };
salesDistribution.DebitAmount = new MoneyAmount() { Currency = "USD", Value = itemsReceived.CostEach };
salesDistribution.DistributionTypeKey = new DistributionTypeKey() { Id = 2};
try
{
// Get the create policy for the sales invoice object
salesInvoiceCreatePolicy = wsDynamicsGP.GetPolicyByOperation("CreateSalesInvoice", context);
wsDynamicsGP.UpdatePolicy(salesInvoiceCreatePolicy, new RoleKey { Id = "00000000-0000-0000-0000-000000000000" }, context);
}
catch (Exception ex)
{
logger.Error("Error creating sales invoice policy." + Environment.NewLine + "Error: " + ex.Message + Environment.NewLine + "Stack trace: " + ex.StackTrace);
throw ex;
}
try
{
// Create the sales invoice
wsDynamicsGP.CreateSalesInvoice(salesInvoice, context, salesInvoiceCreatePolicy);
}
catch (Exception ex)
{
logger.Error("Error creating sales invoice." + Environment.NewLine + "Error: " + ex.Message + Environment.NewLine + "Stack trace: " + ex.StackTrace);
throw ex;
}

test class for handler trigger is not covered

I did a trigger on content version ,but my handler class is not covered ,can you please explain to me why ?
please find below the code and screenshots for non covered lines
in my test class ,i created all data needed for the handler class i call the method with content version input
Trigger:
trigger contentversiontrigger on ContentVersion (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
if(trigger.isAfter && trigger.isInsert) {
Bytel_ContentVersionTriggerHandler.AlignAttachementsWithOpportunity(Trigger.New);
}
}
Trigger Handler
public with sharing class Bytel_ContentVersionTriggerHandler extends TriggerHandler {
public static void AlignAttachementsWithOpportunity(List<ContentVersion> contentVersion) {
Set<Id> contentDocumentIdSet = new Set<Id>();
String Contractid;
String Opportunityid;
for (ContentVersion cv : contentVersion) {
if(cv.ContentDocumentId != null)
{
contentDocumentIdSet.add(cv.ContentDocumentId);
}
}
list<ContentDocumentLink> cdl = [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN:contentDocumentIdSet];
id LinkedEntityId =cdl[0].LinkedEntityId ;
// List<Contract> contractList = [SELECT Id, name FROM Contract where Id =:cdl.LinkedEntityId];
list<contract> Contracts = [SELECT Id, name FROM Contract where Id =:LinkedEntityId ];
if (!Contracts.isEmpty())
{
Contractid=Contracts[0].Id;
}
// Id Contractid = [SELECT Id, name FROM Contract where Id ='8005t0000001UQFAA2' limit 1].Id;
system.debug('test trigger' +Contractid) ;
// String Contractid= String.valueof(contractList[0].Id);
system.debug('ContractId' +Contractid) ;
list<Contract> contractssecond=[SELECT id ,vlocity_cmt__OpportunityId__c FROM Contract WHERE id =:Contractid limit 1];
if (!contractssecond.isEmpty())
{
Opportunityid=contractssecond[0].vlocity_cmt__OpportunityId__c;
}
system.debug('Opportunityid' +Opportunityid) ;
Id conDoc = cdl[0].ContentDocumentId;
//if (Opportunityid!=Null & conDoc!=Null) {
if (Opportunityid!=Null ) {
//create ContentDocumentLink record
ContentDocumentLink conDocLink = New ContentDocumentLink();
conDocLink.LinkedEntityId = Opportunityid;
conDocLink.ContentDocumentId = conDoc; //ContentDocumentId Id from ContentVersion
conDocLink.shareType = 'V';
insert conDocLink;
}
}
}
Test class of handler
#isTest
public class Bytel_ContentVersionTriggerHandlerTest {
static testMethod void createattachememtns() {
insert Bytel_TestDataFactory.createByPassSettings(false); // Custom setting bypass profile
insert Bytel_TestDataFactory.createGlobalVariableSettings(); // Custom setting globalVaribale, parameter callout end-point
insert Bytel_TestDataFactory.createOpportunityRaisonEchecSettings();
insert Bytel_TestDataFactory.createOpportunityStatusSettings();
Account acc = new Account(
Name = 'Test Account',
TypeIdentifiant__c = 'SIREN',
SIREN__c = '123765982',
Statut__c = 'Prospect'
);
insert acc;
Opportunity opp = Bytel_TestDataFactory.createOpportunity(
'FILL AUTO',
'Etape10',
acc.Id,
null
);
opp.Tech_AccountIdToDelete__c = acc.id;
opp.ScoringFinancier__c = 'Vert';
opp.siren__c = '123765981';
insert opp;
Quote quote = new Quote(Name = 'devis1', OpportunityId = opp.Id);
insert quote;
Contract contract1 = new Contract(
vlocity_cmt__QuoteId__c = quote.Id,
vlocity_cmt__OpportunityId__c=opp.id,
AccountId = acc.id
);
insert contract1;
Contract contract2 = new Contract(
vlocity_cmt__QuoteId__c = quote.Id,
AccountId = acc.id,
vlocity_cmt__OpportunityId__c=opp.id
);
insert contract2;
Blob bodyBlob=Blob.valueOf('Unit Test ContentVersion Body to be insert in test class for testing the');
ContentVersion contentVersion_1 = new ContentVersion(
Title='SampleTitle',
PathOnClient ='SampleTitle.txt',
Type_de_Fichier__c='RIB',
VersionData = bodyBlob,
origin = 'H'
);
insert contentVersion_1;
Contract contra = [SELECT Id
FROM Contract WHERE Id = :contract1.Id LIMIT 1];
List<ContentVersion> contentVersion_2 = [SELECT Id, Title, ContentDocumentId
FROM ContentVersion WHERE Id = :contentVersion_1.Id ];
// ContentDocumentLink contentlink = new ContentDocumentLink();
// contentlink.LinkedEntityId = contra.id;
// contentlink.contentdocumentid = contentVersion_2.contentdocumentid;
// contentlink.ShareType = 'V';
// insert contentlink;
Bytel_ContentVersionTriggerHandler.AlignAttachementsWithOpportunity(contentVersion_2);
}
}
After a first look, I guess you forgot to add #isTest to your test method.
#isTest
static testMethod void createattachememtns() {
//Your Code
}

Multiple events getting created on creating event in Teams with 100 members using Graph API

I am creating teams event using Graph API in my Azure function. For 10-30 members, I am able to create an event in MS Teams using Graph. It is sending an email notification also to the members for Join meeting.
When I tried with 50-100 members, multiple events getting created and multiple email notification also sending to each member.
Is there any member limitation or my code issue?
DateTime dStartDate = DateTime.Parse(session.SessionStartDateTime);
DateTime dEndDate = DateTime.Parse(session.SessionEndDateTime);
List<Microsoft.Graph.DayOfWeek> dayOfWeeks = new List<Microsoft.Graph.DayOfWeek>();
dayOfWeeks.Add(Microsoft.Graph.DayOfWeek.Monday);
dayOfWeeks.Add(Microsoft.Graph.DayOfWeek.Tuesday);
Event #event = new Event
{
Subject = "Test Meeting",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "Online Meeting - Test Meeting"
},
Start = new DateTimeTimeZone
{
DateTime = session.StartDateStartTime,
TimeZone = "Eastern Standard Time"
},
End = new DateTimeTimeZone
{
DateTime = session.StartDateEndTime,
TimeZone = "Eastern Standard Time"
},
Location = new Location
{
DisplayName = "Online"
},
Recurrence = new PatternedRecurrence
{
Pattern = new RecurrencePattern
{
Type = Weekly,
Interval = 1,
DaysOfWeek = dayOfWeeks
},
Range = new RecurrenceRange
{
Type = EndDate,
StartDate = new Date(dStartDate.Year, dStartDate.Month, dStartDate.Day),
EndDate = new Date(dEndDate.Year, dEndDate.Month, dEndDate.Day)
}
};
IsOnlineMeeting = true,
OnlineMeetingProvider = "TeamsForBusiness"
};
List<Attendee> attendees = new List<Attendee>();
if (session?.instructors?.Count > 0)
{
session.instructors.ForEach(s =>
{
attendees.Add(new Attendee
{
EmailAddress = new EmailAddress
{
Address = s.Email,
Name = s.Name
},
Type = AttendeeType.Required
});
});
}
if (session?.shoppers?.Count > 0)
{
session.shoppers.ForEach(s =>
{
attendees.Add(new Attendee
{
EmailAddress = new EmailAddress
{
Address = s.Email,
Name = s.Name
},
Type = AttendeeType.Required
});
});
}
#event.Attendees = attendees;
GraphServiceClient graph = GetAuthenticatedClient(session.tenantADInformation);
Event #event = PrepareEvent(session);
string Email = session.instructors.FirstOrDefault()?.Email;
var Event = await graph.Users[Email].Events
.Request()
.Header("Prefer", "outlook.timezone=\"" + session.TenantTimeZone + "\"")
.AddAsync(#event);
If it is 50-100 attendees then my Event is having Event.IsOnlineMeeting as false(even though I have set that to true) and Event.OnlineMeeting is coming as null.
Can anyone help?
I don't think exist any limitation in this case. Since the api allows us to create the event for the members, we can request it although there are many members. The only factor which may limit it is the max number of members in teams is 500. In addition to this, I think the api and the code can work fine.

JPA Cascading removal of parent and Child

I'm trying to learn and understand JPA, and just have a couple of questions regarding deleting a parent and its children in one go. I'm using OpenJPA and EJB3. I have two entities, a Category and a Product. A Category contains many products and a product has a reference to its parent category. The category's list of products is set to cascade.
//Category
#Entity #NamedQueries({#NamedQuery(name = "Category.getCategoryByName", query = "SELECT c FROM Category c WHERE c.name = :name"),#NamedQuery(name = "Category.getCategoryByCategoryId", query = "SELECT c FROM Category c WHERE c.categoryid = :categoryid"), #NamedQuery(name = "Category.getAllCategories", query = "SELECT c FROM Category c left join fetch c.products")})
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=IDENTITY)
private Integer categoryid;
private String name;
//bi-directional many-to-one association to Product
#OneToMany(cascade={CascadeType.ALL}, orphanRemoval = true,
fetch = EAGER, mappedBy="category")
private List<Product> products;
}
//Product
#Entity
#NamedQueries({#NamedQuery(name = "Product.getProductsByCategory",
query = "SELECT p.code, p.description, p.name, p.productid, p.weight FROM Product p WHERE p.category.categoryid = :category_categoryid"),
#NamedQuery(name = "Product.getProductByName", query = "SELECT p FROM Product p WHERE p.name = :name"),
#NamedQuery(name = "Product.getProductByCode", query = "SELECT p FROM Product p WHERE p.code = :code"),
#NamedQuery(name = "Product.getProductByProductId", query = "SELECT p FROM Product p WHERE p.productid = :productid"),
#NamedQuery(name = "Product.getAllProducts", query = "SELECT p FROM Product p")})
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=IDENTITY)
private Integer productid;
private String code;
private String description;
private String name;
private Double weight;
//bi-directional many-to-one association to Category
#ManyToOne(optional = false)
#JoinColumn(name="CATEGORYID")
private Category category;
}
}
// The EJB
#Stateless
#LocalBean
public class ShopManagerBean implements Serializable {
#PersistenceContext(unitName = "TestEJBProject2", type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteCategory(Category category)
throws TestApplicationException {
try {
Category actualCat = entityManager.find(Category.class,
category.getCategoryid());
List<Product> products = actualCat.getProducts();
if (products != null) {
Iterator<Product> it = products.iterator();
while (it.hasNext()) {
Product p = it.next();
it.remove();
entityManager.remove(p);
}
}
entityManager.refresh(actualCat);
entityManager.remove(actualCat);
} catch (Exception e) {
e.printStackTrace();
throw new TestApplicationException("Error creating new Product", e);
}
}
}
If I use the following code in the deleteCategory method the EJB then I cannot delete the parent and children as I get an Optimistic Locking exception (An optimistic lock violation was detected when flushing object instance "entity.Product-101" to the data store. This indicates that the object was concurrently modified in another transaction.) - complaining about flushing the product child to the data store
Category actualCat = entityManager.find(Category.class, category.getCategoryid());
if (products != null) {
actualCat.getProducts().clear();
}
entityManager.remove(actualCat);
However, if I use the following code in the deleteCategory method then I can delete the parent and children...but only if I call entityManager.refresh(actualCat) after removing the children and before removing the parent (otherwise I get an optimistic locking exception). Could somebody please explain to me why this is the case and also what the correct/best way of doing a cascading delete with OpenJPA V2 would be?
Category actualCat = entityManager.find(Category.class, category.getCategoryid());
List<Product> products = actualCat.getProducts();
if (products != null) {
Iterator<Product> it = products.iterator();
while (it.hasNext()) {
Product p = it.next();
it.remove();
entityManager.remove(p);
}
}
entityManager.refresh(actualCat);
entityManager.remove(actualCat);
Thanks in advance for your help
Fais
Addition
Here is the db creation script:
--
CREATE SCHEMA "DB2ADMIN";
CREATE TABLE "DB2ADMIN"."CATEGORY" (
"CATEGORYID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 20),
"NAME" VARCHAR(50) NOT NULL
)
DATA CAPTURE NONE;
CREATE TABLE "DB2ADMIN"."PRODUCT" (
"PRODUCTID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY ( START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 NO CYCLE CACHE 20),
"CODE" CHAR(15) NOT NULL,
"NAME" VARCHAR(50) NOT NULL,
"DESCRIPTION" VARCHAR(200) NOT NULL,
"WEIGHT" FLOAT(53) NOT NULL,
"CATEGORYID" INTEGER NOT NULL
)
DATA CAPTURE NONE;
ALTER TABLE "DB2ADMIN"."CATEGORY" ADD CONSTRAINT "CATEGORY_PK" PRIMARY KEY
("CATEGORYID");
ALTER TABLE "DB2ADMIN"."PRODUCT" ADD CONSTRAINT "PRODUCT_PK" PRIMARY KEY
("PRODUCTID");
ALTER TABLE "DB2ADMIN"."PRODUCT" ADD CONSTRAINT "PRODUCT_CATEGORY_FK" FOREIGN KEY
("CATEGORYID")
REFERENCES "DB2ADMIN"."CATEGORY"
("CATEGORYID")
ON DELETE CASCADE;

Listing Activities via Web Services

I'm trying to reproduce the Activities page in Microsoft CRM 4.0 via web services. I can retrieve a list of activities, and I believe I need to use ActivityPointers to retrieve the entities but have so far been unsuccessful. Would I need to loop through every single entity returned from the first query to retrieve the ActivityPointer for it? And if so, how would I then get the "Regarding" field or Subject of the activity (eg: email).
The code to retrieve the activities is:
var svc = GetCrmService();
var cols = new ColumnSet();
cols.Attributes = new[] { "activityid", "addressused", "scheduledstart", "scheduledend", "partyid", "activitypartyid", "participationtypemask", "ownerid" };
var query = new QueryExpression();
query.EntityName = EntityName.activityparty.ToString();
query.ColumnSet = cols;
LinkEntity link = new LinkEntity();
//link.LinkCriteria = filter;
link.LinkFromEntityName = EntityName.activitypointer.ToString();
link.LinkFromAttributeName = "activityid";
link.LinkToEntityName = EntityName.activityparty.ToString();
link.LinkToAttributeName = "activityid";
query.LinkEntities = new[] {link};
var activities = svc.RetrieveMultiple(query);
var entities = new List<ICWebServices.activityparty>();
RetrieveMultipleResponse retrieved = (RetrieveMultipleResponse) svc.Execute(request);
//var pointers = new List<activitypointer>();
foreach (activityparty c in activities.BusinessEntities)
{
entities.Add(((activityparty)c));
//the entities don't seem to contain a link to the email which they came from
}
Not sure if I understand your problem, but the field "activityid" in the activitypointer object is the same activityid as the underlying activity (email, task, phonecall, etc). The regardingobjectid is the link to the regarding entity.
Heres what you need to get the equivalent of the Activities page
ColumnSet cols = new ColumnSet()
{
Attributes = new string[] { "subject", "regardingobjectid", "regardingobjectidname", "regardingobjectidtypecode", "activitytypecodename", "createdon", "scheduledstart", "scheduledend" }
};
ConditionExpression condition = new ConditionExpression()
{
AttributeName = "ownerid",
Operator = ConditionOperator.Equal,
Values = new object[] { CurrentUser.systemuserid.Value } //CurrentUser is an systemuser object that represents the current user (WhoAmIRequest)
};
FilterExpression filter = new FilterExpression()
{
Conditions = new ConditionExpression[] { condition },
FilterOperator = LogicalOperator.And
};
QueryExpression query = new QueryExpression()
{
EntityName = EntityName.activitypointer.ToString(),
ColumnSet = cols,
Criteria = filter
};
BusinessEntityCollection activities = svc.RetrieveMultiple(query);
foreach (activitypointer activity in activities)
{
//do something with the activity
//or get the email object
email originalEmail = (email)svc.Retrieve(EntityName.email.ToString(), activity.activityid.Value, new AllColumns());
}