0% found this document useful (0 votes)
51 views6 pages

Static Namespace Public Sealed Class Private Const Decimal Private Const Int Private Private

This code activity retrieves bookable resources and holidays from a CRM system. It compares the holidays for each bookable resource to identify any missing holidays. For each missing holiday, it creates and approves a time entry record for the bookable resource if the holiday and resource locations match. It also handles removing time entries if a holiday is no longer associated with a bookable resource's location.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views6 pages

Static Namespace Public Sealed Class Private Const Decimal Private Const Int Private Private

This code activity retrieves bookable resources and holidays from a CRM system. It compares the holidays for each bookable resource to identify any missing holidays. For each missing holiday, it creates and approves a time entry record for the bookable resource if the holiday and resource locations match. It also handles removing time entries if a holiday is no longer associated with a bookable resource's location.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

using System;

using System.Activities;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using static HolidaysManagement.Helpers;

namespace HolidaysManagement
{
public sealed class AddHolidaysForBookableResources : CodeActivity
{
private const decimal ResourceWorkingHours = 8m;
private const int PayableHoursType = 100000000;

private IOrganizationService OrgService;


private ITracingService TracingService;

[Input("HolidayIds")]
[RequiredArgument]
public InArgument<string> HolidayIds { get; set; }

private class EntityComparer : EqualityComparer<Entity>


{
private readonly bool isReverse = false;
public EntityComparer(bool isReverse = false)
{
this.isReverse = isReverse;
}

public override bool Equals(Entity x, Entity y)


{
return isReverse ? x.Id.Equals(y.Id) : !x.Id.Equals(y.Id);
}

public override int GetHashCode(Entity obj)


{
return obj.Id.GetHashCode();
}
}

protected override void Execute(CodeActivityContext executionContext)


{
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationSer
viceFactory>();
TracingService = executionContext.GetExtension<ITracingService>();
OrgService = serviceFactory.CreateOrganizationService(context.UserId);

TracingService.Trace($"Message");
try
{
string[] holidayIds = HolidayIds.Get(executionContext).Split(',').ToArray();
IEnumerable<Entity> holidays = GetHolidays(OrgService, holidayIds);
IEnumerable<Entity> bookableResources = GetBookableResources();
foreach (Entity bookableResource in bookableResources)
{
Guid brId = bookableResource.Id;
DateTime brStartDate = bookableResource.GetAttributeValue<DateTime>("amc_startdate"
);
DateTime? brEndDate = null;
if (bookableResource.Contains("amc_enddate"))
{
brEndDate = bookableResource.GetAttributeValue<DateTime>("amc_enddate");
}
int brTargetUtilization = bookableResource.GetAttributeValue<int>("msdyn_targetutil
ization");
IEnumerable<Entity> brHolidays = GetBookableResourceHolidays(bookableResource.Id);

Entity[] missingHolidays = holidays.Except(brHolidays, new EntityComparer()).ToArra


y();
int holidayDuration = RoundDecimalToInt(ResourceWorkingHours * brTargetUtilization
* 0.6m);

//_Log($"Missing Holidays = {missingHolidays.Select(x => x.ToString()).ToString()}"


);
foreach (Entity holiday in missingHolidays)
{
DateTime holidayDate = holiday.GetAttributeValue<DateTime>("amc_date");
if (holidayDate < brStartDate || holidayDate > brEndDate)
continue;

// TODO: Separate to location comparer


var eLoc = bookableResource.GetAttributeValue<OptionSetValue>("amc_employee_loc
ation").Value;
var hLoc = holiday.GetAttributeValue<OptionSetValue>("amc_holiday_location").Va
lue;
_Log($"= LOCATION / brID = {brId}, brLoc = {eLoc}, holidLoc = {hLoc}");

if (eLoc != hLoc)
{
continue;
}

CreateApprovedHolidayForBookableResource(bookableResource.Id, holiday, holidayD


uration);
}
_Log("* OK");

try
{
// Change to union or other
Entity[] leftHolidays = holidays.Except(brHolidays, new EntityComparer(true)).T
oArray();
_Log($"Count holids = {leftHolidays.Count().ToString()}");
foreach (Entity holiday in leftHolidays)
{
_Log($"* IN CYCLE / brID = {brId}, holidLocObj = {holiday.GetAttributeValue
<OptionSetValue>("amc_holiday_location")}");
var eLoc = bookableResource.GetAttributeValue<OptionSetValue>("amc_employee
_location").Value;
var hLoc = holiday.GetAttributeValue<OptionSetValue>("amc_holiday_location"
).Value;

if (eLoc != hLoc)
{
_Log("* IN IF");
// Delete holiday for thit BR

// GET TE ID

var query = new QueryExpression


{
EntityName = "msdyn_timeentry",
ColumnSet = new ColumnSet("amc_type", "msdyn_date"),
Criteria = new FilterExpression(LogicalOperator.And),
};
query.Criteria.AddCondition("amc_type", ConditionOperator.Equal, 100000
003);
query.Criteria.AddCondition("msdyn_bookableresource", ConditionOperator
.Equal, bookableResource.Id);
//msdyn_timeentryid
var a = OrgService.RetrieveMultiple(query).Entities.Count;
_Log($"###### - {a}");
// return OrgService.RetrieveMultiple(query).Entities;

var id = holiday.GetAttributeValue<Guid>("timeEntry");
_Log($"ID IN CYCLE = {id}");
// FIXME: This need id, current id == Guid(000-00)
var holidayTimeEntry = new Entity("msdyn_timeentry", id);

holidayTimeEntry["msdyn_entrystatus"] = new OptionSetValue(192354320);


OrgService.Update(holidayTimeEntry);

OrgService.Delete("msdyn_timeentry", id);
}
}

}
catch (Exception ex)
{
_Log($"* Hy TyT KaK Bce {ex.Message}");
}
}
}
catch (Exception ex)
{
TracingService.Trace($"Unhandled exception occurred!\nMessage: {ex.Message}\nStack trac
e: {ex.StackTrace}");
}
}

private int RoundDecimalToInt(decimal value) => decimal.ToInt32(decimal.Round(value, MidpointRo


unding.AwayFromZero));

private void CreateApprovedHolidayForBookableResource(Guid bookableResourceId, Entity holiday,


int duration)
{
_Log("= MID / CreateApprovedHolidBR");
DateTime holidayDate = holiday.GetAttributeValue<DateTime>("amc_date");
var holidayTimeEntry = new Entity("msdyn_timeentry")
{
Attributes = new AttributeCollection()
{
{ "msdyn_bookableresource", new EntityReference("bookableresource", bookableResourc
eId) },
{ "msdyn_date", holidayDate },
{ "msdyn_duration", duration },
{ "amc_hourstype", new OptionSetValue(PayableHoursType) },
{ "amc_type", new OptionSetValue(HolidayTimeEntryType) },
{ "amc_holiday", holiday.ToEntityReference() },
{ "amc_isaddedbyhrmanager", true }
}
};
try
{
Guid holidayTimeEntryId = OrgService.Create(holidayTimeEntry);
ApproveHolidayTimeEntry(holidayTimeEntryId);
}
catch (Exception ex)
{
_Log($"= MID / Skip 24 hours error for brID = {bookableResourceId}");
// TODO: ?
}
}

private void ApproveHolidayTimeEntry(Guid holidayTimeEntryId)


{
var holidayTimeEntry = new Entity("msdyn_timeentry", holidayTimeEntryId);
holidayTimeEntry["msdyn_entrystatus"] = new OptionSetValue(TimeEntrySubmittedState);
OrgService.Update(holidayTimeEntry);
holidayTimeEntry["msdyn_entrystatus"] = new OptionSetValue(TimeEntryApprovedState);
OrgService.Update(holidayTimeEntry);
}
private IEnumerable<Entity> GetBookableResources()
{
var query = new QueryExpression("bookableresource");
query.ColumnSet.AddColumns("amc_startdate", "amc_enddate", "msdyn_targetutilization", "amc_
employee_location");
query.Criteria.AddCondition("amc_startdate", ConditionOperator.NotNull);
query.Criteria.AddCondition("amc_employee_location", ConditionOperator.NotNull); // TODO: T
est case without this condition
query.Criteria.AddCondition("resourcetype", ConditionOperator.Equal, 3);

return OrgService.RetrieveMultiple(query).Entities;
}

private void _Log(string message) => TracingService.Trace(message);

private IEnumerable<Entity> GetBookableResourceHolidays(Guid bookableResourceId)


{
_Log($"= IN / brID = {bookableResourceId}");
var query = new QueryExpression("msdyn_timeentry");
var brHolidays = new List<Entity>();
try
{
int currentYear = DateTime.Now.Year;

query.ColumnSet.AddColumns("amc_holiday", "msdyn_timeentryid");
query.Criteria.AddCondition("amc_type", ConditionOperator.Equal, HolidayTimeEntryType);
query.Criteria.AddCondition("msdyn_date", ConditionOperator.Between, new DateTime(curre
ntYear, 1, 1), new DateTime(currentYear + 1, 1, 1));
query.Criteria.AddCondition("msdyn_bookableresource", ConditionOperator.Equal, bookable
ResourceId);

IEnumerable<Entity> holidayTimeEntries = OrgService.RetrieveMultiple(query).Entities;

foreach (Entity holidayTimeEntry in holidayTimeEntries)


{
EntityReference holidayRef = holidayTimeEntry.GetAttributeValue<EntityReference>("a
mc_holiday");
_Log($"= MID / holidRef.ID = {holidayRef.Id}");
var holiday = new Entity(holidayRef.LogicalName, holidayRef.Id);

// FIXME
holiday.Attributes.Add("timeEntry", holidayTimeEntry.GetAttributeValue<Guid>("msdyn
_timeentryid"));

brHolidays.Add(holiday);
}

_Log($"= END / NORMAL");


return brHolidays;
}
catch (Exception ex)
{
_Log($"= END / ERROR");
TracingService.Trace($"ex = {ex}, brID = {bookableResourceId}, query = {query}, brHolid
ays = {brHolidays}");
}

_Log($"= END / EMPTY LIST");


return new List<Entity>();
}
}
}

You might also like