Skip to main content

Compute Dates from Periodicities

This workflow is included in the Scheduling package.

Description​

Outputs dates matching periodicities given a range specified by start date and either an end date or a number of dates.

Properties​

This workflow has the following properties.

PropertyValue
NameCompute Dates from Periodicities
Codeworkflows_computeDatesFromPeriodicities_8e453842273351d387ab2939
TypeWorkflow
ContextPackage
EnabledYes
TagsCauseway
Log retention7 days

Trigger​

A user triggers this workflow on demand, or another workflow runs it (via an MWR). It works on the items of the design below.

PropertyValue
Workflow typeManual workflow
Applies toPeriodicities
Output modeManyItems  (Runs once for all items)
Parameters designMTP - Compute Dates from Periodicities
Output actionThe Output action highlighted in the diagram below

Actions​

This workflow runs 4 actions, in the order shown in this simplified diagram. Every action's full settings are in the configuration below.

Configuration​

The full configuration of this workflow, including every action's parameters.

Show configuration (300 lines)
{
"trigger": {
"dodiCode": "designInterfaces_periodicity_68109e5096e0ec0345072f8a",
"parametersDesignCode": "designs_computeDatesFromPeriodicities_874950917130ef4b6ae2e28c",
"outputActionId": "82a1a421812ef49e2976533c",
"outputMode": "ManyItems"
},
"actions": [
{
"actionId": "68261b9ca71675a82f2ee892",
"designCode": "designs_workflowFilterAction",
"description": "if it's a normal periodicity....",
"parameters": [
{
"attribute": {
"attributeCode": "attributes_workflowFilterActionsAqsQuery",
"value": {
"type": "Query",
"properties": {
"dodiCode": "designs_periodicity_8f3183380533b281ac719c10",
"collectionCode": "Live",
"attributes": [
"attributes_itemsTitle",
"attributes_itemsSubtitle"
]
}
},
"attributeType": "Aqs"
}
}
],
"variables": [],
"actions": []
},
{
"actionId": "68261ba28d57c1b3124ec4d2",
"designCode": "designs_workflowFilterAction",
"description": "if it's a periodicity for relative schedule....",
"parameters": [
{
"attribute": {
"attributeCode": "attributes_workflowFilterActionsAqsQuery",
"value": {
"type": "Query",
"properties": {
"dodiCode": "designs_periodicityWithoutDateRange_68132f2da41c45eca2072f8a",
"collectionCode": "Live",
"attributes": [
"attributes_itemsTitle",
"attributes_itemsSubtitle"
]
}
},
"attributeType": "Aqs"
}
}
],
"variables": [],
"actions": []
},
{
"actionId": "682700fc420340e3121c01b0",
"designCode": "designs_workflowOutputAction",
"comments": "Compute schedule's matching dates",
"parameters": [
{
"attributeCode": "attributes_workflowOutputActionData",
"value": {
"script": "var relativeStart = relativePeriodicityItemId.Any() && lastCompletion != null ? new []{ Json(new { dates = new [] { Date(firstPossibleNext) }.ToArray() }) }.ToArray() : List<JObject>().ToArray(); \r\n\r\nvar allStartsOns = relativePeriodicityItemId.Any() ? relativeStart : Variables.cyclicalPeriodicityStartsOn.AllValues.Values.Select(x => x.SingleValue).ToArray();\r\nvar allEndsOns = relativePeriodicityItemId.Any() ? relativeStart.Select(x => Date(Now.AddYears(1000))).ToArray() : Variables.cyclicalPeriodicityEndsOn.AllValues.Values.Select(x => x.SingleValue).ToArray();\r\n var allRepeats = (relativePeriodicityItemId.Any() ? Variables.relativePeriodicityRepeat : Variables.cyclicalPeriodicityRepeat).AllValues.Values.Select(x => x.SingleValue).ToArray();\r\n var allValidOns = (relativePeriodicityItemId.Any() ? Variables.relativePeriodicityValidOn : Variables.cyclicalPeriodicityValidOn).AllValues.Values.Select(x => x.SingleValue).ToArray();\r\n var allNextDates = (relativePeriodicityItemId.Any() ? Variables.relativePeriodicityNextDate : Variables.cyclicalPeriodicityNextDate).AllValues.Values.Select(x => x.SingleValue).ToArray();\r\n var allData = Enumerable.Range(0, allStartsOns.Length).Select(i => new object[] { allStartsOns[i], allEndsOns[i], allRepeats[i], allValidOns[i], allNextDates[i] }).ToArray();\r\n return Json(new { items = \r\n allData.Select(x =>\r\n new {\r\n attributes_periodicityStartsOnInclusive_863726baef05061cd5adad15 = x[0],\r\n attributes_periodicityEndsOnExclusive_897d0b7250920fc60c072bf1 = x[1],\r\n attributes_periodicityRepeat_8e35bd9dad29336f460f2acd = x[2],\r\n attributes_periodicityValidOn_80a6a695435acd16e0b4d317 = x[3],\r\n attributes_periodicityNextDate_8b766935838e7116fb62e7c0 = x[4] }).ToArray()\r\n });\r\n "
},
"attributeType": "Json"
},
{
"attribute": {
"attributeCode": "attributes_workflowOutputActionDodiCode",
"attributeType": "String",
"value": "designs_periodicity_8f3183380533b281ac719c10"
}
},
{
"attribute": {
"attributeCode": "attributes_workflowOutputActionSingleInstance",
"value": false
}
}
],
"variables": [
{
"name": "lastCompletion",
"value": {
"parameterCode": "attributes_computeDatesFromPeriodicitiesPeriodStartDate_682622f2a2dfdc1bec786d3e",
"inputMode": "Each"
},
"attributeType": "Date"
},
{
"name": "firstPossibleNext",
"value": {
"script": "var freqInterval = relativePeriodicityRepeat != null ? (int)relativePeriodicityRepeat[\"interval\"] : 0; var freqUnit = relativePeriodicityRepeat != null ? (string)relativePeriodicityRepeat[\"unit\"] : \"Days\"; return freqUnit == \"Days\" ? lastCompletion?.Value.AddDays(freqInterval) : freqUnit == \"Weeks\" ? lastCompletion?.Value.AddDays(freqInterval * 7) : freqUnit == \"Months\" ? lastCompletion?.Value.AddMonths(freqInterval) : lastCompletion?.Value.AddYears(freqInterval);"
},
"attributeType": "DateTime"
},
{
"name": "relativePeriodicityItemId",
"value": {
"outputAction": "68261ba28d57c1b3124ec4d2",
"itemValue": {
"property": "ItemId"
},
"outputMode": "Input"
},
"attributeType": "String"
},
{
"name": "cyclicalPeriodicityStartsOn",
"value": {
"outputAction": "68261b9ca71675a82f2ee892",
"itemValue": {
"attributeCode": "attributes_periodicityStartsOnInclusive_863726baef05061cd5adad15"
},
"outputMode": "Input"
},
"attributeType": "Json"
},
{
"name": "cyclicalPeriodicityEndsOn",
"value": {
"outputAction": "68261b9ca71675a82f2ee892",
"itemValue": {
"attributeCode": "attributes_periodicityEndsOnExclusive_897d0b7250920fc60c072bf1"
},
"outputMode": "Input"
},
"attributeType": "Date"
},
{
"name": "cyclicalPeriodicityValidOn",
"value": {
"outputAction": "68261b9ca71675a82f2ee892",
"itemValue": {
"attributeCode": "attributes_periodicityValidOn_80a6a695435acd16e0b4d317"
},
"outputMode": "Input"
},
"attributeType": "Json"
},
{
"name": "cyclicalPeriodicityRepeat",
"value": {
"outputAction": "68261b9ca71675a82f2ee892",
"itemValue": {
"attributeCode": "attributes_periodicityRepeat_8e35bd9dad29336f460f2acd"
},
"outputMode": "Input"
},
"attributeType": "Json"
},
{
"name": "cyclicalPeriodicityNextDate",
"value": {
"outputAction": "68261b9ca71675a82f2ee892",
"itemValue": {
"attributeCode": "attributes_periodicityNextDate_8b766935838e7116fb62e7c0"
},
"outputMode": "Input"
},
"attributeType": "Date"
},
{
"name": "relativePeriodicityValidOn",
"value": {
"outputAction": "68261ba28d57c1b3124ec4d2",
"itemValue": {
"attributeCode": "attributes_periodicityValidOn_80a6a695435acd16e0b4d317"
},
"outputMode": "Input"
},
"attributeType": "Json"
},
{
"name": "relativePeriodicityRepeat",
"value": {
"outputAction": "68261ba28d57c1b3124ec4d2",
"itemValue": {
"attributeCode": "attributes_periodicityRepeat_8e35bd9dad29336f460f2acd"
},
"outputMode": "Input"
},
"attributeType": "Json"
},
{
"name": "relativePeriodicityNextDate",
"value": {
"outputAction": "68261ba28d57c1b3124ec4d2",
"itemValue": {
"attributeCode": "attributes_periodicityNextDate_8b766935838e7116fb62e7c0"
},
"outputMode": "Input"
},
"attributeType": "Date"
}
],
"actions": [
{
"actionId": "82a1a421812ef49e2976533c",
"designCode": "designs_workflowOutputAction",
"comments": "Compute matching dates for periodicities",
"parameters": [
{
"attributeCode": "attributes_workflowOutputActionData",
"value": {
"script": "var freqEndDtRawClamp = argDateRangeEnd?.Value < freqEndDtRaw?.Value ? argDateRangeEnd?.Value : freqEndDtRaw?.Value;\r\nvar freqStartDtms = freqStartDtmsRaw[\"dates\"].Values<DateTime>().Where(dt => dt < freqEndDtRawClamp).OrderBy(i => i).ToList() ?? List<DateTime>();\r\nvar freqValidDaysOfWeek = freqValidOn?[\"daysOfWeek\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidDaysOfMonth = freqValidOn?[\"daysOfMonth\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidDaysOfYear = freqValidOn?[\"daysOfYear\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidWeeksOfMonth = freqValidOn?[\"weeksOfMonth\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidWeeksOfYear = freqValidOn?[\"weeksOfYear\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidMonthsOfYear = freqValidOn?[\"monthsOfYear\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\nvar freqValidYears = freqValidOn?[\"years\"]?.Values<int>().OrderBy(i => i).ToList() ?? List<int>();\r\n\r\nvar freqInterval = (int)freq[\"interval\"];\r\nvar freqUnit = (string)freq[\"unit\"];\r\n\r\nIEnumerable<DateTime> result = List<DateTime>();\r\n\r\nFunc<int, int> DayOfWeekStartingMondayBase1 = sys => sys == 0 ? 7 : sys;\r\n\r\nif (freqInterval > 0 && freqUnit != null && freqStartDtms.Count > 0 && freqEndDtRawClamp != null)\r\n{\r\n if (freqUnit == \"Days\")\r\n {\r\n result = freqStartDtms.SelectMany(x => Enumerable.Range(0, (int)(freqEndDtRawClamp.Value.Subtract(x).TotalDays % 1 > 0 ? 1 + freqEndDtRawClamp.Value.Subtract(x).TotalDays : freqEndDtRawClamp.Value.Subtract(x).TotalDays)).Where(i => i % freqInterval == 0).Select(offset => x.AddDays(offset)));\r\n }\r\n else if (freqUnit == \"Weeks\")\r\n {\r\n result = freqStartDtms.SelectMany(x => Enumerable.Range(0, (int)((freqEndDtRawClamp.Value.Subtract(x).TotalDays / 7.0) % 1 > 0 ? 1 + (freqEndDtRawClamp.Value.Subtract(x).TotalDays / 7.0) : (freqEndDtRawClamp.Value.Subtract(x).TotalDays / 7.0))).Where(i => i % freqInterval == 0).Select(offset => x.AddDays(offset * 7)));\r\n }\r\n else if (freqUnit == \"Months\")\r\n {\r\n result = freqStartDtms.SelectMany(d => Enumerable.Range(0, Enumerable.Range(0, 1 + (int)(Math.Ceiling(freqEndDtRawClamp.Value.Subtract(d).TotalDays / 28.0) + 1)).OrderBy(i => i).FirstOrDefault(x => d.AddMonths(x) >= freqEndDtRawClamp.Value)).Where(i => i % freqInterval == 0).Select(offset => d.AddMonths(offset)));\r\n }\r\n else if (freqUnit == \"Years\")\r\n {\r\n result = freqStartDtms.SelectMany(d => Enumerable.Range(0, Enumerable.Range(0, 1 + (int)(Math.Ceiling(freqEndDtRawClamp.Value.Subtract(d).TotalDays / 365.0) + 1)).OrderBy(i => i).FirstOrDefault(x => d.AddYears(x) >= freqEndDtRawClamp.Value)).Where(i => i % freqInterval == 0).Select(offset => d.AddYears(offset)));\r\n }\r\n\r\n result = result.Where(d => (freqValidDaysOfWeek.Count == 0 || freqValidDaysOfWeek.Contains(DayOfWeekStartingMondayBase1((int)d.DayOfWeek))));\r\n result = result.Where(d => (freqValidDaysOfMonth.Count == 0 || freqValidDaysOfMonth.Contains(d.Day)));\r\n result = result.Where(d => (freqValidDaysOfYear.Count == 0 || freqValidDaysOfYear.Contains(d.DayOfYear)));\r\n result = result.Where(d => (freqValidWeeksOfMonth.Count == 0 || freqValidWeeksOfMonth.Contains(1 + ((d.Day-1) / 7))));\r\n result = result.Where(d => (freqValidWeeksOfYear.Count == 0 || freqValidWeeksOfYear.Contains(Calendar.GetWeekOfYear(d, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday))));\r\n result = result.Where(d => (freqValidMonthsOfYear.Count == 0 || freqValidMonthsOfYear.Contains(d.Month)));\r\n result = result.Where(d => (freqValidYears.Count == 0 || (freqValidYears.Count > 0 && freqValidYears.Contains(d.Year))));\r\n}\r\n\r\nresult = result.Distinct().OrderBy(d => d);\r\n\r\nif (argDateRangeStart != null)\r\n{\r\n result = result.Where(x => x >= argDateRangeStart.Value);\r\n}\r\n\r\nif (argLimit != null)\r\n{\r\n result = result.Take((int)argLimit.Value);\r\n}\r\n\r\nreturn Json(new { items = result.Select(x => new { attributes_computeDatesFromPeriodicitiesOutputDateOccurance_8ad5639456d15a25d67516c5 = x }).ToArray() });"
},
"attributeType": "Json"
},
{
"attribute": {
"attributeCode": "attributes_workflowOutputActionDodiCode",
"value": "designs_computeDatesFromPeriodicitiesOutput_8c05e8b036adaaba582068a2"
}
},
{
"attribute": {
"attributeCode": "attributes_workflowOutputActionSingleInstance",
"value": false
}
}
],
"variables": [
{
"name": "argDateRangeStart",
"value": {
"parameterCode": "attributes_computeDatesFromPeriodicitiesDateRangeStart_800d6f68feb01147ef0d2035",
"inputMode": "Each"
},
"attributeType": "Date"
},
{
"name": "argDateRangeEnd",
"value": {
"parameterCode": "attributes_computeDatesFromPeriodicitiesDateRangeEnd_81c4dd81e998b56ddfe158ab",
"inputMode": "Each"
},
"attributeType": "Date"
},
{
"name": "argLimit",
"value": {
"parameterCode": "attributes_computeDatesFromPeriodicitiesLimit_8f4d17da8e3a79f4d3fa840b",
"inputMode": "Each"
},
"attributeType": "Number"
},
{
"name": "freqValidOn",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_periodicityValidOn_80a6a695435acd16e0b4d317"
}
},
"attributeType": "Json"
},
{
"name": "freq",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_periodicityRepeat_8e35bd9dad29336f460f2acd"
}
},
"attributeType": "Number"
},
{
"name": "freqEndDtRaw",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_periodicityEndsOnExclusive_897d0b7250920fc60c072bf1"
}
},
"attributeType": "Date"
},
{
"name": "freqStartDtmsRaw",
"value": {
"inputParent": 0,
"itemValue": {
"attributeCode": "attributes_periodicityStartsOnInclusive_863726baef05061cd5adad15"
}
},
"attributeType": "Json"
}
],
"actions": []
}
]
}
]
}