Κοινή χρήση μέσω


Χρήση API χρονοδιαγράμματος έργου για την εκτέλεση λειτουργιών με οντότητες προγραμματισμού

Ισχύει για: Project Operations για σενάρια βασισμένα σε πόρους/μη εφοδιασμένα, ελαφριά ανάπτυξη - συμφωνία για προτιμολόγηση.

Οντότητες προγραμματισμού

Τα API χρονοδιαγράμματος έργου παρέχουν τη δυνατότητα εκτέλεσης λειτουργιών δημιουργίας, ενημέρωσης και διαγραφής με Οντότητες προγραμματισμού. Η διαχείριση αυτών των οντοτήτων γίνεται μέσω της μηχανής προγραμματισμού στο Έργο για το web. Οι λειτουργίες δημιουργίας, ενημέρωσης και διαγραφής με Οντότητες προγραμματισμού περιορίστηκαν σε προηγούμενες εκδόσεις του Dynamics 365 Project Operations.

Ο παρακάτω πίνακας παρέχει μια πλήρη λίστα των οντοτήτων χρονοδιαγράμματος έργου.

Όνομα οντότητας Λογικό όνομα οντότητας
Project msdyn_project
Εργασία έργου msdyn_projecttask
Εξάρτηση εργασίας έργου msdyn_projecttaskdependency
Ανάθεση πόρου msdyn_resourceassignment
Κάδος έργου msdyn_projectbucket
Μέλος ομάδας έργου msdyn_projectteam
Λίστες ελέγχου έργου msdyn_projectchecklist
Ετικέτα έργου msdyn_projectlabel
Εργασία έργου για την ετικέτα msdyn_projecttasktolabel
Κύκλος επανάληψης έργου msdyn_projectsprint

OperationSet

Το OperationSet είναι ένα μοτίβο μονάδας εργασίας που μπορεί να χρησιμοποιηθεί όταν διάφορα αιτήματα που επηρεάζουν το χρονοδιάγραμμα πρέπει να υποβληθούν σε επεξεργασία εντός μιας συναλλαγής.

API χρονοδιαγράμματος έργου

Ακολουθεί μια λίστα με τα τρέχοντα API χρονοδιαγράμματος έργου.

API Description
msdyn_CreateProjectV1 Αυτό το API χρησιμοποιείται για τη δημιουργία ενός έργου. Το έργο και ο προεπιλεγμένος κάδος έργου δημιουργούνται αμέσως. Η δημιουργία έργου μπορεί επίσης να γίνει με την προσθήκη μιας γραμμής στον πίνακα έργου με τη χρήση τυπικών Dataverse API. Αυτή η διαδικασία δεν δημιουργεί προεπιλογή για το έργο, αλλά ενδέχεται να έχει καλύτερη απόδοση.
msdyn_CreateTeamMemberV1 Αυτό το API χρησιμοποιείται για τη δημιουργία ενός μέλους ομάδας έργου. Η καρτέλα μέλους ομάδας δημιουργείται αμέσως. Η δημιουργία μέλους ομάδας μπορεί επίσης να γίνει με την προσθήκη μιας γραμμής στον πίνακα Μέλη ομάδας έργου χρησιμοποιώντας τα τυπικά API του Dataverse.
msdyn_CreateOperationSetV1 Αυτό το API μπορεί να χρησιμοποιηθεί για τον προγραμματισμό διαφόρων αιτήσεων που πρέπει να εκτελεστούν εντός μιας συναλλαγής.
msdyn_PssCreateV1 Αυτό το API χρησιμοποιείται για τη δημιουργία μιας οντότητας. Η οντότητα μπορεί να είναι οποιαδήποτε από τις οντότητες προγραμματισμού έργου που υποστηρίζουν τη λειτουργία δημιουργίας.
msdyn_PssCreateV2 Αυτό το API χρησιμοποιείται για τη δημιουργία μιας οντότητας. Λειτουργεί όπως msdyn_PssCreateV1, αλλά πολλές οντότητες μπορούν να δημιουργηθούν σε μία ενέργεια.
msdyn_PssUpdateV1 Αυτό το API χρησιμοποιείται για την ενημέρωση μιας οντότητας. Η οντότητα μπορεί να είναι οποιαδήποτε από τις οντότητες προγραμματισμού έργου που υποστηρίζουν τη λειτουργία ενημέρωσης.
msdyn_PssUpdateV2 Αυτό το API χρησιμοποιείται σε ενημερωμένες οντότητες. Λειτουργεί όπως msdyn_PssUpdateV1, αλλά πολλές οντότητες μπορούν να ενημερωθούν σε μία ενέργεια.
msdyn_PssDeleteV1 Αυτό το API χρησιμοποιείται για τη διαγραφή μιας οντότητας. Η οντότητα μπορεί να είναι οποιαδήποτε από τις οντότητες προγραμματισμού έργου που υποστηρίζουν τη λειτουργία διαγραφής.
msdyn_PssDeleteV2 Αυτό το API χρησιμοποιείται για τη διαγραφή οντοτήτων. Λειτουργεί όπως msdyn_PssDeleteV1, αλλά πολλές οντότητες μπορούν να διαγραφούν σε μία ενέργεια.
msdyn_ExecuteOperationSetV1 Αυτό το API χρησιμοποιείται για την εκτέλεση όλων των λειτουργιών εντός του δεδομένου συνόλου λειτουργιών.
msdyn_PssUpdateResourceAssignmentV1 Αυτό το API χρησιμοποιείται για την ενημέρωση μιας προγραμματισμένης εργασίας ανάθεσης πόρων.

