TeamcenterKnowledge

Skills

TC Schedule Program Planning

Skill tc-schedule-program-planning. Author Teamcenter Schedule Manager schedules and IPP&E program structure over SOA. The createSchedule path and the single site preference that silently blocks it site-wide, the root-task lazy-creation gotcha, the coordinator-membership gap, and the Psi0WorkElement precedence-network alternative. Use for schedules, tasks, milestones, WBS, IMP or program-planning work in TC.

Native Schedule Manager over REST works. One site preference decides it.

ProjectManagement-2008-06-ScheduleManagement/createSchedule with a newSchedules container is the real path and the payload the AWC itself POSTs.

The blocker that looks like a dead transport

createSchedule returning 200 OK with empty output (only updated: [UserSession]) is not a transport failure and not a payload error. The real reason is in ServiceData.partialErrors:

code 230305 - The preference "SiteTimeZone" is required to be set for the
              Schedule Manager application.

getPreferences(['SiteTimeZone']) shows the preference defined (category "Schedule Manager", string, single-value, protectionScope Site) but with no value. In that state Schedule Manager rejects every create, for everyone, including the native AWC Create button. The AWC's own button creates nothing either, which is the tell that it is not your code.

Fix: an admin sets SiteTimeZone at SITE scope to a valid zoneinfo region/city (America/Chicago). Rich client: Edit > Options, search "SiteTimeZone". A Designer role cannot do it.

After the admin sets it, a client-side refresh does not pick it up. The running tcserver caches it, and refreshPreferences operations fault 214085/214086 over REST. The user must re-log in so a fresh session/pool reads the value. Once that happened, the exact same previously-failing payload created real persisted schedules with zero partial errors.

The generalizable lesson: surface ServiceData.partialErrors in every error path. Swallowing it is what produced a confident, wrong "the write path is dead over REST" conclusion that stood overnight.

Two follow-ons for a polished schedule

  1. Raw createSchedule does not add the creator as coordinator. The schedule exists and reads back fine, but does not appear in the AWC's ?privilege=coordinator "Not Started" list. Add coordinator membership as part of the push.
  2. The response does not return the root ScheduleTask uid (it is created lazily). To hang tasks: load the schedule and getProperties to fetch the root task first, then createTasks with parent = {root uid, type: ScheduleTask}.

What the Active Workspace Gantt can and cannot do

Confirmed with coordinator privilege on a live AW instance:

Works in AW Blocked in AW (silent no-op or a toast)
Add Task, Add Milestone Delete (even leaf tasks)
Inline rename via the Name-cell editor Cut / Paste
Indent of a last-position row, Outdent Drag-reorder
Planned Start/Finish date-cell edit Indent of a mid-list row
Create Dependency (no link forms)

Net effect: nesting, reordering and dependency links must be finished in the rich client (2-tier). This is the same relational/hierarchical write block that also stops IPP&E Accomplishment/Criteria/Work-Package creation from the AW browser, while flat adds (Events, Risks, Deliverables) work fine.

Working-calendar gotcha: with a Mon-Fri 09:00-18:00 calendar, a 1-day task starting after 09:00 on the schedule's last day overflows the window and the date edit reverts. Only 0-day milestones hold there. Start full-day tasks at 09:00 or shorten the duration.

The IPP&E alternative: a precedence network

Where native Schedule Manager is blocked, IPP&E Item-rooted objects go in through the ordinary createAttachAndSubmitObjects engine, because they are just Items:

  • Types confirmed deployed: Wbs0Root, Wbs0Element, Psi0WorkElement, Prg0ProgramPlan, Ipp0IPT.
  • A real schedule as a Psi0WorkElement precedence network: one work element per task, chained by the relation Psi0PredecessorWorkElement (revision to revision, primary = successor, secondary = predecessor).
  • That relation reads back as a same-named reference property on each successor revision, so it is machine-verifiable in one getProperties call. See tc-relations-traceability.

Known gaps on that path:

  • Ipp0IMPAccomplishment needs a required "IMP Element ID" property whose real internal name is unknown; ipp0IMPElementID is wrong, and the create-input descriptor is Ipp0IMPAccomplishmentCreI.
  • WBS parent/child containment (Wbs0Root to Wbs0Element) is a BOM structure operation, not a GRM relation. Wbs0ApplRelatedStruct is rejected with code
    1. Use the BOM/BVR add-children path. See tc-bom-structure.
  • Prg0ProgramPlan faults "invalid input object" via plain createAttachAndSubmitObjects. Program Planning has its own create flow.

IMP master-plan gotcha in AW

Adding an IMP Accomplishment under an Event opens a panel requiring Accomplishment ID, Name and IMP Element ID. Overriding the auto-generated Accomplishment ID (for example to "A1") makes the create silently no-op. Leave the auto ACMxxxxxxxx id and set only Name and IMP Element ID. Even then the create does not persist in AW; build Accomplishments, Criteria and Work Packages in the rich client.

Prefer native Schedule Manager once unblocked

Both paths work. Native Schedule Manager is the one that shows up in the Schedule Manager UI and that existing sync code targets; the IPP&E precedence network is the fallback when a site preference or privilege cannot be changed.

Related skills

tc-object-authoring, tc-relations-traceability, tc-soa-payload-shapes, tc-bom-structure.

Not every blocked tier is the SiteTimeZone tier

EXERCISED on saber2506 (TC 2506) 2026-09-01. The SiteTimeZone story above is real but it is ONE cause, and reaching for it first cost time here.

On this tier createSchedule never produced 230305 at all. It returned 214022 across five attempts, and an earlier version of this section concluded the payload was "unsettled". ★ Corrected the same day: the payload was simply WRONG, and once fixed the real blocker is a licence.

