@outbuild-company/schedule-core 1.23.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +168 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +168 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6287,7 +6287,9 @@ var P6_PERCENT_COMPLETE_TYPE = {
|
|
|
6287
6287
|
var P6_ACTIVITY_TYPE = {
|
|
6288
6288
|
TASK: "task",
|
|
6289
6289
|
LEVEL_OF_EFFORT: "level_of_effort",
|
|
6290
|
-
START_MILESTONE: "start_milestone"
|
|
6290
|
+
START_MILESTONE: "start_milestone",
|
|
6291
|
+
RESOURCE_DEPENDENT: "resource_dependent"
|
|
6292
|
+
};
|
|
6291
6293
|
var P6_EXECUTION_STATUS = {
|
|
6292
6294
|
NOT_STARTED: "not_started",
|
|
6293
6295
|
IN_PROGRESS: "in_progress",
|
|
@@ -11979,14 +11981,65 @@ function createOutbuildP6ActivityDraft(activity) {
|
|
|
11979
11981
|
if (state === void 0) return void 0;
|
|
11980
11982
|
return {
|
|
11981
11983
|
...state,
|
|
11982
|
-
|
|
11984
|
+
...outbuildProgressExecution(activity, activity.durationHours)
|
|
11983
11985
|
};
|
|
11984
11986
|
}
|
|
11985
|
-
|
|
11987
|
+
var COMPLETED_PHYSICAL_PERCENT = 100;
|
|
11988
|
+
var NOT_STARTED_PHYSICAL_PERCENT = 0;
|
|
11989
|
+
function outbuildProgressExecution(activity, originalDurationHours) {
|
|
11986
11990
|
if (activity.progress === NOT_STARTED_PROGRESS) {
|
|
11987
|
-
return
|
|
11991
|
+
return {
|
|
11992
|
+
executionStatus: P6_EXECUTION_STATUS.NOT_STARTED,
|
|
11993
|
+
actualStart: null,
|
|
11994
|
+
actualFinish: null,
|
|
11995
|
+
remainingDurationHours: originalDurationHours,
|
|
11996
|
+
physicalPercentComplete: NOT_STARTED_PHYSICAL_PERCENT,
|
|
11997
|
+
actualDurationHours: 0,
|
|
11998
|
+
atCompletionDurationHours: originalDurationHours,
|
|
11999
|
+
durationPercentComplete: 0
|
|
12000
|
+
};
|
|
11988
12001
|
}
|
|
11989
|
-
|
|
12002
|
+
const actualStart = cloneValidDate(activity.startDate, "actualStart");
|
|
12003
|
+
if (isCompletedProgress(activity.progress)) {
|
|
12004
|
+
const hasMeasurableDuration = originalDurationHours > 0;
|
|
12005
|
+
return {
|
|
12006
|
+
executionStatus: P6_EXECUTION_STATUS.COMPLETED,
|
|
12007
|
+
actualStart,
|
|
12008
|
+
actualFinish: cloneValidDate(activity.endDate, "actualFinish"),
|
|
12009
|
+
remainingDurationHours: 0,
|
|
12010
|
+
physicalPercentComplete: COMPLETED_PHYSICAL_PERCENT,
|
|
12011
|
+
actualDurationHours: originalDurationHours,
|
|
12012
|
+
atCompletionDurationHours: originalDurationHours,
|
|
12013
|
+
durationPercentComplete: hasMeasurableDuration ? COMPLETED_PHYSICAL_PERCENT : NOT_STARTED_PHYSICAL_PERCENT
|
|
12014
|
+
};
|
|
12015
|
+
}
|
|
12016
|
+
return {
|
|
12017
|
+
executionStatus: P6_EXECUTION_STATUS.IN_PROGRESS,
|
|
12018
|
+
actualStart,
|
|
12019
|
+
actualFinish: null,
|
|
12020
|
+
remainingDurationHours: originalDurationHours,
|
|
12021
|
+
physicalPercentComplete: activity.progress,
|
|
12022
|
+
actualDurationHours: 0,
|
|
12023
|
+
atCompletionDurationHours: originalDurationHours,
|
|
12024
|
+
durationPercentComplete: 0
|
|
12025
|
+
};
|
|
12026
|
+
}
|
|
12027
|
+
function awaitsOutbuildExecution(draft) {
|
|
12028
|
+
return draft.executionStatus === P6_EXECUTION_STATUS.NOT_STARTED && draft.actualStart === null;
|
|
12029
|
+
}
|
|
12030
|
+
function reconcileOutbuildProgress(activity, draft) {
|
|
12031
|
+
const isProgressed = activity.progress !== NOT_STARTED_PROGRESS;
|
|
12032
|
+
if (!isProgressed || !awaitsOutbuildExecution(draft)) return draft;
|
|
12033
|
+
const inferred = outbuildProgressExecution(
|
|
12034
|
+
activity,
|
|
12035
|
+
draft.originalDurationHours
|
|
12036
|
+
);
|
|
12037
|
+
const keepsRecordedRemaining = inferred.executionStatus === P6_EXECUTION_STATUS.IN_PROGRESS && draft.remainingDurationHours !== null;
|
|
12038
|
+
return {
|
|
12039
|
+
...draft,
|
|
12040
|
+
...inferred,
|
|
12041
|
+
...keepsRecordedRemaining ? { remainingDurationHours: draft.remainingDurationHours } : {}
|
|
12042
|
+
};
|
|
11990
12043
|
}
|
|
11991
12044
|
|
|
11992
12045
|
// src/p6/inactive-drafts.ts
|
|
@@ -12039,17 +12092,41 @@ function ordinaryInputChanges(before, activity) {
|
|
|
12039
12092
|
...before.startDate.getTime() !== activity.startDate.getTime() ? { plannedStart: new Date(activity.startDate) } : {},
|
|
12040
12093
|
...before.endDate.getTime() !== activity.endDate.getTime() ? { plannedFinish: new Date(activity.endDate) } : {},
|
|
12041
12094
|
...durationChanged ? { originalDurationHours: activity.durationHours } : {},
|
|
12042
|
-
...durationChanged || before.progress !== activity.progress ?
|
|
12095
|
+
...durationChanged || before.progress !== activity.progress ? executionInputChanges(before, activity, durationChanged) : {}
|
|
12043
12096
|
};
|
|
12044
12097
|
}
|
|
12045
|
-
function
|
|
12098
|
+
function executionInputChanges(before, activity, durationChanged) {
|
|
12046
12099
|
const current = activity.p6;
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
const
|
|
12100
|
+
const hasExplicitRemainingCorrection = current.remainingDurationHours !== before.p6.remainingDurationHours;
|
|
12101
|
+
if (hasExplicitRemainingCorrection) return {};
|
|
12102
|
+
const progressChanged = before.progress !== activity.progress;
|
|
12103
|
+
const resetsToNotStarted = progressChanged && activity.progress === NOT_STARTED_PROGRESS;
|
|
12104
|
+
if (awaitsOutbuildExecution(current) || resetsToNotStarted) {
|
|
12105
|
+
const originalDurationHours = durationChanged ? activity.durationHours : current.originalDurationHours;
|
|
12106
|
+
return outbuildProgressExecution(activity, originalDurationHours);
|
|
12107
|
+
}
|
|
12108
|
+
const isStarted = current.actualStart !== null;
|
|
12109
|
+
if (!isStarted || !progressChanged) return {};
|
|
12110
|
+
return startedProgressChanges(current, activity);
|
|
12111
|
+
}
|
|
12112
|
+
function startedProgressChanges(current, activity) {
|
|
12113
|
+
const mirrorsPhysicalPercent = current.percentCompleteType === P6_PERCENT_COMPLETE_TYPE.PHYSICAL;
|
|
12114
|
+
if (!isCompletedProgress(activity.progress)) {
|
|
12115
|
+
return {
|
|
12116
|
+
...current.actualFinish === null ? {} : {
|
|
12117
|
+
executionStatus: P6_EXECUTION_STATUS.IN_PROGRESS,
|
|
12118
|
+
actualFinish: null
|
|
12119
|
+
},
|
|
12120
|
+
...mirrorsPhysicalPercent ? { physicalPercentComplete: activity.progress } : {}
|
|
12121
|
+
};
|
|
12122
|
+
}
|
|
12123
|
+
const finishesAfterActualStart = current.actualStart !== null && activity.endDate.getTime() >= current.actualStart.getTime();
|
|
12124
|
+
if (current.actualFinish !== null || !finishesAfterActualStart) return {};
|
|
12050
12125
|
return {
|
|
12051
|
-
|
|
12052
|
-
|
|
12126
|
+
executionStatus: P6_EXECUTION_STATUS.COMPLETED,
|
|
12127
|
+
actualFinish: new Date(activity.endDate),
|
|
12128
|
+
remainingDurationHours: 0,
|
|
12129
|
+
physicalPercentComplete: COMPLETED_PROGRESS
|
|
12053
12130
|
};
|
|
12054
12131
|
}
|
|
12055
12132
|
|
|
@@ -17941,6 +18018,7 @@ var LOAD_DIAGNOSTIC_SAMPLE_LIMIT = 10;
|
|
|
17941
18018
|
var LOAD_DIAGNOSTIC_CODE = {
|
|
17942
18019
|
INVALID_BASELINE_POINT: "invalid_baseline_point",
|
|
17943
18020
|
UNKNOWN_CONSTRAINT: "unknown_constraint",
|
|
18021
|
+
PROGRESS_OUT_OF_RANGE: "progress_out_of_range",
|
|
17944
18022
|
ORPHAN_ACTIVITY: "orphan_activity",
|
|
17945
18023
|
INVALID_LINK: "invalid_link",
|
|
17946
18024
|
DUPLICATE_LINK: "duplicate_link"
|
|
@@ -17948,6 +18026,7 @@ var LOAD_DIAGNOSTIC_CODE = {
|
|
|
17948
18026
|
var LOAD_DIAGNOSTIC_CODE_ORDER = [
|
|
17949
18027
|
LOAD_DIAGNOSTIC_CODE.INVALID_BASELINE_POINT,
|
|
17950
18028
|
LOAD_DIAGNOSTIC_CODE.UNKNOWN_CONSTRAINT,
|
|
18029
|
+
LOAD_DIAGNOSTIC_CODE.PROGRESS_OUT_OF_RANGE,
|
|
17951
18030
|
LOAD_DIAGNOSTIC_CODE.ORPHAN_ACTIVITY,
|
|
17952
18031
|
LOAD_DIAGNOSTIC_CODE.INVALID_LINK,
|
|
17953
18032
|
LOAD_DIAGNOSTIC_CODE.DUPLICATE_LINK
|
|
@@ -24753,12 +24832,21 @@ function normalizePersistedActivityId(rawId) {
|
|
|
24753
24832
|
}
|
|
24754
24833
|
return rawId;
|
|
24755
24834
|
}
|
|
24756
|
-
function parseProgress(raw) {
|
|
24835
|
+
function parseProgress(raw, reporter, recordDiagnostic, activityId) {
|
|
24757
24836
|
const progress = Number(raw);
|
|
24758
|
-
if (!Number.isFinite(progress)
|
|
24837
|
+
if (!Number.isFinite(progress)) {
|
|
24759
24838
|
throw new TypeError(`invalid activity progress ${String(raw)}`);
|
|
24760
24839
|
}
|
|
24761
|
-
|
|
24840
|
+
const isBelowNotStarted = progress < NOT_STARTED_PROGRESS;
|
|
24841
|
+
const isAboveCompleted = progress > MAX_TOLERATED_PROGRESS;
|
|
24842
|
+
const isWithinRange = !isBelowNotStarted && !isAboveCompleted;
|
|
24843
|
+
if (isWithinRange) return progress;
|
|
24844
|
+
const clamped = isBelowNotStarted ? NOT_STARTED_PROGRESS : COMPLETED_PROGRESS;
|
|
24845
|
+
recordDiagnostic(LOAD_DIAGNOSTIC_CODE.PROGRESS_OUT_OF_RANGE, activityId);
|
|
24846
|
+
reporter.warn(
|
|
24847
|
+
`[parseFromBackend] activity "${activityId}" progress ${String(raw)} is out of range \u2014 clamping to ${clamped}`
|
|
24848
|
+
);
|
|
24849
|
+
return clamped;
|
|
24762
24850
|
}
|
|
24763
24851
|
function parseCriticality(raw, reporter) {
|
|
24764
24852
|
if (typeof raw.is_critical === "boolean") return raw.is_critical;
|
|
@@ -24791,7 +24879,12 @@ function parseActivity(raw, context) {
|
|
|
24791
24879
|
context.defaultCalendarId
|
|
24792
24880
|
);
|
|
24793
24881
|
const inheritedDefaultCalendar = raw.calendarId == null || !context.knownCalendarIds.has(String(raw.calendarId));
|
|
24794
|
-
const progress = parseProgress(
|
|
24882
|
+
const progress = parseProgress(
|
|
24883
|
+
raw.progress,
|
|
24884
|
+
context.reporter,
|
|
24885
|
+
context.recordDiagnostic,
|
|
24886
|
+
String(raw.unique_id)
|
|
24887
|
+
);
|
|
24795
24888
|
const { constraintType, constraintDate } = resolveConstraint(
|
|
24796
24889
|
raw,
|
|
24797
24890
|
context.reporter,
|
|
@@ -26245,8 +26338,8 @@ var P6ActivityStatusError = class extends Error {
|
|
|
26245
26338
|
}
|
|
26246
26339
|
code;
|
|
26247
26340
|
};
|
|
26248
|
-
var
|
|
26249
|
-
var
|
|
26341
|
+
var COMPLETED_PHYSICAL_PERCENT2 = 100;
|
|
26342
|
+
var NOT_STARTED_PHYSICAL_PERCENT2 = 0;
|
|
26250
26343
|
function validateP6ActivityStatus(activity) {
|
|
26251
26344
|
validateRemainingDuration(activity.remainingDurationHours);
|
|
26252
26345
|
validateDates(activity);
|
|
@@ -26272,11 +26365,11 @@ function normalizeP6ActualDatePatch(current, patch) {
|
|
|
26272
26365
|
executionStatus,
|
|
26273
26366
|
...actualFinish !== null ? {
|
|
26274
26367
|
remainingDurationHours: 0,
|
|
26275
|
-
physicalPercentComplete:
|
|
26368
|
+
physicalPercentComplete: COMPLETED_PHYSICAL_PERCENT2
|
|
26276
26369
|
} : {},
|
|
26277
26370
|
...unStarting ? {
|
|
26278
26371
|
remainingDurationHours: current.originalDurationHours,
|
|
26279
|
-
physicalPercentComplete:
|
|
26372
|
+
physicalPercentComplete: NOT_STARTED_PHYSICAL_PERCENT2
|
|
26280
26373
|
} : {}
|
|
26281
26374
|
};
|
|
26282
26375
|
validateP6ActivityDraftStatus({ ...current, ...normalized2 });
|
|
@@ -30020,6 +30113,39 @@ function blockedActivities(code, message, activityIds, missingInputs = []) {
|
|
|
30020
30113
|
};
|
|
30021
30114
|
}
|
|
30022
30115
|
|
|
30116
|
+
// src/p6/rolled-expected-finish.ts
|
|
30117
|
+
var PINNABLE_ACTIVITY_TYPES = /* @__PURE__ */ new Set([
|
|
30118
|
+
P6_ACTIVITY_TYPE.TASK,
|
|
30119
|
+
P6_ACTIVITY_TYPE.RESOURCE_DEPENDENT
|
|
30120
|
+
]);
|
|
30121
|
+
var NO_ROLLED_EXPECTED_FINISHES = /* @__PURE__ */ new Map();
|
|
30122
|
+
function planRolledExpectedFinishes(input) {
|
|
30123
|
+
const adoptsShownFinishes = input.settings.useExpectedFinishDates && rollsDataDateForward(input.previousSettings, input.settings);
|
|
30124
|
+
if (!adoptsShownFinishes) return NO_ROLLED_EXPECTED_FINISHES;
|
|
30125
|
+
const pinned = /* @__PURE__ */ new Map();
|
|
30126
|
+
for (const [activityId, state] of input.activities) {
|
|
30127
|
+
const shownFinish = state.remainingEarlyFinish;
|
|
30128
|
+
if (shownFinish === null) continue;
|
|
30129
|
+
if (!needsExpectedFinishPin(state)) continue;
|
|
30130
|
+
pinned.set(activityId, new Date(shownFinish));
|
|
30131
|
+
}
|
|
30132
|
+
return pinned;
|
|
30133
|
+
}
|
|
30134
|
+
function rollsDataDateForward(previous, next) {
|
|
30135
|
+
const previousDataDate = previous.dataDate;
|
|
30136
|
+
const nextDataDate = next.dataDate;
|
|
30137
|
+
if (previousDataDate === null || nextDataDate === null) return false;
|
|
30138
|
+
return nextDataDate.getTime() > previousDataDate.getTime();
|
|
30139
|
+
}
|
|
30140
|
+
function needsExpectedFinishPin(state) {
|
|
30141
|
+
return state.executionStatus === P6_EXECUTION_STATUS.IN_PROGRESS && state.expectedFinish === null && hasPinnableActivityType(state);
|
|
30142
|
+
}
|
|
30143
|
+
function hasPinnableActivityType(state) {
|
|
30144
|
+
const { activityType } = state;
|
|
30145
|
+
if (activityType === void 0) return true;
|
|
30146
|
+
return PINNABLE_ACTIVITY_TYPES.has(activityType);
|
|
30147
|
+
}
|
|
30148
|
+
|
|
30023
30149
|
// src/p6/commands.ts
|
|
30024
30150
|
function dataDateScheduleReadiness(input) {
|
|
30025
30151
|
const preflight = getP6SchedulePreflight({
|
|
@@ -30133,8 +30259,17 @@ function prepareDataDateSchedule(input) {
|
|
|
30133
30259
|
preflight.settings,
|
|
30134
30260
|
beforeProjectState
|
|
30135
30261
|
);
|
|
30262
|
+
const rolledExpectedFinishes = planRolledExpectedFinishes({
|
|
30263
|
+
previousSettings: preflight.previousSettings,
|
|
30264
|
+
settings: preflight.settings,
|
|
30265
|
+
activities: preflight.activities
|
|
30266
|
+
});
|
|
30136
30267
|
const calculated = calculateP6Schedule({
|
|
30137
|
-
adapter: calculationState(
|
|
30268
|
+
adapter: calculationState(
|
|
30269
|
+
input.state,
|
|
30270
|
+
preflight.activities,
|
|
30271
|
+
rolledExpectedFinishes
|
|
30272
|
+
),
|
|
30138
30273
|
settings: preflight.settings,
|
|
30139
30274
|
project: {
|
|
30140
30275
|
projectId: String(input.sector.projectId),
|
|
@@ -30180,11 +30315,19 @@ function requireProjectState(projectState) {
|
|
|
30180
30315
|
"P6 capability is not enabled for this Schedule"
|
|
30181
30316
|
);
|
|
30182
30317
|
}
|
|
30183
|
-
function calculationState(current, schedulableActivities) {
|
|
30318
|
+
function calculationState(current, schedulableActivities, rolledExpectedFinishes) {
|
|
30184
30319
|
const state = current.fork();
|
|
30185
30320
|
state.forEachActivity((activity) => {
|
|
30186
|
-
if (schedulableActivities.has(activity.id))
|
|
30187
|
-
|
|
30321
|
+
if (!schedulableActivities.has(activity.id)) {
|
|
30322
|
+
state.setActivityField(activity.id, "p6", void 0);
|
|
30323
|
+
return;
|
|
30324
|
+
}
|
|
30325
|
+
const rolledExpectedFinish = rolledExpectedFinishes.get(activity.id);
|
|
30326
|
+
if (rolledExpectedFinish === void 0 || activity.p6 === void 0) return;
|
|
30327
|
+
state.setActivityField(activity.id, "p6", {
|
|
30328
|
+
...activity.p6,
|
|
30329
|
+
expectedFinish: rolledExpectedFinish
|
|
30330
|
+
});
|
|
30188
30331
|
});
|
|
30189
30332
|
return state;
|
|
30190
30333
|
}
|
|
@@ -30309,7 +30452,7 @@ function initializeDataDate(input, activities) {
|
|
|
30309
30452
|
function attachImportedDataDate(activities, imported, settings) {
|
|
30310
30453
|
for (const activity of activities) {
|
|
30311
30454
|
const importedP6 = Object.hasOwn(imported, activity.id) ? imported[activity.id] : void 0;
|
|
30312
|
-
const p6 = importedP6
|
|
30455
|
+
const p6 = importedP6 === void 0 ? createOutbuildP6ActivityDraft(activity) : reconcileOutbuildProgress(activity, importedP6);
|
|
30313
30456
|
if (p6 === void 0) continue;
|
|
30314
30457
|
activity.p6 = p6;
|
|
30315
30458
|
if (!hasActiveDataDate(settings)) continue;
|