Jaa


Projektiaikataulun ohjelmointirajapintojen käyttö toimintojen suorittamiseen aikataulutusentiteeteillä

Soveltuu seuraaviin: Project Operations -järjestelmän integroiminen ERP:n kanssa, Project Operations Core.

Yksiköiden aikataulutus

Projektin ajoituksen ohjelmointirajapinnat tarjoavat mahdollisuuden luoda, päivittää ja poistaa Entiteettejä. Nämä entiteetit hallitaan Project for the Webin aikataulutusmoduulilla. Aiempi Dynamics 365 Project Operations julkaisee rajoitettuja luonti-, päivitys- ja poistotoimintoja Ajoitettavat entiteetit.

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_projektitehtäväriippuvuus
Resurssien delegointi msdyn_resourceassignment
Projektin joukko msdyn_projectbucket
Projektiryhmän jäsen msdyn_projectteam
Projektin tarkistusluettelot msdyn_projektin_tarkistuslista
Projektin selite msdyn_projectlabel
Projektitehtävä, jolle annetaan selite msdyn_projecttasktolabel
Projektisprintti msdyn_projectsprint

OperationSet

Käytä OperationSet-toimintoa työyksikkönä, kun haluat käsitellä useita tapahtumaan kuuluvia aikatauluun vaikuttavia pyyntöjä.

Projektin aikataulun ohjelmointirajapinnat

Seuraavassa luettelossa esitetään nykyiset projektiaikataulun ohjelmointirajapinnat.

API Description
msdyn_CreateProjectV1 Tämän ohjelmointirajapinnan avulla voit luoda projektin. Se luo projektin ja oletusprojektin säilön heti. Voit myös luoda projektin lisäämällä rivin projektitaulukkoon käyttämällä Dataverse-vakio-ohjelmointirajapintoja. Tämä prosessi ei luo oletusluonteista säilöä projektille, mutta sen suorituskyky voi olla parempi.
msdyn_CreateTeamMemberV1 Tämän ohjelmointirajapinnan avulla voit luoda projektitiimin jäsenen. Heti luodaan tiimin jäsenen tietue. Voit myös luoda tiimin jäsenen lisäämällä rivin Projektiryhmän jäsen -taulukkoon käyttämällä Dataverse-vakio-ohjelmointirajapintoja.
msdyn_CreateOperationSetV1 Tämän ohjelmointirajapinnan avulla voit ajoittaa useita pyyntöjä, jotka on suoritettava tapahtuman yhteydessä.
msdyn_PssCreateV1 Luo entiteetti tämän ohjelmointirajapinnan avulla. Entiteetti voi olla mikä tahansa luontitoimintoa tukeva projektin aikataulutusentiteetti.
msdyn_PssCreateV2 Luo entiteetti tämän ohjelmointirajapinnan avulla. Se toimii kuin msdyn_PssCreateV1, mutta voit luoda useita entiteettejä yhdessä toiminnossa.
msdyn_PssUpdateV1 Päivitä entiteetti tämän ohjelmointirajapinnan avulla. Entiteetti voi olla mikä tahansa päivitystoimintoa tukeva projektin aikataulutusentiteetti.
msdyn_PssUpdateV2 Päivitä entiteetit tämän ohjelmointirajapinnan avulla. Se toimii kuin msdyn_PssUpdateV1, mutta voit päivittää useita entiteettejä yhdellä toiminnolla.
msdyn_PssDeleteV1 Tämän ohjelmointirajapinnan avulla voit poistaa entiteetin. Entiteetti voi olla mikä tahansa poistotoimintoa tukeva projektin aikataulutusentiteetti.
msdyn_PssDeleteV2 Tämän ohjelmointirajapinnan avulla voit poistaa entiteettejä. Se toimii kuin msdyn_PssDeleteV1, mutta voit poistaa useita entiteettejä yhdellä toiminnolla.
msdyn_ExecuteOperationSetV1 Tämän ohjelmointirajapinnan avulla voit suorittaa kaikki toiminnot kyseisessä toimintojoukossa.
msdyn_PssUpdateResourceAssignmentV1 Tämän ohjelmointirajapinnan avulla voit päivittää Resource Assignmentin suunnitellun työmatkan.