Χρήση API χρονοδιαγράμματος έργου με το OperationSet

Επειδή οι καρτέλες δημιουργούνται αμέσως τόσο για το CreateProjectV1 όσο και για το CreateTeamMemberV1, αυτά τα API δεν μπορούν να χρησιμοποιηθούν άμεσα στο OperationSet. Ωστόσο, μπορείτε να τα χρησιμοποιήσετε για να δημιουργήσετε τις απαραίτητες καρτέλες, να δημιουργήσετε ένα OperationSet και, στη συνέχεια, να χρησιμοποιήσετε αυτές τις προ-δημιουργημένες καρτέλες στο OperationSet.

Υποστηριζόμενες λειτουργίες

Οντότητα προγραμματισμού Δημιουργία Update Delete Σημαντικές επισημάνσεις
Εργασία έργου Ναι Ναι Ναι Μπορείτε να επεξεργαστείτε τα πεδία Πρόοδος, EffortCompleted και EffortRemaining στο Project for the Web, αλλά δεν είναι δυνατή η επεξεργασία τους στο Project Operations.
Εξάρτηση εργασίας έργου Όχι όχι Όχι Οι καρτέλες εξάρτησης εργασιών έργου δεν ενημερώνονται. Αντίθετα, είναι δυνατό να διαγραφεί μια παλιά καρτέλα και να δημιουργηθεί μια νέα καρτέλα.
Ανάθεση πόρου Όχι Ναι* Όχι Οι λειτουργίες με τα ακόλουθα πεδία δεν υποστηρίζονται: BookableResourceID, Effort, EffortCompleted, EffortRemaining και PlannedWork.
Κάδος έργου Όχι Όχι Όχι Ο προεπιλεγμένος κάδος δημιουργείται με τη χρήση του API CreateProjectV1. Η υποστήριξη για τη δημιουργία και διαγραφή κάδων έργων προστέθηκε στην έκδοση ενημέρωσης 16.
Μέλος ομάδας έργου Ναι Ναι Ναι Για τη λειτουργία δημιουργίας, χρησιμοποιήστε το API CreateTeamMemberV1.
Project Όχι Όχι όχι Οι λειτουργίες με τα ακόλουθα πεδία δεν υποστηρίζονται: StateCode, BulkGenerationStatus, GlobalRevisionToken, CalendarID, Effort, EffortCompleted, EffortRemaining, Progress, Finish, TaskEarliestStart και Duration.
Λίστες ελέγχου έργου Όχι Όχι Όχι
Ετικέτα έργου όχι Όχι όχι Τα ονόματα ετικετών μπορούν να αλλάξουν. Αυτή η δυνατότητα είναι διαθέσιμη μόνο στο Project for the Web. Δημιουργούνται ετικέτες με την πρώτη φορά που ανοίγετε ένα έργο.
Εργασία έργου για την ετικέτα Όχι όχι Όχι Αυτή η δυνατότητα είναι διαθέσιμη μόνο στο Project for the Web.
Κύκλος επανάληψης έργου Όχι Όχι Όχι Το πεδίο Έναρξη πρέπει να έχει μια ημερομηνία προγενέστερη από το πεδίο Τέλος. Οι κύκλοι επανάληψης για το ίδιο έργο δεν μπορούν να επικαλύπτονται μεταξύ τους. Αυτή η δυνατότητα είναι διαθέσιμη μόνο στο Project for the Web.
Στόχος έργου Όχι Όχι Όχι Δεν υποστηρίζονται οι λειτουργίες με τα ακόλουθα πεδία: DescriptionPlainText, TaskDisplayOrder
Εργασία έργου για τον στόχο Όχι Όχι Όχι Δεν υποστηρίζονται οι λειτουργίες με τα ακόλουθα πεδία: TaskDisplayOrder

* Οι καρτέλες ανάθεσης πόρων δεν ενημερώνονται. Αντίθετα, είναι δυνατό να διαγραφεί η παλιά καρτέλα και να δημιουργηθεί μια νέα καρτέλα. Παρέχεται ξεχωριστό API για την ενημέρωση των περιγραμμάτων ανάθεσης πόρων.

Η ιδιότητα αναγνωριστικού είναι μόνο για ανάγνωση. Εάν παρέχεται η ιδιότητα αναγνωριστικού, το σύστημα προσπαθεί να τη χρησιμοποιήσει και πετάει μια εξαίρεση εάν δεν μπορεί να χρησιμοποιηθεί. Εάν δεν παρέχεται, το σύστημα το δημιουργεί.

Περιορισμοί και γνωστά προβλήματα

