Projekti ajakava API-de kasutamine ajastamise olemitega toimingute tegemiseks
Kehtib: Ressursipõhiste/mitteladustatud stsenaariumide projektitoimingud, Lite’i juurutamine – tehing proforma arveldamiseks.
Plaanimise olemid
Projekti ajakava API-d annavad võimaluse plaanimisolemitega loomis-, värskenda- ja kustutamistoiminguid teha. Neid olemeid hallatakse veebirakenduse Project ajastamise mootori kaudu. Toimingute loomine, värskendamine ja kustutamine plaanimisolemitega oli varasemates Dynamics 365 Project Operations väljaannetes piiratud.
Järgmises tabelid on toodud projekti ajakava olemite täielik loend.
Olemi nimi | Olemi loogiline nimi |
---|---|
Project | msdyn_project |
Projekti ülesanne | msdyn_projecttask |
Projekti ülesande sõltuvus | msdyn_projecttaskdependency |
Ressursi määramine | msdyn_resourceassignment |
Projektisalv | msdyn_projectbucket |
Projektimeeskonna liige | msdyn_projectteam |
Projekti kontroll-loendid | msdyn_projectchecklist |
Projekti silt | msdyn_projectlabel |
Projekti ülesanne sildile | msdyn_projecttasktolabel |
Projekti sprint | msdyn_projectsprint |
OperationSet
OperationSet on tööühiku muster, mida saab kasutada juhul, kui kandes tuleb töödelda mitut ajakava mõjutavat taotlust.
Projekti ajakava API-d
Järgnev on praeguste projekti ajakava API-de loend.
API | Kirjeldus |
---|---|
msdyn_CreateProjectV1 | Seda API-t kasutatakse projekti loomiseks. Projekt ja vaikimisi projektisalv luuakse kohe. Projekti saab luua ka lisades projekti tabelisse rea, kasutades standardseid Dataverse API-sid. See protsess ei loo projektile vaike salv, kuid selle jõudlus võib olla parem. |
msdyn_CreateTeamMemberV1 | Seda API-t kasutatakse projektimeeskonna liikme loomiseks. Meeskonnaliikme kirje luuakse kohe. Meeskonnaliikme loomiseks saab standardsete Dataverse API-de abil lisada rea ka Project Team Memberi tabelisse. |
msdyn_CreateOperationSetV1 | Seda API-t saab kasutada mitme taotluse ajastamiseks, mis tuleb kande sees teha. |
msdyn_PssCreateV1 | Seda API-t kasutatakse olemi loomiseks. Olem võib olla mis tahes priekti ajastamise olemitest, mis toetab loomistoimingut. |
msdyn_PssCreateV2 | Seda API-t kasutatakse olemi loomiseks. See töötab nagu msdyn_PssCreateV1, kuid ühes toimingus saab luua mitu olemit. |
msdyn_PssUpdateV1 | Seda API-t kasutatakse olemi värskendamiseks. Olem võib olla mis tahes priekti ajastamise olemitest, mis toetab värskendamistoimingut. |
msdyn_PssUpdateV2 | Seda API-t kasutatakse olemite värskendamiseks. See töötab nagu msdyn_PssUpdateV1, kuid ühe toiminguga saab värskendada mitut olemit. |
msdyn_PssDeleteV1 | Seda API-t kasutatakse olemi kustutamiseks. Olem võib olla mis tahes priekti ajastamise olemitest, mis toetab kustutamistoimingut. |
msdyn_PssDeleteV2 | Seda API-d kasutatakse olemite kustutamiseks. See töötab nagu msdyn_PssDeleteV1, kuid ühe toiminguga saab kustutada mitu olemit. |
msdyn_ExecuteOperationSetV1 | Seda API-t kasutatakse antud toimingute komplektis kõikide toimingute täitmiseks. |
msdyn_PssUpdateResourceAssignmentV1 | Seda API-t kasutatakse ressursi määramise plaanitud töö kontuuri värskendamiseks. |
Projecti ajakava API-de kasutamine operatsioonikomplektiga OperationSet
Kuna kirjed luuakse kohe nii CreateProjectV1 kui ka CreateTeamMemberV1 jaoks, ei saa neid API-sid otse operatsioonikomplektis kasutada. Siiski saate neid kasutada vajalike kirjete loomiseks, OperationSeti loomiseksja seejärel OperationSeti eelloodud kirjetekasutamiseks.
Toetatud tegevused
Olemi ajastamine | Koosta | Värskendus | Kustutusklahv (Delete) | Olulised kaalutlused |
---|---|---|---|---|
Projekti ülesanne | Ja | Ja | Ja | Välju Edenemine, Pingutus Lõpetatud ja PingutusSäilitamine saab redigeerida Project for the Webis, kuid neid ei saa redigeerida Project Operationsis. |
Projektiülesande sõltuvus | Ja | No | Ja | Projektiülesande sõltuvuskirjeid ei värskendata. Selle asemel saab vana kirje kustutada ja luua uue kirje. |
Ressursi määramine | Ja | Jah* | Ja | Järgmiste väljadega toimingud pole toetatud: BookableResourceID, Effort, EffortCompleted, EffortRemaining ja Planned Work. |
Projektisalv | Ja | Ja | Ja | Vaike salv luuakse CreateProjectV1 API abil . Värskendusväljaandes 16 lisati projektisalvede loomise ja kustutamise tugi. |
Projektimeeskonna liige | Ja | Ja | Ja | Loomise toimingu jaoks kasutage API-d CreateTeamMemberV1 . |
Project | Ja | Ja | No | Järgmiste väljadega toiminguid ei toetata: StateCode,BulkGenerationStatus,GlobalRevisionToken,CalendarID,Effort,EffortCompleted,EffortRemaining,Progress,Finish,TaskEarliestStart ja Duration. |
Projekti kontroll-loendid | Ja | Ja | Ja | |
Projekti silt | No | Ja | No | Sildinimesid saab muuta. See funktsioon on saadaval ainult Projecti veebirakenduse jaoks. Sildid luuakse projekti esmakordsel avamisel. |
Projekti ülesanne sildile | Ja | No | Ja | See funktsioon on saadaval ainult Projecti veebirakenduse jaoks. |
Projekti sprint | Ja | Ja | Ja | Väljal Start peab olema väljast Lõpp varasem kuupäev. Sama projekti sprindid ei tohi üksteisega kattuda. See funktsioon on saadaval ainult Projecti veebirakenduse jaoks. |
Projekti eesmärk | Ja | Ja | Ja | Järgmiste väljadega tehtavad toimingud pole toetatud: DescriptionPlainText, TaskDisplayOrder |
Projekti ülesande ja eesmärgi seos | Ja | No | Ja | Järgmiste väljadega toimingud pole toetatud. TaskDisplayOrder |
* Ressursimäärangu kirjeid ei värskendata. Selle asemel saab vana kirje kustutada ja luua uue kirje. Ressursside määramise kontuuride värskendamiseks on ette nähtud eraldi API.
ID atribuut on valikuline. Kui ID-atribuut on olemas, proovib süsteem seda kasutada ja viskab erandi, kui seda ei saa kasutada. Kui seda ei pakuta, loob süsteem selle.
Piirangud ja teadaolevad probleemid
Järgmine loend näitab piiranguid ja teadaolevaid probleeme.
Project Schedule’i API-sid saavad kasutada ainult Microsoft Projecti litsentsiga kasutajad. Neid ei saa kasutada järgnevad.
- Rakenduse kasutajad
- Süsteemi kasutajad
- Integratsiooni kasutajad
- Teised kasutajad, kes ei oma nõutavat litsentsi
Igal operatsioonikomplektil saab olla ainult maksimaalselt 200 toimingut.
Igal kasutajal saab olla ainult maksimaalselt 10 avatud operatsioonikomplekti.
Iga värskenduse ressursi määramise kontuuri toiming loetakse üheks toiminguks.
Iga värskendatud kontuuride loend võib sisaldada maksimaalselt 100 ajalõiku.
OperationSeti tõrkeoleku ja tõrkelogid pole praegu saadaval.
Ühe projekti kohta on maksimaalselt 400 sprinti.
Projektide ja ülesannete piirangud ja piirid.
Vigade käsitlemine
- Operatsioonikomplektidest loodud tõrgete ülevaatamiseks minge jaotisse Sätete>ajakava Integratsioonitoimingute>komplektid.
- Teenusest Project schedule Service loodud tõrgete ülevaatamiseks avage jaotis Sätete ajakava integreerimise>PSS-i tõrkelogid>.
Ressursside määramise kontuuride redigeerimine
Erinevalt kõigist teistest olemit värskendavatest projekti ajastamise API-dest vastutab ressursi määramise kontuuri API ainuüksi ühe välja msdyn_plannedwork värskenduste eest ühel olemil, msydn_resourceassignment.
Antud ajakavarežiim on:
- fikseeritud ühikud.
- Projekti kalender on esmaspäeval, teisipäeval, neljapäeval ja reedel kell 9.00–17.00 (Vaikse ookeani aeg). (Kolmapäeviti tööd ei ole.)
- Ressursside kalender on esmaspäevast reedeni kella 9.00–13.00 (Vaikse ookeani aeg).
See ülesanne on üks nädal, neli tundi päevas, kuna ressursikalender on kella 9.00–13.00 (Vaikse ookeani aeg) või neli tundi päevas.
Toiming | Alguskuupäev | Lõpukuupäev | Kogus | 13.06.2022 | 14.06.2022 | 15.06.2022 | 16.06.2022 | 17.06.2022 | |
---|---|---|---|---|---|---|---|---|---|
9-1 töötaja | T1 | 13.06.2022 | 17.06.2022 | 20 | 4 | 4 | 4 | 4 | 4 |
Näiteks kui soovite, et töötaja töötaks sel nädalal iga päev ainult kolm tundi ja jätaks ühe tunni muude ülesannete jaoks.
UuendatudKontuuride näidis kasulik koormus
[{
"minutes":900.0,
"start":"2022-06-13T00:00:00-07:00",
"end":"2022-06-18T00:00:00-07:00"
}]
See on määramine pärast kontuuri ajakava värskendamise API käitamist.
Toiming | Alguskuupäev | Lõpukuupäev | Kogus | 13.06.2022 | 14.06.2022 | 15.06.2022 | 16.06.2022 | 17.06.2022 | |
---|---|---|---|---|---|---|---|---|---|
9-1 töötaja | T1 | 13.06.2022 | 17.06.2022 | 15 | 3 | 3 | 3 | 3 | 3 |
Stsenaariumi näidis
Selles stsenaariumis loote projekti, meeskonnaliikme, neli ülesannet ja kaks ressursimäärangut. Järgmisena värskendate ühte ülesannet, värskendate projekti, värskendate ressursimäärangu kontuuri, kustutate ühe ülesande, kustutate ühe ressursiülesande ja loote ülesande sõltuvuse.
Entity project = CreateProject();
project.Id = CallCreateProjectAction(project);
var projectReference = project.ToEntityReference();
var teamMember = new Entity("msdyn_projectteam", Guid.NewGuid());
teamMember["msdyn_name"] = $"TM {DateTime.Now.ToShortTimeString()}";
teamMember["msdyn_project"] = projectReference;
var createTeamMemberResponse = CallCreateTeamMemberAction(teamMember);
var description = $"My demo {DateTime.Now.ToShortTimeString()}";
var operationSetId = CallCreateOperationSetAction(project.Id, description);
var task1 = GetTask("1WW", projectReference);
var task2 = GetTask("2XX", projectReference, task1.ToEntityReference());
var task3 = GetTask("3YY", projectReference);
var task4 = GetTask("4ZZ", projectReference);
var assignment1 = GetResourceAssignment("R1", teamMember, task2, project);
var assignment2 = GetResourceAssignment("R2", teamMember, task3, project);
var task1Response = CallPssCreateAction(task1, operationSetId);
var task2Response = CallPssCreateAction(task2, operationSetId);
var task3Response = CallPssCreateAction(task3, operationSetId);
var task4Response = CallPssCreateAction(task4, operationSetId);
var assignment1Response = CallPssCreateAction(assignment1, operationSetId);
var assignment2Response = CallPssCreateAction(assignment2, operationSetId);
task2["msdyn_subject"] = "Updated Task";
var task2UpdateResponse = CallPssUpdateAction(task2, operationSetId);
project["msdyn_subject"] = $"Proj update {DateTime.Now.ToShortTimeString()}";
var projectUpdateResponse = CallPssUpdateAction(project, operationSetId);
List<UpdatedContour> updatedContours = new List<UpdatedContour>();
UpdatedContour updatedContour = new UpdatedContour();
updatedContour.Start = DateTime.UtcNow.Date;
updatedContour.End = DateTime.UtcNow.Date.AddDays(1);
updatedContour.Minutes = 120;
updatedContours.Add(updatedContour);
String serializedUpdate = JsonConvert.SerializeObject(updatedContours);
var updateContoursResponse = CallPssUpdateContourAction(assignment1.Id, serializedUpdate, operationSetId);
var task4DeleteResponse = CallPssDeleteAction(task4.Id.ToString(), task4.LogicalName, operationSetId);
var assignment2DeleteResponse = CallPssDeleteAction(assignment2.Id.ToString(), assignment2.LogicalName, operationSetId);
var dependency1 = GetTaskDependency(project, task2, task3);
var dependency1Response = CallPssCreateAction(dependency1, operationSetId);
CallExecuteOperationSetAction(operationSetId);
Console.WriteLine("Done....");
Täiendavad proovid
#region Call actions --- Sample code ----
/// <summary>
/// Calls the action to create an operationSet
/// </summary>
/// <param name="projectId">project id for the operations to be included in this operationSet</param>
/// <param name="description">description of this operationSet</param>
/// <returns>operationSet id</returns>
private string CallCreateOperationSetAction(Guid projectId, string description)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_CreateOperationSetV1");
operationSetRequest["ProjectId"] = projectId.ToString();
operationSetRequest["Description"] = description;
OrganizationResponse response = organizationService.Execute(operationSetRequest);
return response["OperationSetId"].ToString();
}
/// <summary>
/// Calls the action to create an entity
/// </summary>
/// <param name="entity">Scheduling entity</param>
/// <param name="operationSetId">operationSet id</param>
/// <returns>OperationSetResponse</returns>
private OperationSetResponse CallPssCreateAction(Entity entity, string operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_PssCreateV1");
operationSetRequest["Entity"] = entity;
operationSetRequest["OperationSetId"] = operationSetId;
return GetOperationSetResponseFromOrgResponse(organizationService.Execute(operationSetRequest));
}
/// <summary>
/// Calls the action to update an entity
/// </summary>
/// <param name="entity">Scheduling entity</param>
/// <param name="operationSetId">operationSet Id</param>
/// <returns>OperationSetResponse</returns>
private OperationSetResponse CallPssUpdateAction(Entity entity, string operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_PssUpdateV1");
operationSetRequest["Entity"] = entity;
operationSetRequest["OperationSetId"] = operationSetId;
return GetOperationSetResponseFromOrgResponse(organizationService.Execute(operationSetRequest));
}
/// <summary>
/// Calls the action to update an entity
/// </summary>
/// <param name="recordId">Id of the record to be deleted</param>
/// <param name="entityLogicalName">Entity logical name of the record</param>
/// <param name="operationSetId">OperationSet Id</param>
/// <returns>OperationSetResponse</returns>
private OperationSetResponse CallPssDeleteAction(string recordId, string entityLogicalName, string operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_PssDeleteV1");
operationSetRequest["RecordId"] = recordId;
operationSetRequest["EntityLogicalName"] = entityLogicalName;
operationSetRequest["OperationSetId"] = operationSetId;
return GetOperationSetResponseFromOrgResponse(organizationService.Execute(operationSetRequest));
}
/// <summary>
/// Calls the action to update a Resource Assignment contour
/// </summary>
/// <param name="resourceAssignmentId">Id of the resource assignment to be updated</param>
/// <param name="serializedUpdates">JSON formatted contour updates</param>
/// <param name="operationSetId">operationSet id</param>
/// <returns>OperationSetResponse</returns>
private OperationSetResponse CallPssUpdateContourAction(string resourceAssignmentId, string serializedUpdates string operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_PssUpdateResourceAssignmentContourV1");
operationSetRequest["ResourceAssignmentId"] = resourceAssignmentId;
operationSetRequest["UpdatedContours"] = serializedUpdates;
operationSetRequest["OperationSetId"] = operationSetId;
return GetOperationSetResponseFromOrgResponse(OrganizationService.Execute(operationSetRequest));
}
/// <summary>
/// Calls the action to execute requests in an operationSet
/// </summary>
/// <param name="operationSetId">operationSet id</param>
/// <returns>OperationSetResponse</returns>
private OperationSetResponse CallExecuteOperationSetAction(string operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_ExecuteOperationSetV1");
operationSetRequest["OperationSetId"] = operationSetId;
return GetOperationSetResponseFromOrgResponse(organizationService.Execute(operationSetRequest));
}
/// <summary>
/// This can be used to abandon an operationSet that is no longer needed
/// </summary>
/// <param name="operationSetId">operationSet id</param>
/// <returns>OperationSetResponse</returns>
protected OperationSetResponse CallAbandonOperationSetAction(Guid operationSetId)
{
OrganizationRequest operationSetRequest = new OrganizationRequest("msdyn_AbandonOperationSetV1");
operationSetRequest["OperationSetId"] = operationSetId.ToString();
return GetOperationSetResponseFromOrgResponse(organizationService.Execute(operationSetRequest));
}
/// <summary>
/// Calls the action to create a new project
/// </summary>
/// <param name="project">Project</param>
/// <returns>project Id</returns>
private Guid CallCreateProjectAction(Entity project)
{
OrganizationRequest createProjectRequest = new OrganizationRequest("msdyn_CreateProjectV1");
createProjectRequest["Project"] = project;
OrganizationResponse response = organizationService.Execute(createProjectRequest);
var projectId = Guid.Parse((string)response["ProjectId"]);
return projectId;
}
/// <summary>
/// Calls the action to create a new project team member
/// </summary>
/// <param name="teamMember">Project team member</param>
/// <returns>project team member Id</returns>
private string CallCreateTeamMemberAction(Entity teamMember)
{
OrganizationRequest request = new OrganizationRequest("msdyn_CreateTeamMemberV1");
request["TeamMember"] = teamMember;
OrganizationResponse response = organizationService.Execute(request);
return (string)response["TeamMemberId"];
}
private OperationSetResponse GetOperationSetResponseFromOrgResponse(OrganizationResponse orgResponse)
{
return JsonConvert.DeserializeObject<OperationSetResponse>((string)orgResponse.Results["OperationSetResponse"]);
}
private EntityCollection GetDefaultBucket(EntityReference projectReference)
{
var columnsToFetch = new ColumnSet("msdyn_project", "msdyn_name");
var getDefaultBucket = new QueryExpression("msdyn_projectbucket")
{
ColumnSet = columnsToFetch,
Criteria =
{
Conditions =
{
new ConditionExpression("msdyn_project", ConditionOperator.Equal, projectReference.Id),
new ConditionExpression("msdyn_name", ConditionOperator.Equal, "Bucket 1")
}
}
};
return organizationService.RetrieveMultiple(getDefaultBucket);
}
private Entity GetBucket(EntityReference projectReference)
{
var bucketCollection = GetDefaultBucket(projectReference);
if (bucketCollection.Entities.Count > 0)
{
return bucketCollection[0].ToEntity<Entity>();
}
throw new Exception($"Please open project with id {projectReference.Id} in the Dynamics UI and navigate to the Tasks tab");
}
private Entity CreateProject()
{
var project = new Entity("msdyn_project", Guid.NewGuid());
project["msdyn_subject"] = $"Proj {DateTime.Now.ToShortTimeString()}";
return project;
}
private Entity GetTask(string name, EntityReference projectReference, EntityReference parentReference = null)
{
var task = new Entity("msdyn_projecttask", Guid.NewGuid());
task["msdyn_project"] = projectReference;
task["msdyn_subject"] = name;
task["msdyn_effort"] = 4d;
task["msdyn_scheduledstart"] = DateTime.Today;
task["msdyn_scheduledend"] = DateTime.Today.AddDays(5);
task["msdyn_start"] = DateTime.Now.AddDays(1);
task["msdyn_projectbucket"] = GetBucket(projectReference).ToEntityReference();
task["msdyn_LinkStatus"] = new OptionSetValue(192350000);
//Custom field handling
/*
task["new_custom1"] = "Just my test";
task["new_age"] = 98;
task["new_amount"] = 591.34m;
task["new_isready"] = new OptionSetValue(100000000);
*/
if (parentReference == null)
{
task["msdyn_outlinelevel"] = 1;
}
else
{
task["msdyn_parenttask"] = parentReference;
}
return task;
}
private Entity GetResourceAssignment(string name, Entity teamMember, Entity task, Entity project)
{
var assignment = new Entity("msdyn_resourceassignment", Guid.NewGuid());
assignment["msdyn_projectteamid"] = teamMember.ToEntityReference();
assignment["msdyn_taskid"] = task.ToEntityReference();
assignment["msdyn_projectid"] = project.ToEntityReference();
assignment["msdyn_name"] = name;
return assignment;
}
protected Entity GetTaskDependency(Entity project, Entity predecessor, Entity successor)
{
var taskDependency = new Entity("msdyn_projecttaskdependency", Guid.NewGuid());
taskDependency["msdyn_project"] = project.ToEntityReference();
taskDependency["msdyn_predecessortask"] = predecessor.ToEntityReference();
taskDependency["msdyn_successortask"] = successor.ToEntityReference();
taskDependency["msdyn_linktype"] = new OptionSetValue(192350000);
return taskDependency;
}
#endregion
#region OperationSetResponse DataContract --- Sample code ----
[DataContract]
public class OperationSetResponse
{
[DataMember(Name = "operationSetId")]
public Guid OperationSetId { get; set; }
[DataMember(Name = "operationSetDetailId")]
public Guid OperationSetDetailId { get; set; }
[DataMember(Name = "operationType")]
public string OperationType { get; set; }
[DataMember(Name = "recordId")]
public string RecordId { get; set; }
[DataMember(Name = "correlationId")]
public string CorrelationId { get; set; }
}
#endregion
#region UpdatedContour DataContract --- Sample code ----
[DataContract]
public class UpdatedContour
{
[DataMember(Name = "start")]
public DateTime Start { get; set; }
[DataMember(Name = "end")]
public DateTime End { get; set; }
[DataMember(Name = "minutes")]
public decimal Minutes { get; set; }
}
#endregion