Projektiaikataulun ohjelmointirajapintojen käyttö Operaatiojoukon kanssa

Koska sekä CreateProjectV1 että CreateTeamMemberV1 luovat tietueita välittömästi, et voi käyttää näitä ohjelmointirajapintoja suoraan Toimintojoukossa. Näiden ohjelmointirajapintojen avulla voit kuitenkin luoda pakolliset tietueet, luoda Toimintojoukon ja käyttää sitten OperationSet-toiminnon esimerkillisiä tietueita.

Tuetut toiminnot

Aikataulutusentiteetti Luominen Päivittäminen Delete Tärkeitä huomioon otettavia seikkoja
Projektitehtävä Kyllä Kyllä Kyllä Voit muokata EffortCompleted ja EffortRemaining -kenttiä Project for the Webissä, mutta et voi muokata näitä kenttiä Project Operations.
Projektitehtävän riippuvuus Kyllä Ei Kyllä Projektitehtävän riippuvuustietueita ei päivitetä. Sen sijaan voit poistaa vanhan tietueen ja luoda uuden tietueen.
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ä Ei 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 Ei Kyllä Ei Voit muuttaa tunnisteiden nimiä. Tämä toiminto on käytettävissä vain Project for the Webissä. Tunnisteet luodaan, kun avaat projektin ensimmäisen kerran.
Projektitehtävä, jolle annetaan selite Kyllä Ei 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 voit poistaa vanhan tietueen ja luoda uuden tietueen. Resurssin delegoinnin jaksojen päivittämistä varten on erillinen ohjelmointirajapinta.

Tunnusominaisuus on valinnainen. Jos annat ID-ominaisuuden, järjestelmä yrittää käyttää sitä ja aiheuttaa poikkeuksen, jos sitä ei voi käyttää. Jos et anna ID-ominaisuutta, järjestelmä luo sen.

Rajoitukset ja tunnetut ongelmat

Seuraavassa luettelossa näkyvät rajoitukset ja tunnetut ongelmat:

  • Vain Käyttäjät, joilla on Microsoft Project License voivat käyttää projektin ajoitusohjelmointirajapintoja. Seuraavat käyttäjät eivät voi käyttää näitä ohjelmointirajapintoja:

    • 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 Operaatiojoukossa voi olla vain enintään 200 toimintoa.

  • Jokaisella käyttäjällä voi olla vain enintään 10 avointa Toimintojoukkoa.

  • Jokainen Update Resource Assignment Contour -toiminto lasketaan yhdeksi toiminnoksi.

  • Jokainen päivitettyjen ääriviivojen luettelo voi sisältää jopa 100 aikaleikettä.

  • OperationSet-virheen tila- ja virhelokit eivät ole tällä hetkellä käytettävissä.

  • Jokaisessa projektissa voi olla jopa 400 sprinttiä.

  • Projektien ja tehtävien rajoitukset ja rajat.

Virheenkä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 projektin ajoituksen ohjelmointirajapinnat, jotka päivittävät entiteettiä, resource assignment contour -ohjelmointirajapinta päivittää yksinomaan yhden kentän, msdyn_plannedwork, yksittäisessä entiteetissä, msydn_resourceassignment.

Annettu aikataulutila on:

  • kiinteät yksiköt.
  • Projektikalenteri on klo 9.00–17.00 (Tyynenmeren aikaa) maanantaina, tiistaina, torstaina ja perjantaina. 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ä.

  Task 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ä määritys on sen jälkeen, kun Contour Schedule -ohjelmointirajapinnan päivitys on suoritettu.

  Task 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

Esimerkkiskenaario

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....");

Lisänäytteet

#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