Ο ακόλουθος κατάλογος παρουσιάζει τους περιορισμούς και τα γνωστά προβλήματα:

  • Τα API χρονοδιαγράμματος έργου μπορούν να χρησιμοποιηθούν μόνο από Χρήστες με Άδεια χρήσης του Microsoft Project. Δεν είναι δυνατό να χρησιμοποιηθούν από:

    • Χρήστες εφαρμογής
    • Χρήστες συστήματος
    • Χρήστες ενοποίησης
    • Άλλοι χρήστες που δεν διαθέτουν την απαιτούμενη άδεια χρήσης
  • Κάθε OperationSet μπορεί να έχει μέγιστο αριθμό 200 λειτουργιών.

  • Κάθε χρήστης μπορεί να έχει μόνο μέγιστο αριθμό 10 ανοιχτών OperationSets.

  • Κάθε λειτουργία ενημέρωσης ενημέρωσης καμπύλης εκχώρησης πόρων μετράει ως μία λειτουργία.

  • Κάθε λίστα ενημερωμένων καμπυλών μπορεί να περιέχει το πολύ έως 100 τμήματα χρόνου.

  • Η κατάσταση αποτυχίας και τα αρχεία καταγραφής αποτυχίας του OperationSet δεν είναι αυτή τη στιγμή διαθέσιμα.

  • Υπάρχει μέγιστο όριο 400 κύκλοι επανάληψης ανά έργο.

  • Όρια και περιορισμοί για έργα και εργασίες.

Χειρισμός σφαλμάτων

  • Για να εξετάσετε τα σφάλματα που δημιουργούνται από τα σύνολα λειτουργιών, μεταβείτε στην επιλογή Ρυθμίσεις>Προγραμματισμός ενοποίησης>Σύνολα λειτουργιών.
  • Για να εξετάσετε τα σφάλματα που δημιουργούνται από την υπηρεσία χρονοδιαγράμματος έργου, μεταβείτε στις Ρυθμίσεις>Προγραμματισμός ενοποίησης>Αρχεία καταγραφής σφαλμάτων PSS.

Επεξεργασία καμπύλων εκχώρησης πόρων

Σε αντίθεση με όλα τα άλλα API προγραμματισμού έργου που ενημερώνουν μια οντότητα, το API καμπύλης ανάθεσης πόρων είναι αποκλειστικά υπεύθυνο για τις ενημερώσεις σε ένα μόνο πεδίο, msdyn_plannedwork, σε μία μόνο οντότητα msydn_resourceassignment.

Η δεδομένη λειτουργία χρονοδιαγράμματος είναι:

  • σταθερές μονάδες.
  • Το ημερολόγιο έργου είναι από τις 9:00 έως τις 5:00 μμ (Ώρα Ειρηνικού) Δευτέρα, Τρίτη, Πέμπτη και Παρασκευή. (Δεν υπάρχει εργασία τις Τετάρτες.)
  • Το ημερολόγιο πόρων είναι από τις 9:00 π.μ. έως τις 1:00 μμ (Ώρα Ειρηνικού) Δευτέρα έως Παρασκευή.

Αυτή η ανάθεση είναι για μία εβδομάδα, τέσσερις ώρες την ημέρα, επειδή το ημερολόγιο πόρων είναι από τις 9:00 π.μ. έως τη 1:00 μ.μ. (ώρα Ειρηνικού) ή τέσσερις ώρες την ημέρα.

  Εργασία Ημερομηνία έναρξης Ημερομηνία λήξης Ποσότητα 6/13/2022 6/14/2022 6/15/2022 6/16/2022 6/17/2022
9-1 υπάλληλος T1 6/13/2022 6/17/2022 20 4 4 4 4 4

Για παράδειγμα, εάν θέλετε ο εργαζόμενος να εργάζεται μόνο τρεις ώρες κάθε ημέρα αυτήν την εβδομάδα και να έχει μια ώρα για άλλες εργασίες.

Δείγμα ωφέλιμου φορτίου UpdatedContours

[{

"minutes":900.0,

"start":"2022-06-13T00:00:00-07:00",

"end":"2022-06-18T00:00:00-07:00"

}]

Αυτή είναι η εκχώρηση μετά την εκτέλεση του API χρονοδιαγράμματος ενημέρωσης καμπύλης.

  Κλείσιμο εργασίας Ημερομηνία έναρξης Ημερομηνία λήξης Ποσότητα 6/13/2022 6/14/2022 6/15/2022 6/16/2022 6/17/2022
9-1 υπάλληλος T1 6/13/2022 6/17/2022 15 3 3 3 3 3

Δείγμα σεναρίου

Σε αυτό το σενάριο, δημιουργείτε ένα έργο, ένα μέλος ομάδας, τέσσερις εργασίες και δύο αναθέσεις πόρων. Στη συνέχεια, ενημερώνετε μία εργασία, θα ενημερώσετε το έργο, θα ενημερώσετε μια καμπύλη ανάθεσης πόρου, θα διαγράψετε μια εργασία, θα διαγράψετε μία ανάθεση πόρου και θα δημιουργήσετε μια εξάρτηση εργασίας.

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

Πρόσθετα δείγματα

#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