22.05.2015, 00:28 | #1 |
Участник
|
Incident Resolution In CRM Online 2013
Коллеги, добрый вечер!
Давно не писал под СРМ, хотелось бы узнать какое решение выбрать. Пытаемся внедрить ITIL, используем базовую сущность - Обращение (Incident). Добавил три кастомных поля: Факт. реакция, Дата Завершения и Затраченное время. Так вот, js заполняю поле Факт. реакция, а дату Завершения и Затраченное время устанавливаю в процессе закрытия обращения плагином
X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using Microsoft.Xrm.Sdk.Query; using System.ServiceModel.Description; using System.ServiceModel; using System.Globalization; namespace AmicaPackage.SetCaseDurationPlugin { public class SetFactDuration : IPlugin { //Resolved public readonly int problemResolved = 5; public readonly int infoGranted = 1000; public void Execute(IServiceProvider ServiceProvider) { IPluginExecutionContext Context = (IPluginExecutionContext)ServiceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory ServiceFactory = (IOrganizationServiceFactory)ServiceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService Service = ServiceFactory.CreateOrganizationService(Context.UserId); ITracingService tracingService = (ITracingService)ServiceProvider.GetService(typeof(ITracingService)); if (Context.PostEntityImages.Contains("PostImage") && Context.PostEntityImages["PostImage"] is Entity) { if (Context.Depth > 1) return; Entity incident = (Entity)Context.PostEntityImages["PostImage"]; var startDate = incident.GetAttributeValue<DateTime>("new_factreaction"); var dueDate = DateTime.Now; var statusCode = ((OptionSetValue)incident["statuscode"]).Value; if (statusCode == problemResolved || statusCode == infoGranted) { if (startDate != null) { var minutes = Math.Abs(Math.Round(((startDate - dueDate).TotalMinutes), 2)); incident.Attributes.Add("new_facttime", dueDate); incident.Attributes.Add("new_duedate", dueDate); incident.Attributes.Add("new_timediff", minutes); } } Service.Update(incident); } } } } Как правильно апдейтить поля после завершения кейса? Последний раз редактировалось GetLucky; 22.05.2015 в 00:42. |
|
22.05.2015, 08:52 | #2 |
Чайный пьяница
|
Никак. Закрытую запись редактировать есть только 2 варианта - Открыть, отредактировать, закрыть.
Пересмотрев ваш вопрос ещё раз - переделывайте плагин на Pre-Operation и будет вам счастье.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit Последний раз редактировалось a33ik; 22.05.2015 в 11:37. |
|
22.05.2015, 09:40 | #3 |
Участник
|
Это можно реализовать процессом (которые раньше бизнес-процессами назывались), регистрировать на Условие запуска - Перед - Изменение статуса записи, Обновить сущность и устанавливаете нужные поля. Работает.
|
|
22.05.2015, 15:25 | #4 |
Участник
|
|
|
22.05.2015, 15:52 | #5 |
Еда - топливо, Одежда - н
|
есть такое понятие как преобразование процесса в риалтайм. Кнопочка сверху.
По сути это синхронный плагин )
__________________
Все что вам нужно - это мозК Еда - топливо... Одежда - необходимость... |
|
22.05.2015, 16:26 | #6 |
Участник
|
|
|
22.05.2015, 16:53 | #7 |
Еда - топливо, Одежда - н
|
__________________
Все что вам нужно - это мозК Еда - топливо... Одежда - необходимость... |
|
22.05.2015, 21:50 | #8 |
Участник
|
|
|
22.05.2015, 22:21 | #9 |
Участник
|
Нашел более правильное решение, т.к. Case переводиться в состояния закрыто с использованием сущности IncidentResolution, то вполне логично повесить на создание этой сущности плагин, который на Post-operation будет апдейтить Кейс.
X++: public class CaseResolution : IPlugin { public void Execute(IServiceProvider serviceProvider) { #region must to have IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); // Create service with context of current user IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); //create tracing service ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); #endregion #region Variable Entity targetCase = new Entity("incident"); string strResolution = string.Empty; int intTotalTime = -1; int intTotalBillableTime = -1; string strRemarks = string.Empty; #endregion if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { //create entity context Entity entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName != "incidentresolution") return; try { if (entity.Contains("incidentid")) { //get the related Case targetCase.Id = ((EntityReference)entity["incidentid"]).Id; //capture the Case Resolution Fields strResolution = entity.Contains("subject") ? entity["subject"].ToString() : string.Empty; intTotalBillableTime = entity.Contains("timespent") ? (Int32)entity["timespent"] : 0; strRemarks = entity.Contains("description") ? (entity["description"] != null ? entity["description"].ToString() : string.Empty) : string.Empty; //get the total time from Activities intTotalTime = GetTotalTime(service, targetCase.Id); //update Case with the fields targetCase["new_resolution"] = strResolution; targetCase["new_totalbillabletime"] = intTotalBillableTime; targetCase["new_totaltime"] = intTotalTime; targetCase["new_remark"] = strRemarks; service.Update(targetCase); } } catch (Exception ex) { throw new InvalidPluginExecutionException(ex.Message); } } } private int GetTotalTime(IOrganizationService service, Guid guidRelatedCaseId) { //count the Activity Actual Duration Minutes for this Case //need to sum time spent of each activity (cannot directly using the actualtdurationminutes) int intSumTotalTime = 0; //Retrieve all related Activities by Case QueryExpression query = new QueryExpression("activitypointer"); query.ColumnSet.AddColumns("actualdurationminutes"); query.Criteria = new FilterExpression(); query.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, guidRelatedCaseId); // Execute the Query EntityCollection results = service.RetrieveMultiple(query); foreach (Entity entity in results.Entities) { int intActivityTime = 0; intActivityTime = entity.Contains("actualdurationminutes") ? (Int32)entity["actualdurationminutes"] : 0; intSumTotalTime = intSumTotalTime + intActivityTime; } return intSumTotalTime; } } Последний раз редактировалось GetLucky; 22.05.2015 в 22:55. |
|
24.05.2015, 17:16 | #10 |
Еда - топливо, Одежда - н
|
На самом деле, в 2013 уже есть такая тема, как подсчет затраченного времени.
В контрактах учитывается и в "entitlement" не знаю как это на русском объяснить Посмотрите стандартный функционал, и ненадо писать плагины.
__________________
Все что вам нужно - это мозК Еда - топливо... Одежда - необходимость... |
|
24.05.2015, 21:55 | #11 |
Участник
|
У клиента свой процесс, поэтому в нашем use case надо было именно так сделать
|
|
|
|