update the case status depend on task regarding status - c#

I have this code below. If all the task is reject =>> the case status=>> reject, but i want if i choose other like approve or pending it it gonna do the same with case status. For ex:like i choose csu task status == complete =>> csu case status== complete
Entity target = (Entity)context.InputParameters["target"];
Entity entity = service.Retrieve("task", target.Id, new ColumnSet(true));
EntityReference regardingCaseRef = entity["regardingobjectid"] as EntityReference;
Entity regardingCase = service.Retrieve(regardingCaseRef.LogicalName, regardingCaseRef.Id, new ColumnSet(true));
QueryExpression qeRelatedTasks = new QueryExpression("task");
qeRelatedTasks.ColumnSet = new ColumnSet(true);
qeRelatedTasks.Criteria.AddCondition(new ConditionExpression("regardingobjectid", ConditionOperator.Equal, regardingCaseRef.Id));
EntityCollection relatedTasks = service.RetrieveMultiple(qeRelatedTasks);
if (AllTaskReject(relatedTasks))
{
trace.Trace("status check");
regardingCase["cos_csucasestatus"] = new OptionSetValue(769190006);
trace.Trace("status check 2");
service.Update(regardingCase);
trace.Trace("status check 3");
/* Entity incident = new Entity("incident");
incident.Id = regardingCaseRef.Id;
trace.Trace("1");
incident["cos_csucasestatus"] = new OptionSetValue(769190006);
service.Update(incident);*/
// regardingCase.Attributesk["cos_csucasestatus"] = new OptionSetValue(769190006);
}
}
catch
{
throw;
}
}
}
public bool AllTaskReject(EntityCollection relatedTasks)
{
//check all the the task if rejected continue if on task not rejected do nothing
if (relatedTasks.Entities.All(x => x.GetAttributeValue<OptionSetValue>("cos_csutaskstatus")?.Value == 769190003))
{
return true;
}
else
{
return false;
}

Related

ASP.NET Core - How to update existing record and insert a new one at the same time using Entity Framework

In ASP.NET Core-6 Web API Entity Framework, I want the application to perform update and insert on the same model in the database at the same time.
I have this code:
public async Task<Response<string>> CreateIdentiticationAsync(CreateIdentiticationDto model)
{
var response = new Response<string>();
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
try
{
var identification = _mapper.Map<Identification>(model);
var existingIdentifications = await _dbContext.Identifications.Where(e => e.IsModified == false).ToListAsync();
foreach (var existingIdentification in existingIdentifications)
{
if (existingIdentification != null)
{
existingIdentification.IsModified = true;
_unitOfWork.UserIdentifications.Update(identification);
await _unitOfWork.Save();
}
}
Identification.IsModified = false;
Identification.Type = model.Type;
Identification.Name = model.Name;
await _unitOfWork.UserIdentifications.InsertAsync(identification);
await _unitOfWork.Save();
response.StatusCode = (int)HttpStatusCode.Created;
response.Successful = true;
response.Message = "Created Successfully!";
transaction.Complete();
return response;
}
catch (Exception ex)
{
transaction.Dispose();
response.Message = "An error occured";
response.Successful = false;
response.StatusCode = (int)HttpStatusCode.BadRequest;
return response;
}
}
}
When user wants to insert a new record, I want the application to first check the model, if no record exists it should just insert the new record.
But if it exists, it should update all the IsModified to true, and then go ahead and also insert a new record.
However, when no record exists, I was able to insert new record.
But where I have issue is that when it wants to update and insert new record, I got this error:
Violation of PRIMARY KEY constraint 'PK_identifications'. Cannot insert duplicate key in object 'dbo.identifications'. The duplicate key value is (81fe9b8d-2d9c-4d49-8f92-22afe043e327).
Note: Id is Guid and autgenerated
How do I resolve this?
Thanks
Many things to consider here, in modern EF, I would not use a unitOfWork also a transaction is not needed unless very specific cases, you should also validate the ID from your incoming model value is null since ID is supposed to be autogenerated (most likely this is the source of your error). Since I don't know the name of your PK field, I will not introduce such validation in my proposed code.
One last recommendation, avoid this code on your controller, it breaks Single Responsibility Principle. Create a layer where you perform your business tasks and call this layer from your controller.
Here is a simplified proposed code which should work, don't forget to ensure the value in the model ID is coming as null.
public async Task<Response<string>> CreateIdentiticationAsync(CreateIdentiticationDto model)
{
var response = new Response<string>();
try
{
var identification = _mapper.Map<Identification>(model);
var existingIdentifications = await _dbContext.Identifications.Where(e => e.IsModified == false).ToListAsync();
foreach (var existingIdentification in existingIdentifications)
{
existingIdentification.IsModified = true;
}
Identification.IsModified = false;
// If you already mapped this in line 6 why map those two fields again manually?
// Identification.Type = model.Type;
// Identification.Name = model.Name;
_dbContext.UpdateRange(existingIdentifications);
_dbContext.Add(identification);
await _dbContext.SaveChangesAsync();
response.StatusCode = (int)HttpStatusCode.Created;
response.Successful = true;
response.Message = "Created Successfully!";
return response;
}
catch (Exception ex)
{
transaction.Dispose();
response.Message = "An error occured";
response.Successful = false;
response.StatusCode = (int)HttpStatusCode.BadRequest;
return response;
}
}
public IActionResult Update(int? id,UpdateEmployeeVM employeeVM)
{
ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
Employee existed=_context.Employees.Find(id);
if(existed==null) { NotFound();}
if (!_context.Positions.Any(p => p.Id == employeeVM.PositionId)) ModelState.AddModelError("PoitionId", "Choose Id right");
if (!ModelState.IsValid)
{
ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
return View();
}
if (employeeVM.Image!=null)
{
string result = employeeVM.Image.CheckValidate("image/", 300);
if (result.Length > 0)
{
ViewBag.Positions=new SelectList(_context.Positions,nameof(Position.Id),nameof(Position.Name));
ModelState.AddModelError("Image", result);
}
existed.ImageUrl.DeleteFile(_env.WebRootPath, "assets/img");
existed.ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"));
return View();
}
existed.PositionId=employeeVM.PositionId;
existed.FullName=employeeVM.FullName;
existed.ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"));
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> Create(CreateEmployeeVM employeeVM)
{
if (!_context.Positions.Any(p => p.Id == employeeVM.PositionId)) ModelState.AddModelError("PositionId", "bele bir position yoxdu");
if (!ModelState.IsValid)
{
ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
return View();
}
string result = employeeVM.Image.CheckValidate(500,"image/");
if (result.Length > 0)
{
ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
ModelState.AddModelError("Image", result);
return View();
}
Employee employee = new Employee
{
Name = employeeVM.Name,
Surname = employeeVM.Surname,
PositionId = employeeVM.PositionId,
FacebookUrl = employeeVM.FacebookUrl,
InstagramUrl = employeeVM.InstagramUrl,
TwitterUrl = employeeVM.TwitterUrl,
Salary = employeeVM.Salary,
ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"))
};
await _context.Employees.AddAsync(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}

Data synchronization (validation) between two clients

I have a webshop built on ASP.NET Boilerplate (Angular frontend and MSSQL database).
The webshop contains items and I want to keep an inventory of these items.
Every time an order is created the inventory is updated. So basically I have a database with Webshops, Items and Orders.
I have repositories and managers for these objects.
All works fine, but the issue occurs when two clients at the same time load the webshop.
Client1 opens webpage:
Webshop1
Item1: "10 items available"
Item2: "8 items available"
Client2 opens webpage at the same time:
Webshop1
Item1: "10 items available"
Item2: "8 items available"
The first one that buys all the available items, should be able to create an order and the second one should get an error.
When an order is created, the backend checks if there are enough items available.
But when the webshop is loaded BEFORE the order of the first client is created, the second client does not know the updated inventory and will be able to create the order as well.
Meaning 20 items of Item1 can be sold!
How do I "sync" the data between the two sessions in the backend? It seems somehow the data is cached in the backend when loading the webshop.
CreateOrder function
public async Task<CreateOrderResponseDto> Create(CreateOrderDto input, long? userId)
{
input.OrderItems.ForEach(async o =>
{
if (!(await _salesItemManager.ReserveStock(o.SalesItemId, o.Quantity)).IsSuccess)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
});
var salesPage = await _salesPageManager.Get(input.SalesPageId, false);
if (salesPage.GetState() != StatePage.Published)
{
throw CodeException.ToAbpValidationException("Order", "PageNotAvailable");
}
if (salesPage.CommentsRequired.HasValue && salesPage.CommentsRequired.Value)
{
if (string.IsNullOrWhiteSpace(input.Description))
{
throw CodeException.ToAbpValidationException("Order", "CommentsRequired");
}
}
var order = new Order
{
Address = input.Address,
City = input.City,
LastName = input.LastName,
Name = input.Name,
PostalCode = input.PostalCode,
Email = input.Email,
PhoneNumber = input.PhoneNumber,
Description = input.Description,
SalesPage = salesPage
};
try
{
order.Price = await _salesItemManager.GetPriceByOrders(input.OrderItems);
order = await _orderRepository.InsertAsync(order);
input.OrderItems.ForEach(async o =>
{
var orderItem = new OrderItem();
orderItem.SalesItemId = o.SalesItemId;
orderItem.OrderId = order.Id;
orderItem.Quantity = o.Quantity;
await _orderItemRepository.InsertAsync(orderItem);
});
if (input.SelectedSalesPageOptionId.HasValue)
{
order.SalesOption = await _salesPageManager.GetOption(input.SelectedSalesPageOptionId.Value);
}
}
catch (Exception e)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
if (userId.HasValue && salesPage.User.Id == userId.Value)
{
var payment = await _paymentManager.CreateManualPayment(order, input.IsPaid);
order.Payment = payment;
return new CreateOrderResponseDto() { IsSuccess = true, PaymentUrl = string.Empty, OrderId = order.Id.ToString() };
}
else
{
var payment = await _paymentManager.CreatePayment(order);
order.Payment = payment;
return new CreateOrderResponseDto() { IsSuccess = true, PaymentUrl = payment.PaymentUrl, OrderId = order.Id.ToString() };
}
}
ReserveStock function
public async Task<GeneralDto> ReserveStock(Guid itemId, int quantity)
{
var salesItem = await _salesItemRepository.GetAsync(itemId);
if (salesItem == null || salesItem.Stock == null || salesItem.ReservedStock == null)
return new GeneralDto() { IsSuccess = false };
if (salesItem.Stock < quantity)
{
return new GeneralDto() { IsSuccess = false };
}
salesItem.Stock -= quantity;
salesItem.ReservedStock += quantity;
try
{
await _salesItemRepository.UpdateAsync(salesItem);
}
catch (Exception e)
{
throw CodeException.ToAbpValidationException("SalesItem", "SalesItemUpdate");
}
return new GeneralDto() { IsSuccess = true };
}
The problem is not that the data is cached.
The problem is that your ReserveStock checks are async tasks that are not awaited by the caller:
input.OrderItems.ForEach(async o =>
{
if (!(await _salesItemManager.ReserveStock(o.SalesItemId, o.Quantity)).IsSuccess)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
});
Assign your async ReserveStock checks to an array of tasks that is awaited by the caller:
var reserveStockChecks = input.OrderItems.Select(async o =>
{
if (!(await _salesItemManager.ReserveStock(o.SalesItemId, o.Quantity)).IsSuccess)
{
throw CodeException.ToAbpValidationException("OrderItem", "OrderItemCreate");
}
}).ToArray();
await Task.WhenAll(reserveStockChecks);

Your Campaign is not ready to send in mailchimp api v3 using C#

I created code to send campaign immediately by consuming mailchimp api v3.0 using C# console. When i tried in free account everything goes well, but when i upgrade my account in premium i got this problem (only add 2 members).
My scenario:
create audience => success
add member subscriber into audience that i created => success
create campaign with specific template => success
send cehcklist in campaign already created => return is_ready false
send campaign => return Your Campaign is not ready to send
When I try to run my console program using console c# consume mailchimp api I got this error:
Type: http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/
Title: Bad Request
Status: 400
Detail: Your Campaign is not ready to send.
instance: 214b85f4-a288-44e7-b890-35925d8601ac
When I checked campaign into mailchimp website portal, I saw a message like this:
To send, you need at least 1 subscriber in your list.
This means that there is no recipients in my campaign, here is detail screenshot:
Please has anyone ever faced this, too? I really appreciate any suggestions.
Is there any way to resolve that issue before sending campaign? Because when I checked mailchimp portal (based on screenshot shown above), I back into campaign list then open my campaign above the problem automatically resolve, this is my confusing one.
Because mailchimp api v3.0 has limitation only 500 members subscriber on one call, finally I created class to partition my list:
//partition list of members more than 500
public static class Extensions
{
public static List<List<T>> SplitPartition<T>(this IEnumerable<T> collection, int size)
{
var chunks = new List<List<T>>();
var count = 0;
var temp = new List<T>();
foreach (var element in collection)
{
if (count++ == size)
{
chunks.Add(temp);
temp = new List<T>();
count = 1;
}
temp.Add(element);
}
chunks.Add(temp);
return chunks;
}
}
this my main code using several scenario to handle single method can call in many way:
public class MailChimpProcessor
{
static MailChimpProcessor()
{
//initialize
ApiHelper.InitializeClient(baseUrl, apiKey);
}
public class MailChimpResponse
{
public string result { get; set; }
public GlobalErrorResponseModel error { get; set; }
}
public static MailChimpResponse MailChimpSendCampaign(SendEmailCampaignModel model)
{
MailChimpResponse mailchimpResult = new MailChimpResponse();
#region PROPERTY OBJECT AUDIENCE
Contact contact = new Contact()
{
company = model.audience_company,
address1 = model.audience_address1,
address2 = model.address2Config,
city = model.audience_city,
state = model.audience_state,
zip = model.audience_zip,
country = model.audience_country,
phone = model.phoneConfig
};
CampaignDefaults campaign = new CampaignDefaults()
{
from_name = model.campaign_from_name,
from_email = model.campaign_reply_to,
subject = model.campaign_subject,
language = "en"
};
AudienceRequestModel audienceModel = new AudienceRequestModel();
audienceModel.name = model.audience_name;
audienceModel.contact = contact;
audienceModel.permission_reminder = permissionReminderConfig;
audienceModel.use_archive_bar = true;
audienceModel.campaign_defaults = campaign;
audienceModel.notify_on_subscribe = "";
audienceModel.notify_on_unsubscribe = "";
audienceModel.email_type_option = true;
#endregion
#region PROPERTY OBJECT MEMBER
List<Member> members = new List<Member>();
//prevent duplicate email_address
var queryMemberList = model.members.GroupBy(x => x.email_address).Select(x => x.First());
foreach (var item in queryMemberList)
{
members.Add(new Member
{
email_address = item.email_address.ToLower(),
status = "subscribed",
status_if_new = "subscribed",
merge_fields = new MergeFields()
{
FNAME = item.merge_fields.FNAME,
LNAME = item.merge_fields.LNAME
}
});
}
bool isUploadContact = false;
int offset = 0;
const int numberPerBatch = 500; // maximum member per execution.
double LoopMax = Math.Ceiling(members.Count / (double)numberPerBatch);
//partition array
var PartitionMembers = members.SplitPartition(numberPerBatch);
#endregion
//create audience using post method
var audienceResult = AudienceProcessor.PostAudienceAsync(audienceModel).Result;
#region PROPERTY OBJECT CAMPAIGN
Recipients recipient = new Recipients()
{
list_id = audienceResult.ResponseModel != null ? audienceResult.ResponseModel.id : "0"
};
Settings setting = new Settings()
{
subject_line = model.campaign_subject,
title = model.campaign_title,
reply_to = model.campaign_reply_to,
from_name = model.campaign_from_name,
template_id = model.campaign_template_id
};
CampaignRequestModel campaignModel = new CampaignRequestModel();
campaignModel.recipients = recipient;
campaignModel.type = "regular";
campaignModel.settings = setting;
#endregion
if (audienceResult.ResponseModel != null)
{
MemberProcessor.MemberResponse memberResult = new MemberProcessor.MemberResponse();
while (offset < LoopMax)
{
MemberRequestModel memberModel = new MemberRequestModel();
memberModel.members = PartitionMembers[offset];//list based on index of array
memberModel.update_existing = true;
//post contact member
memberResult = MemberProcessor.PostContatcAsync(memberModel, audienceResult.ResponseModel.id).Result;
if (memberResult.ResponseModel != null)
{
isUploadContact = true;
}
else
{
isUploadContact = false;
}
offset++; // increment
}
//create campaign
if (isUploadContact)//belum tereksekusi
{
//sleep thread 20 seconds after upload subcriber members
System.Threading.Thread.Sleep(20000);
//create campaign using post method
var campaignResult = CampaignProcessor.PostCampaignAsync(campaignModel).Result;
if (campaignResult.ResponseModel.id != null)
{
#region USING ITERATION TO CHECK CAMPAIGN
CampaignProcessor.CampaignResponseCheckList campaignChecklist = new CampaignProcessor.CampaignResponseCheckList();
bool isReadySend = false;
int check = 0;
while (check <= 10) //maksimum 10 iteration
{
//check campaign using get method
campaignChecklist = CampaignProcessor.GetCheckListCampaign(campaignResult.ResponseModel.id).Result;
if (campaignChecklist.ResponseModel.is_ready == true) //when error model is not null
{
isReadySend = true;
break;
}
else
{
isReadySend = false;
}
System.Threading.Thread.Sleep(1000); // will puase every 1 second
check++;
}
if (isReadySend)
{
//sleep action before send campaign
System.Threading.Thread.Sleep(2000);
//send campaign
var sendCampaignResult = CampaignProcessor.SendCampaignAsync(campaignResult.ResponseModel.id).Result;
if (sendCampaignResult.ErrorModel == null)
mailchimpResult.result = sendCampaignResult.ResponseModel;
else
mailchimpResult.error = sendCampaignResult.ErrorModel; //i got this return indicate that my campaign is not ready
}
else
{
mailchimpResult.error = campaignChecklist.ErrorModel;
mailchimpResult.result = $"failed Check List Campaign / Your Campaign is not ready to send.";
}
#endregion
}
else
{
mailchimpResult.error = campaignResult.ErrorModel;
mailchimpResult.result = "failed create Campaign";
}
}
else
{
mailchimpResult.result = $"failed create contact: {offset}";
mailchimpResult.error = memberResult.ErrorModel;
}
}
else
{
mailchimpResult.error = audienceResult.ErrorModel;
mailchimpResult.result = "failed create Audience";
}
return mailchimpResult;
}
}
Try this code below
System.Threading.Thread.Sleep(40000); //try change this one
//create campaign using post method
var campaignResult = CampaignProcessor.PostCampaignAsync(campaignModel).Result;
if (campaignResult.ResponseModel.id != null)
{
#region USING ITERATION TO CHECK CAMPAIGN
CampaignProcessor.CampaignResponseCheckList campaignChecklist = new CampaignProcessor.CampaignResponseCheckList();
bool isReadySend = false;
int check = 0;
while (true) //just change this condition
{
//check campaign using get method
campaignChecklist = CampaignProcessor.GetCheckListCampaign(campaignResult.ResponseModel.id).Result;
if (campaignChecklist.ResponseModel.is_ready == true) //when error model is not null
{
isReadySend = true;
break;
}
else
{
isReadySend = false;
}
check++;
}
if (isReadySend)
{
//send campaign
var sendCampaignResult = CampaignProcessor.SendCampaignAsync(campaignResult.ResponseModel.id).Result;
if (sendCampaignResult.ErrorModel == null)
mailchimpResult.result = sendCampaignResult.ResponseModel;
else
mailchimpResult.error = sendCampaignResult.ErrorModel; //i got this return indicate that my campaign is not ready
}
else
{
mailchimpResult.error = campaignChecklist.ErrorModel;
mailchimpResult.result = $"failed Check List Campaign / Your Campaign is not ready to send.";
}
#endregion

CRM workflow: How to get all the records from a subgrid as a list of entities and perform multi-retrieve

As the title suggests, I do not know how to convert entity.attributes ["subgrid"] as a list of entities, on which to run the multiretrieve:
My code for now:
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
var entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName != "account")
{
return;
}
var currentAccountId = entity.Id;
try
{
if (!entity.Contains("Subgrid"))
{
return;
}
var itemsOnSubgrid = entity.Attributes["Subgrid"];
if(itemsOnSubgrid == null)
{
return;
}
else
{
//if subgrid exist and is not null
//List of entities needed
}
}
catch (Exception ex)
{
tracingService.Trace("MyWorkflow: {0}", ex.ToString());
throw new InvalidPluginExecutionException(ex.Message);
}
}
As you are writing code in a custom workflow assembly - the entity at this point does not know anything about the form it is being called from, and does not have a "Subgrid" property to allow you to access the related records.
You will need to do a sperate query to retrieve related contacts (as an example) using the target entity's "accountid" property to relate to the contacts' "parentcustomerid" property.
Assume you are looking for a method to get all associated records for a particular record.
If that is the case, I would have written something like this. Hope that helps.
private EntityCollection GetAssociatedRecords(string relationshipName, string relatedEntityName, string entityName, Guid entityId,OrganizationService service)
{
EntityCollection result = null;
try
{
QueryExpression query = new QueryExpression();
query.EntityName = relatedEntityName;
query.ColumnSet = new ColumnSet(false);
Relationship relationship = new Relationship();
relationship.SchemaName = relationshipName;
relationship.PrimaryEntityRole = EntityRole.Referencing;
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(relationship, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet(true);
request.Target = new EntityReference
{
Id = entityId,
LogicalName = entityName
};
RetrieveResponse response = (RetrieveResponse)service.Execute(request);
RelatedEntityCollection relatedEntityCollection = response.Entity.RelatedEntities;
if (relatedEntityCollection.Count > 0)
{
if (relatedEntityCollection.Values.Count > 0)
{
result = (EntityCollection)relatedEntityCollection.Values.ElementAt(0);
}
}
}
catch (Exception exception)
{
throw exception;
}
return result;
}
In that based on the role of the other entity change the Primary Entity Role between Referencing and Referenced.
Hope that helps. Let me know if my assumption is wrong.

Create/Update method not allowed in "Activity Pointer" CRM 2011

Am having a plugin that moves the activities of lead to opportunity on qualify. I have registered the plugin on "Create" of opportunity and the following is the code
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
entity = (Entity)context.InputParameters["Target"];
if (entity.Attributes.Contains("originatingleadid") == false) return;
}
else
{
return;
}
try
{
//.....
EntityReference Lead = (EntityReference)entity.Attributes["originatingleadid"];
Guid LeadGuid = Lead.Id;
MoveActivitiesFromLeadToOpportunity(service, LeadGuid, Opportunityid);
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException(
"An error occurred in the plug-in.", ex);
}
}
private void MoveActivitiesFromLeadToOpportunity(IOrganizationService service, Guid LeadID, Guid OpportunityID)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "regardingobjectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(LeadID.ToString());
var query = new QueryExpression("activitypointer");
query.Criteria.AddCondition(condition);
//query.Conditions.Add("reagrdingobjectid", ConditionOperator.Equal, theIdOfTheRelatedRecord);
query.ColumnSet = new ColumnSet(true);
var activities = service.RetrieveMultiple(query).Entities;
foreach (var activity in activities)
{
var castedActivity = (ActivityPointer)activity;
if (castedActivity.ActivityTypeCode == "email")
{
castedActivity.Id = Guid.NewGuid();
castedActivity["regardingobjectid"] = new EntityReference("opportunity", OpportunityID);
//service.Create(castedActivity);--->Exception thrown
//service.Update(castedActivity);---->Tried this one too.Exception is thrown stating method not supported on "ActivityPointer"
}
}
Can somebody shed light on this? Am i missing something here? Thank you
You need to query for the exact entity type, because you can't update an activitypointer
private void MoveEmailsFromLeadToOpportunity(IOrganizationService service, Guid LeadID, Guid OpportunityID)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "regardingobjectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(LeadID.ToString());
var query = new QueryExpression("email");
query.Criteria.AddCondition(condition);
query.ColumnSet = new ColumnSet(true);
var emails = service.RetrieveMultiple(query).Entities;
foreach (var email in emails)
{
email["regardingobjectid"] = new EntityReference("opportunity", OpportunityID);
service.Update(email);
}
}
you can also write a method that will retrieve first all the activities (as you already did) check the ActivityTypeCode after retrieve and update each single record depending on activity type (email, fax, ...)
Try commenting out this line:
castedActivity.Id = Guid.NewGuid();
And then just do your Update:
service.Update(castedActivity)
You are just updating the RegardingObjectId, not creating a new activity, so you shouldn't change the Id and you shouldn't use Create.

Categories