Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Berlaku untuk: Project Operations Terintegrasi dengan ERP, Project Operations Core.
Menjadwalkan entitas
API jadwal proyek menyediakan kemampuan untuk membuat, memperbarui, dan menghapus entitas Penjadwalan. Mesin Penjadwalan di Project untuk web mengelola entitas ini. Rilis Dynamics 365 Project Operations sebelumnya membatasi operasi pembuatan, pembaruan, dan penghapusan untuk entitas Scheduling.
Tabel berikut menyediakan daftar lengkap entitas jadwal Proyek.
| Nama entitas | Nama logika entitas |
|---|---|
| Proyek | msdyn_project |
| Tugas Proyek | msdyn_projecttask |
| Dependensi Tugas Proyek | msdyn_projecttaskdependency |
| Penetapan Sumber Daya | msdyn_resourceassignment |
| Wadah Proyek | msdyn_projectbucket |
| Anggota Tim Proyek | msdyn_projectteam |
| Daftar Periksa Proyek | msdyn_projectchecklist |
| Label Proyek | msdyn_projectlabel |
| Tugas Proyek yang akan Dilabeli | msdyn_projecttasktolabel |
| Sprint Proyek | msdyn_projectsprint |
OperationSet
Gunakan OperationSet sebagai unit kerja saat Anda perlu memproses beberapa permintaan yang memengaruhi jadwal dalam transaksi.
API jadwal proyek
Daftar berikut menunjukkan API jadwal Project saat ini.
| API | Deskripsi |
|---|---|
| msdyn_CreateProjectV1 | Gunakan API ini untuk membuat project. Ini segera membuat proyek dan bucket proyek default. Anda juga dapat membuat proyek dengan menambahkan baris ke tabel proyek dengan menggunakan API Dataverse standar. Proses ini tidak membuat bucket default untuk proyek tetapi mungkin memiliki performa yang lebih baik. |
| msdyn_CreateTeamMemberV1 | Gunakan API ini untuk membuat anggota tim proyek. Ini segera membuat catatan anggota tim. Anda juga dapat membuat anggota tim dengan menambahkan baris ke tabel Anggota Tim Proyek dengan menggunakan API Dataverse standar. |
| msdyn_CreateOperationSetV1 | Gunakan API ini untuk menjadwalkan beberapa permintaan yang harus dilakukan dalam transaksi. |
| msdyn_PssCreateV1 | Gunakan API ini untuk membuat entitas. Entitas dapat merupakan entitas penjadwalan Proyek yang mendukung operasi pembuatan. |
| msdyn_PssCreateV2 | Gunakan API ini untuk membuat entitas. Ini berfungsi seperti msdyn_PssCreateV1, tetapi Anda dapat membuat beberapa entitas dalam satu tindakan. |
| msdyn_PssUpdateV1 | Gunakan API ini untuk memperbarui entitas. Entitas dapat merupakan entitas penjadwalan Proyek yang mendukung operasi pembaruan. |
| msdyn_PssUpdateV2 | Gunakan API ini untuk memperbarui entitas. Ini berfungsi seperti msdyn_PssUpdateV1, tetapi Anda dapat memperbarui beberapa entitas dalam satu tindakan. |
| msdyn_PssDeleteV1 | Gunakan API ini untuk menghapus entitas. Entitas dapat merupakan entitas penjadwalan Proyek yang mendukung operasi penghapusan. |
| msdyn_PssDeleteV2 | Gunakan API ini untuk menghapus entitas. Ini berfungsi seperti msdyn_PssDeleteV1, tetapi Anda dapat menghapus beberapa entitas dalam satu tindakan. |
| msdyn_ExecuteOperationSetV1 | Gunakan API ini untuk menjalankan semua operasi dalam kumpulan operasi yang diberikan. |
| msdyn_PssUpdateResourceAssignmentV1 | Gunakan API ini untuk memperbarui kontur kerja yang direncanakan Penetapan Sumber Daya. |
Menggunakan API jadwal Project dengan OperationSet
Karena CreateProjectV1 dan CreateTeamMemberV1 segera membuat rekaman, Anda tidak dapat menggunakan API ini secara langsung di OperationSet. Namun, Anda dapat menggunakan API ini untuk membuat rekaman yang diperlukan, membuat OperationSet, lalu menggunakan rekaman yang telah dibuat sebelumnya di OperationSet.
Operasi yang Didukung
| Entitas Penjadwalan | Create | Update | Delete | Pertimbangan penting |
|---|---|---|---|---|
| Tugas proyek | Yes | Yes | Yes | Anda dapat mengedit bidang EffortCompleted dan EffortRemaining di Project untuk Web, tetapi Anda tidak dapat mengedit bidang ini di Project Operations. |
| Dependensi Tugas Proyek | Yes | No | Yes | Rekaman dependensi tugas proyek tidak diperbarui. Sebagai gantinya, Anda dapat menghapus rekaman lama dan membuat rekaman baru. |
| Penugasan Sumber Daya | Yes | Ya* | Yes | Operasi dengan bidang berikut tidak didukung: BookableResourceID,Upaya,UpayaSelesai,UpayaRemaining, dan PlannedWork. |
| Wadah Proyek | Yes | Yes | Yes | Wadah default dibuat dengan menggunakan API CreateProjectV1 . Dukungan untuk membuat dan menghapus wadah proyek telah ditambahkan dalam Pembaruan Release 16. |
| Anggota Tim Proyek | Yes | Yes | Yes | Untuk operasi buat, gunakan API CreateTeamMemberV1 . |
| Proyek | Yes | Yes | No | Operasi dengan bidang berikut tidak didukung: StateCode,BulkGenerationStatus,GlobalRevisionToken,CalendarID,Upaya,EffortCompleted,EffortRemaining,Progress,Finish,TaskEarliestStart, dan Duration. |
| Daftar Periksa Proyek | Yes | Yes | Yes | |
| Label Proyek | No | Yes | No | Anda dapat mengubah nama label. Fitur ini hanya tersedia untuk Project for the Web. Label dibuat saat pertama kali Anda membuka proyek. |
| Tugas Proyek yang akan Dilabeli | Yes | No | Yes | Fitur ini hanya tersedia untuk Project for the Web. |
| Sprint Proyek | Yes | Yes | Yes | Bidang Mulai harus memiliki tanggal lebih awal dari bidang Selesai. Sprint untuk proyek yang sama tidak dapat tumpang tindih satu sama lain. Fitur ini hanya tersedia untuk Project for the Web. |
| Sasaran Proyek | Yes | Yes | Yes | Operasi dengan bidang berikut tidak didukung: DescriptionPlainText, TaskDisplayOrder |
| Tugas Proyek untuk Sasaran | Yes | No | Yes | Operasi dengan bidang berikut tidak didukung: TaskDisplayOrder |
* Rekaman penetapan sumber daya tidak diperbarui. Sebagai gantinya, Anda dapat menghapus catatan lama dan membuat catatan baru. API terpisah disediakan untuk memperbarui kontur Penetapan Sumber Daya.
Properti ID bersifat opsional. Jika Anda memberikan properti ID, sistem mencoba menggunakannya dan melemparkan pengecualian jika tidak dapat digunakan. Jika Anda tidak memberikan properti ID, sistem akan menghasilkannya.
Keterbatasan dan masalah yang diketahui
Daftar berikut menunjukkan batasan dan masalah yang diketahui:
Hanya Pengguna dengan Lisensi Microsoft Project yang dapat menggunakan API Jadwal Proyek. Pengguna berikut tidak dapat menggunakan API ini:
- Pengguna aplikasi
- Pengguna Sistem
- Pengguna Integrasi
- Pengguna lain yang tidak memiliki lisensi yang diperlukan
Setiap OperationSet hanya dapat memiliki hingga 200 operasi.
Setiap pengguna hanya dapat memiliki hingga 10 OperationSet terbuka.
Setiap operasi Kontur Penetapan Penetapan Sumber Daya Perbarui dihitung sebagai satu operasi.
Setiap daftar kontur yang diperbarui dapat berisi hingga 100 irisan waktu.
Status kegagalan OperationSet dan log kegagalan saat ini tidak tersedia.
Setiap proyek dapat memiliki hingga 400 sprint.
Penanganan kesalahan
- Untuk meninjau kesalahan yang dihasilkan dari Set Operasi, buka Pengaturan Jadwalkan>Set Operasi> Integrasi.
- Untuk meninjau kesalahan yang dihasilkan dari Layanan jadwal proyek, buka Log Kesalahan> PSS Integrasi>Jadwal Pengaturan.
Mengedit kontur penetapan sumber daya
Tidak seperti semua API penjadwalan proyek lainnya yang memperbarui entitas, API kontur penetapan sumber daya hanya memperbarui satu bidang, msdyn_plannedwork, pada satu entitas, msydn_resourceassignment.
Mode jadwal yang ditentukan adalah:
- unit tetap.
- Kalender proyek adalah dari pukul 09:00 hingga 17:00 (Waktu Pasifik) Senin, Selasa, Kamis, dan Jumat. (Tidak ada pekerjaan pada hari Rabu.)
- Kalender sumber daya adalah dari pukul 09.00 hingga 1.00 (Waktu Pasifik) Senin hingga Jumat.
Penugasan ini selama satu minggu, empat jam sehari karena kalender sumber daya adalah dari pukul 09.00 hingga 1.00 (Waktu Pasifik), atau empat jam sehari.
| Tugas | Tanggal Mulai | Tanggal Selesai | Kuantitas | 13/6/2022 | 14/6/2022 | 15/6/2022 | 16/6/2022 | 17/6/2022 | |
|---|---|---|---|---|---|---|---|---|---|
| Pekerja 9-1 | T1 | 13/6/2022 | 17/6/2022 | 20 | 4 | 4 | 4 | 4 | 4 |
Misalnya, jika Anda ingin agar pekerja hanya bekerja tiga jam setiap hari di minggu ini dan memungkinkan selama satu jam untuk tugas lainnya.
Muatan sampel UpdateContours
[{
"minutes":900.0,
"start":"2022-06-13T00:00:00-07:00",
"end":"2022-06-18T00:00:00-07:00"
}]
Penetapan ini dilakukan setelah API Jadwal Kontur Perbarui berjalan.
| Tugas | Tanggal Mulai | Tanggal Selesai | Kuantitas | 13/6/2022 | 14/6/2022 | 15/6/2022 | 16/6/2022 | 17/6/2022 | |
|---|---|---|---|---|---|---|---|---|---|
| Pekerja 9-1 | T1 | 13/6/2022 | 17/6/2022 | 15 | 3 | 3 | 3 | 3 | 3 |
Contoh skenario
Dalam skenario ini, Anda membuat proyek, anggota tim, empat tugas, dan dua penugasan sumber daya. Selanjutnya, Anda memperbarui satu tugas, memperbarui proyek, memperbarui kontur penetapan sumber daya, menghapus satu tugas, menghapus satu penetapan sumber daya, dan membuat dependensi tugas.
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....");
Sampel tambahan
#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