Projektiaikataulun ohjelmointirajapintojen käyttö toimintojen suorittamiseen aikataulutusentiteeteillä
Koskee: Project Operationsin resurssiin/ei-varastointiin perustuvia skenaarioita, Lite-käyttöönotto - kaupasta proformalaskutukseen.
Aikataulutusentiteetit
Projektiaikataulun ohjelmointirajapintojen avulla voi luoda, päivittää ja poistaa toimintoja aikataulutusentiteettien avulla. Näitä entiteettejä hallitaan verkkopohjaisessa Projectissa aikataulutusytimen kautta. Luonti-, päivitys- ja poisto-operaatioita Aikataulutusentiteettien avulla rajoitettiin aiemmissa Dynamics 365 Project Operations -julkaisuissa.
Seuraavassa taulukossa on täydellinen luettelo Projektiaikataulu -entiteeteistä.
Entiteetin nimi | Entiteetin looginen nimi |
---|---|
Project | msdyn_project |
Projektin tehtävä | msdyn_projecttask |
Projektitehtävän riippuvuus | msdyn_projecttaskdependency |
Resurssien delegointi | msdyn_resourceassignment |
Projektin joukko | msdyn_projectbucket |
Projektiryhmän jäsen | msdyn_projectteam |
Projektin tarkistusluettelot | msdyn_projectchecklist |
Projektin selite | msdyn_projectlabel |
Projektitehtävä, jolle annetaan selite | msdyn_projecttasktolabel |
Projektisprintti | msdyn_projectsprint |
OperationSet
OperationSet on työyksikkörakenne, jota voidaan käyttää, kun useita aikatauluihin vaikuttavia pyyntöjä on käsiteltävä tapahtumassa.
Projektiaikataulujen ohjelmointirajapinnat
Seuraavassa on luettelo nykyisistä Projektiaikataulun ohjelmointirajapinnoista.
Ohjelmointirajapinta | Description |
---|---|
msdyn_CreateProjectV1 | Tätä ohjelmointirajapintaa käytetään projektin luomiseen. Projekti ja oletusprojektisäilö luodaan heti. Projektin luonti voidaan tehdä myös lisäämällä projektitaulukkoon rivi Dataversen vakio-ohjelmointirajapintojen avulla. Tämä prosessi ei luo projektille oletussäilöä, mutta se voi parantaa suorituskykyä. |
msdyn_CreateTeamMemberV1 | Tätä ohjelmointirajapintaa käytetään projektin ryhmän jäsenen luomiseen. Ryhmän jäsentietue luodaan heti. Ryhmän jäsenen luonti voidaan tehdä myös lisäämällä projektiryhmän jäsentaulukkoon rivi Dataversen vakio-ohjelmointirajapintojen avulla. |
msdyn_CreateOperationSetV1 | Tämän ohjelmointirajapinnan avulla voidaan aikatauluttaa useita pyyntöjä, jotka on suoritettava tapahtumassa. |
msdyn_PssCreateV1 | Tätä ohjelmointirajapintaa käytetään entiteetin luomiseen. Entiteetti voi olla mikä tahansa luontitoimintoa tukeva projektin aikataulutusentiteetti. |
msdyn_PssCreateV2 | Tätä ohjelmointirajapintaa käytetään entiteetin luomiseen. Se toimii samoin kuin msdyn_PssCreateV1, mutta yhdellä toiminnolla voidaan luoda useita entiteettejä. |
msdyn_PssUpdateV1 | Tätä ohjelmointirajapintaa käytetään entiteetin päivittämiseen. Entiteetti voi olla mikä tahansa päivitystoimintoa tukeva projektin aikataulutusentiteetti. |
msdyn_PssUpdateV2 | Tätä ohjelmointirajapintaa käytetään entiteettien päivittämiseen. Se toimii samoin kuin msdyn_PssUpdateV1, mutta yhdellä toiminnolla voidaan päivittää useita entiteettejä. |
msdyn_PssDeleteV1 | Tätä ohjelmointirajapintaa käytetään entiteetin poistamiseen. Entiteetti voi olla mikä tahansa poistotoimintoa tukeva projektin aikataulutusentiteetti. |
msdyn_PssDeleteV2 | Tätä ohjelmointirajapintaa käytetään entiteettien poistamiseen. Se toimii samoin kuin msdyn_PssDeleteV1, mutta yhdellä toiminnolla voidaan poistaa useita entiteettejä. |
msdyn_ExecuteOperationSetV1 | Tämän ohjelmointirajapinnan avulla suoritetaan kaikki toiminnot tietyn toimintojoukon sisällä. |
msdyn_PssUpdateResourceAssignmentV1 | Tätä ohjelmointirajapintaa käytetään päivittämään resurssin määrityksen suunnitellut työt. |
Projektiaikataulun ohjelmointirajapintojen käyttäminen OperationSetin kanssa
Koska tietueet luodaan heti sekä CreateProjectV1 - että CreateTeamMemberV1 -toiminnolla, näitä ohjelmointirajapointoja ei voi käyttää suoraan OperationSet -toiminnossa. Niiden avulla voit kuitenkin luoda tarvittavat tietueet, luoda OperationSetin, ja käyttää sitten näitä aiemmin luotuja tietueita OperationSetissä.
Tuetut toiminnot
Aikataulutusentiteetti | Luo | Update | Delete | Tärkeitä huomioon otettavia seikkoja |
---|---|---|---|---|
Projektitehtävä | Kyllä | Kyllä | Kyllä | Progress-, EffortCompleted- ja EffortRemaining-kenttiä voi muokata Project for the Webissä, mutta niitä ei voi muokata Project Operationsissa. |
Projektitehtävän riippuvuus | Kyllä | No | Kyllä | Projektitehtävän riippuvuustietueita ei päivitetä. Sen sijaan voidaan poistaa vanha tietue ja luoda uusi tietue. |
Resurssien delegointi | Kyllä | Kyllä* | Kyllä | Toimintoja, joilla on seuraavat kentät, ei tueta: BookableResourceID, Effort, EffortCompleted, EffortRemaining ja PlannedWork. |
Projektin säilö | Kyllä | Kyllä | Kyllä | Oletussäilö luodaan CreateProjectV1-ohjelmointirajapinnan avulla. Update Release 16 -versiossa lisättiin projektisäilöjen luonti- ja poistotuki. |
Projektiryhmän jäsen | Kyllä | Kyllä | Kyllä | Käytä luontioperaatiolle CreateTeamMemberV1 -ohjelmointirajapintaa. |
Project | Kyllä | Kyllä | No | Toimintoja, joilla on seuraavat kentät, ei tueta StateCode, BulkGenerationStatus, GlobalRevisionToken, CalendarID, Effort, EffortCompleted, EffortRemaining, Progress, Finish, TaskEarliestStart ja Duration. |
Projektin tarkistusluettelot | Kyllä | Kyllä | Kyllä | |
Projektin selite | No | Kyllä | No | Selitteiden nimiä voi muuttaa. Tämä toiminto on käytettävissä vain Project for the Webissä. Otsikot luodaan, kun avaat projektin ensimmäisen kerran. |
Projektitehtävä, jolle annetaan selite | Kyllä | No | Kyllä | Tämä toiminto on käytettävissä vain Project for the Webissä. |
Projektisprintti | Kyllä | Kyllä | Kyllä | Aloitus-kentässä on oltava Päättymispäivä-kenttää vanhempi päivämäärä. Saman projektin sprintit eivät voi olla päällekkäisiä toistensa kanssa. Tämä toiminto on käytettävissä vain Project for the Webissä. |
Projektitavoite | Kyllä | Kyllä | Kyllä | Seuraavia kenttiä sisältäviä toimintoja ei tueta: DescriptionPlainText, TaskDisplayOrder |
Projektitehtävä, jolle annetaan tavoite | Kyllä | Ei | Kyllä | Seuraavia kenttiä sisältäviä toimintoja ei tueta: TaskDisplayOrder |
* Resurssien määritystietueita ei päivitetä. Sen sijaan voidaan poistaa vanha tietue ja luoda uusi tietue. Resurssin delegoinnin jaksojen päivittämistä varten on erillinen ohjelmointirajapinta.
Tunnusominaisuus on valinnainen. Jos tunnusominaisuus on annettu, järjestelmä yrittää käyttää sitä ja antaa poikkeuksen, jos sitä ei voi käyttää. Jos sitä ei ole annettu, järjestelmä luo sen.
Rajoitukset ja tunnetut ongelmat
Seuraavassa on luettelo rajoituksista ja tunnetuista ongelmista:
Projektiaikataulun ohjelmointirajapintoja voivat käyttää vain käyttäjät, joilla on Microsoft Project -lisenssi. Niitä eivät voi käyttää:
- Sovelluksen käyttäjät
- Järjestelmäkäyttäjät
- Integrointikäyttäjät
- Muut käyttäjät, joilla ei ole tarvittavaa lisenssiä
Kussakin OperationSetissä voi olla enintään 200 toimintoa.
Kullakin käyttäjällä voi olla enintään 10 avointa OperationSetiä.
Kukin päivitysresurssien määritystoiminto lasketaan yhdeksi toiminnoksi.
Kussakin päivitetyssä luettelossa voi olla enintään 100 aikaviipaletta.
OperationSet-virheen tila- ja virhelokit eivät ole tällä hetkellä käytettävissä.
Projektissa voi olla enintään 400 sprinttiä.
Virheen käsittely
- Voit tarkastella toimintojoukoista luotuja virheitä kohdassa Asetukset>Aikatauluta integrointi>Toimintojoukot.
- Voit tarkastella Projektin aikataulupalvelussa luotuja virheitä valitsemalla Asetukset>Aikataulun integrointi>PSS-virhelokit.
Resurssien määrityksen jaksotuksen muokkaaminen
Toisin kuin kaikki muut entiteettiä päivittävät projektin aikataulutuksen ohjelmointirajapinnat, resurssin määrityksen ohjelmointirajapinta vastaa yksin yhteen kenttään tehtävistä päivityksistä, msdyn_plannedwork, yksittäisessä entiteetissä, msydn_resourceassignment.
Annettu aikataulutila on:
- kiinteät yksiköt.
- Projektin kalenteri on maanantaisin, tiistaisin, torstaisin ja perjantaisin klo 9–17 (Tyynenmeren aika). (Keskiviikkoisin ei ole töitä.)
- Resurssikalenteri on maanantaista perjantaihin klo 9–13 (Tyynenmeren aika).
Tämä varaus on yksi viikko ja neljä tuntia päivässä, koska resurssin kalenteri on klo 9.00–13.00 (Tyynenmeren aikaa) tai neljä tuntia päivässä.
Tehtävä | Aloituspäivämäärä | Päättymispäivämäärä | Määrä | 6/13/2022 | 6/14/2022 | 6/15/2022 | 6/16/2022 | 6/17/2022 | |
---|---|---|---|---|---|---|---|---|---|
9-1-työntekijä | T1 | 6/13/2022 | 6/17/2022 | 20 | 4 | 4 | 4 | 4 | 4 |
Jos esimerkiksi haluat, että työntekijä työskentelee vain kolme tuntia joka päivä tällä viikolla ja sallitaan tunti muita tehtäviä varten.
UpdatedContours-näytehyötykuorma
[{
"minutes":900.0,
"start":"2022-06-13T00:00:00-07:00",
"end":"2022-06-18T00:00:00-07:00"
}]
Tämä on tehtävä Päivitä aikataulu -ohjelmointirajapinnan suorituksen jälkeen.
Tehtävä | Aloituspäivämäärä | Päättymispäivämäärä | Määrä | 6/13/2022 | 6/14/2022 | 6/15/2022 | 6/16/2022 | 6/17/2022 | |
---|---|---|---|---|---|---|---|---|---|
9-1-työntekijä | T1 | 6/13/2022 | 6/17/2022 | 15 | 3 | 3 | 3 | 3 | 3 |
Näyteskenaario
Tässä skenaariossa luodaan projekti, ryhmän jäsen, neljä tehtävää ja kaksi resurssivarausta. Seuraavaksi päivität yhden tehtävän, päivität projektin, päivität resurssimäärityksen aikavälin, poistat yhden tehtävän, poistat yhden resurssin määrityksen ja luot tehtävän riippuvuuden.
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....");
Muita näytteitä
#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