The exact working payload, and the one member that decides it

NewScheduleContainer is 20 required XML attributes (flat JSON members) plus billRate (NULLTAG) and two optional containers. Types matter and must come from the XSD, not from guessing: 10 strings, 2 xsd:dateTime, 3 xsd:integer (priority, status, taskFixedType), 5 xsd:boolean.

{"newSchedules":[{
  "billRate":{"uid":"AAAAAAAAAAAAAA","type":"unknownType"},
  "stringValueContainer":[],          <-- ARRAY. `{}` here returns 214022.
  "typedAttributesContainer":[],
  "name":"<name>","description":"","id":"","revID":"",
  "customerName":"","customerNumber":"",
  "startDate":"2026-09-01T09:00:00-04:00","finishDate":"2026-12-18T17:00:00-05:00",
  "priority":3,"status":0,"taskFixedType":1,
  "published":true,"notificationsEnabled":false,"percentLinked":true,
  "isTemplate":false,"isPublic":true,
  "type":"Schedule","billCode":"","billSubCode":"","billType":""}]}

⚠⚠ stringValueContainer is a StringValContainer carrying a required @key, and it still wants an ARRAY, not a map. This is worth stating loudly because the sibling recipe in tc-object-authoring has the OPPOSITE answer: reviseObjects' reviseInputs is a PropertyValues, also @key-bearing, and it needs {} while [] faults. A required @key does NOT reliably predict map-vs-array in this binding. Both were settled by flipping that one member and re-running, which is a two-minute experiment; do that rather than reasoning from the other recipe.

What the correct payload revealed, and the wrong conclusion drawn from it

26023  The current user is not licensed to perform authoring functions in Teamcenter.

That was measured as infodba (privileged: true, licence level 5, dba/DBA) in a session that had just created items, relations and a revision, and written up as "Schedule Manager is gated by a MODULE licence on that tier".

★★★ That was WRONG, corrected the same hour. license_level is a CLASS, not a ranking.

license_level meaning
0 Author
1 Consumer
2 Occasional User
3 Viewer
5 Admin

Read that LOV before interpreting the number: getInitialLOVValues with lovInput.boName "User", propertyName "license_level".

Level 5 is Admin, and Admin is not Author. The message says "not licensed to perform authoring functions" and means it literally. Both accounts in use (infodba and dcproxy) were level 5, which is why swapping between them changed nothing and made the gate look tier-wide. A third account on the SAME host, same release, same project, at level 0 with an engineering group and role, created a real Schedule (root task, its own TCCalendar, and a ScheduleMember at coordinator privilege) and an SSP0ServicePlan, first try, no payload change at all.

Why the wrong conclusion survived a control. The control was sound in isolation: a known-good Document create succeeded in the SAME call that the Service Plan refused, which genuinely proves the session can write. It does not prove the account can AUTHOR in the licence sense, because ordinary item creation is not gated the way Schedule Manager and Service Lifecycle are. The control tested a weaker property than the claim needed. Two accounts agreeing added nothing either, because they shared the licence class: that is [[false-corroboration]], not corroboration.

⇒ Before ever calling 26023 a tier or module licence, enumerate the accounts you have and check license_level on each. It is one getTCSessionInfo per account, and here it was the difference between "needs an admin licensing decision" and "use the other credential".

⇒ Two lessons, and the second is the expensive one. Read partialErrors before choosing which failure you are looking at; and do not let a persistent parse error stand in for a diagnosis. "The payload is unsettled" reads like a finding and is really an absence of one: it names no cause, cannot be acted on, and here it was hiding a licence fault that a single correct request exposed immediately.

The IPP&E fallback carried the capability. Six Psi0WorkElement items chained by Psi0PredecessorWorkElement produced a real fork/join network (two work elements joining at a third), each also FND_TraceLink-ed to the deliverable it produces. Confirmed the skill's claim that it is machine-verifiable in one getProperties call, and worth doing from a second login: the successor with two predecessors listed both, which is the check that distinguishes a real network from a create response that merely echoed the input.

Adding tasks: createTasks, and the one type that faults

ProjectManagement-2012-02-ScheduleManagement/createTasks. The root ScheduleTask uid is in the createSchedule response's ServiceData.updated (it carries schedule_tag pointing back at the schedule), so the documented "load it separately" step is avoidable.

{"schedule":{"uid":"<Schedule uid>","type":"Schedule"},
 "createContainers":[{
   "parent":{"uid":"<root ScheduleTask uid>","type":"ScheduleTask"},
   "prevSibling":{"uid":"AAAAAAAAAAAAAA","type":"unknownType"},
   "otherAttributes":[], "typedOtherAttributes":[],
   "name":"<name>","desc":"<desc>","objectType":"ScheduleTask",
   "start":"2026-09-01T09:00:00-04:00","finish":"2026-09-25T17:00:00-04:00",
   "workEstimate":0}]}

workEstimate is xsd:integer. Sending "0" as a STRING returns 214022 naming nothing, exactly like a malformed envelope. Six tasks went in unchanged once it was a JSON number, and the root task's duration recomputed on its own.

★ Note this tier had SiteTimeZone set all along (the created TCCalendar carries America/Chicago), so the preference blocker at the top of this skill never applied here. Three different causes have now worn the same 214022/empty-200 mask on this operation: an unset preference, a wrong member type, and a wrong licence class. Diagnose, do not pattern-match.


Generated from skills/tc-schedule-program-planning/SKILL.md in the tc-automation-skills library, which is the canonical copy and also serves as the agent skill set for Teamcenter work.