@outbuild-company/schedule-core 1.35.1 → 1.35.3
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/build-fingerprint.json +2 -2
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +361 -329
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -87
- package/dist/index.d.ts +89 -87
- package/dist/index.js +361 -329
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -13002,11 +13002,6 @@ function rejectedGesture(editability) {
|
|
|
13002
13002
|
...editability.alertKey ? { alertKey: editability.alertKey } : {}
|
|
13003
13003
|
};
|
|
13004
13004
|
}
|
|
13005
|
-
var STATUS_ONLY_CHANGES = {
|
|
13006
|
-
patch: {},
|
|
13007
|
-
needsAutoSchedule: false,
|
|
13008
|
-
postProcessors: []
|
|
13009
|
-
};
|
|
13010
13005
|
function resolveDataDateProgressButton(activity, progress, progressChanges, deps, confirmations) {
|
|
13011
13006
|
const governsProgress = deps.dataDateCapability !== null && hasActiveDataDate(deps.dataDateSettings, deps.dataDateEnabled);
|
|
13012
13007
|
if (!governsProgress) return null;
|
|
@@ -13020,19 +13015,19 @@ function resolveDataDateProgressButton(activity, progress, progressChanges, deps
|
|
|
13020
13015
|
if (activity.p6 === void 0) return null;
|
|
13021
13016
|
return resolveDataDateFieldChanges(
|
|
13022
13017
|
activity,
|
|
13023
|
-
progressChanges
|
|
13018
|
+
progressChanges,
|
|
13024
13019
|
deps,
|
|
13025
13020
|
COLUMN.PROGRESS,
|
|
13026
13021
|
confirmations,
|
|
13027
13022
|
{
|
|
13028
13023
|
progress,
|
|
13029
13024
|
explicitCompletion: true,
|
|
13030
|
-
writesProgress:
|
|
13025
|
+
writesProgress: activity.p6.percentCompleteType !== P6_PERCENT_COMPLETE_TYPE.UNITS
|
|
13031
13026
|
}
|
|
13032
13027
|
);
|
|
13033
13028
|
}
|
|
13034
13029
|
function resolveDataDateFieldChanges(activity, changes, deps, column, confirmations, progressRouting, editedStart = null) {
|
|
13035
|
-
const
|
|
13030
|
+
const routed = routeGenericColumnEdit(
|
|
13036
13031
|
activity,
|
|
13037
13032
|
routeConstraintTypeEdit(activity, changes, column),
|
|
13038
13033
|
deps,
|
|
@@ -13041,9 +13036,8 @@ function resolveDataDateFieldChanges(activity, changes, deps, column, confirmati
|
|
|
13041
13036
|
progressRouting,
|
|
13042
13037
|
editedStart
|
|
13043
13038
|
);
|
|
13044
|
-
if (
|
|
13045
|
-
if ("accepted" in
|
|
13046
|
-
const routed = limitTransitionActuals(activity, generic, deps, column);
|
|
13039
|
+
if (routed === null) return rejected(REJECTION_REASON.INVALID_VALUE);
|
|
13040
|
+
if ("accepted" in routed) return routed;
|
|
13047
13041
|
if (routed.dataDatePatch === void 0) return accepted(routed);
|
|
13048
13042
|
if (activity.p6 === void 0 || deps.dataDateCapability === null) {
|
|
13049
13043
|
return rejected(REJECTION_REASON.INVALID_VALUE);
|
|
@@ -13103,32 +13097,6 @@ function withMirroredProgress(activity, changes, next, deps, column) {
|
|
|
13103
13097
|
}
|
|
13104
13098
|
return { ...changes, patch: { ...changes.patch, progress: percent } };
|
|
13105
13099
|
}
|
|
13106
|
-
var EXECUTION_TRANSITION_COLUMNS = /* @__PURE__ */ new Set([
|
|
13107
|
-
COLUMN.PROGRESS,
|
|
13108
|
-
COLUMN.EXECUTION_STATUS,
|
|
13109
|
-
COLUMN.PHYSICAL_PERCENT_COMPLETE
|
|
13110
|
-
]);
|
|
13111
|
-
function limitTransitionActuals(activity, changes, deps, column) {
|
|
13112
|
-
const dataDate = deps.dataDateSettings?.dataDate ?? null;
|
|
13113
|
-
if (!EXECUTION_TRANSITION_COLUMNS.has(column) || dataDate === null || changes.dataDatePatch === void 0 || !hasActiveDataDate(deps.dataDateSettings, deps.dataDateEnabled)) {
|
|
13114
|
-
return changes;
|
|
13115
|
-
}
|
|
13116
|
-
const calendar = deps.ctx.calendars.getCalendar(activity.calendarId);
|
|
13117
|
-
const limit = calendar === null ? { start: dataDate, finish: dataDate } : completionActualsLimit(dataDate, calendar);
|
|
13118
|
-
const recordedStart = activity.p6?.actualStart ?? null;
|
|
13119
|
-
const floor = recordedStart !== null && recordedStart <= dataDate ? recordedStart : null;
|
|
13120
|
-
const alternative = changes.confirmationAlternative;
|
|
13121
|
-
return {
|
|
13122
|
-
...changes,
|
|
13123
|
-
dataDatePatch: capActualDates(changes.dataDatePatch, floor, limit),
|
|
13124
|
-
...alternative === void 0 ? {} : {
|
|
13125
|
-
confirmationAlternative: {
|
|
13126
|
-
...alternative,
|
|
13127
|
-
effects: capActualDates(alternative.effects, floor, limit)
|
|
13128
|
-
}
|
|
13129
|
-
}
|
|
13130
|
-
};
|
|
13131
|
-
}
|
|
13132
13100
|
function accepted(changes) {
|
|
13133
13101
|
return { accepted: true, changes };
|
|
13134
13102
|
}
|
|
@@ -16117,6 +16085,315 @@ async function dispatchHistoryRevert(action, options, deps) {
|
|
|
16117
16085
|
};
|
|
16118
16086
|
}
|
|
16119
16087
|
|
|
16088
|
+
// src/p6/status.ts
|
|
16089
|
+
var INVALID_STATUS = "Invalid P6 activity status";
|
|
16090
|
+
var P6ActivityStatusError = class extends Error {
|
|
16091
|
+
constructor(code, reason) {
|
|
16092
|
+
super(`${INVALID_STATUS}: ${reason}`);
|
|
16093
|
+
this.code = code;
|
|
16094
|
+
this.name = "P6ActivityStatusError";
|
|
16095
|
+
}
|
|
16096
|
+
code;
|
|
16097
|
+
};
|
|
16098
|
+
var COMPLETED_PHYSICAL_PERCENT2 = 100;
|
|
16099
|
+
var NOT_STARTED_PHYSICAL_PERCENT2 = 0;
|
|
16100
|
+
function validateP6ActivityStatus(activity) {
|
|
16101
|
+
validateRemainingDuration(activity.remainingDurationHours);
|
|
16102
|
+
validateDates(activity);
|
|
16103
|
+
validateExecutionStatus(activity);
|
|
16104
|
+
validateDateOrder(activity);
|
|
16105
|
+
}
|
|
16106
|
+
function validateP6ActivityDraftStatus(activity) {
|
|
16107
|
+
validateDraftRemainingDuration(activity.remainingDurationHours);
|
|
16108
|
+
validateDates(activity);
|
|
16109
|
+
validateDraftExecutionStatus(activity);
|
|
16110
|
+
validateDateOrder(activity);
|
|
16111
|
+
}
|
|
16112
|
+
function normalizeP6ActualDatePatch(current, patch) {
|
|
16113
|
+
if (patch.actualStart === void 0 && patch.actualFinish === void 0) {
|
|
16114
|
+
return patch;
|
|
16115
|
+
}
|
|
16116
|
+
const actualStart = patch.actualStart !== void 0 ? patch.actualStart : current.actualStart;
|
|
16117
|
+
const actualFinish = patch.actualFinish !== void 0 ? patch.actualFinish : current.actualFinish;
|
|
16118
|
+
const executionStatus = actualFinish !== null ? "completed" : actualStart !== null ? "in_progress" : "not_started";
|
|
16119
|
+
const unStarting = actualStart === null && actualFinish === null && current.actualStart !== null;
|
|
16120
|
+
const normalized2 = {
|
|
16121
|
+
...patch,
|
|
16122
|
+
executionStatus,
|
|
16123
|
+
...actualFinish !== null ? {
|
|
16124
|
+
remainingDurationHours: 0,
|
|
16125
|
+
physicalPercentComplete: COMPLETED_PHYSICAL_PERCENT2
|
|
16126
|
+
} : {},
|
|
16127
|
+
...unStarting ? {
|
|
16128
|
+
remainingDurationHours: current.originalDurationHours,
|
|
16129
|
+
physicalPercentComplete: NOT_STARTED_PHYSICAL_PERCENT2
|
|
16130
|
+
} : {}
|
|
16131
|
+
};
|
|
16132
|
+
validateP6ActivityDraftStatus({ ...current, ...normalized2 });
|
|
16133
|
+
return normalized2;
|
|
16134
|
+
}
|
|
16135
|
+
function validateRemainingDuration(remainingDurationHours) {
|
|
16136
|
+
if (!Number.isFinite(remainingDurationHours) || remainingDurationHours < 0) {
|
|
16137
|
+
invalid2("Remaining Duration must be finite and non-negative");
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
function validateDraftRemainingDuration(remainingDurationHours) {
|
|
16141
|
+
if (remainingDurationHours === null) return;
|
|
16142
|
+
validateRemainingDuration(remainingDurationHours);
|
|
16143
|
+
}
|
|
16144
|
+
function validateDates(activity) {
|
|
16145
|
+
const dates = [
|
|
16146
|
+
activity.actualStart,
|
|
16147
|
+
activity.actualFinish,
|
|
16148
|
+
activity.suspendDate,
|
|
16149
|
+
activity.resumeDate
|
|
16150
|
+
];
|
|
16151
|
+
if (dates.some((date2) => date2 !== null && Number.isNaN(date2.getTime()))) {
|
|
16152
|
+
invalid2("actual, suspend and resume dates must be valid");
|
|
16153
|
+
}
|
|
16154
|
+
}
|
|
16155
|
+
function validateExecutionStatus(activity) {
|
|
16156
|
+
const hasActualStart = activity.actualStart !== null;
|
|
16157
|
+
const hasActualFinish = activity.actualFinish !== null;
|
|
16158
|
+
if (activity.executionStatus === "not_started") {
|
|
16159
|
+
if (hasActualStart || hasActualFinish) {
|
|
16160
|
+
invalid2("not_started cannot have actual dates");
|
|
16161
|
+
}
|
|
16162
|
+
return;
|
|
16163
|
+
}
|
|
16164
|
+
if (activity.executionStatus === "in_progress") {
|
|
16165
|
+
if (!hasActualStart || hasActualFinish) {
|
|
16166
|
+
invalid2("in_progress requires Actual Start and no Actual Finish");
|
|
16167
|
+
}
|
|
16168
|
+
return;
|
|
16169
|
+
}
|
|
16170
|
+
if (!hasActualStart || !hasActualFinish || activity.remainingDurationHours !== 0) {
|
|
16171
|
+
invalid2(
|
|
16172
|
+
"completed requires Actual Start, Actual Finish and zero Remaining Duration"
|
|
16173
|
+
);
|
|
16174
|
+
}
|
|
16175
|
+
}
|
|
16176
|
+
function validateDraftExecutionStatus(activity) {
|
|
16177
|
+
const hasActualStart = activity.actualStart !== null;
|
|
16178
|
+
const hasActualFinish = activity.actualFinish !== null;
|
|
16179
|
+
if (hasActualFinish && !hasActualStart) {
|
|
16180
|
+
invalid2("Actual Finish requires Actual Start");
|
|
16181
|
+
}
|
|
16182
|
+
if (activity.executionStatus === "not_started" && hasActualStart) {
|
|
16183
|
+
invalid2("not_started cannot have actual dates");
|
|
16184
|
+
}
|
|
16185
|
+
if (activity.executionStatus === "in_progress" && hasActualFinish) {
|
|
16186
|
+
invalid2("in_progress cannot have Actual Finish");
|
|
16187
|
+
}
|
|
16188
|
+
if (activity.executionStatus === "completed" && activity.remainingDurationHours !== null && activity.remainingDurationHours !== 0) {
|
|
16189
|
+
invalid2("completed requires zero Remaining Duration");
|
|
16190
|
+
}
|
|
16191
|
+
}
|
|
16192
|
+
function validateDateOrder(activity) {
|
|
16193
|
+
const { actualStart, actualFinish, suspendDate, resumeDate } = activity;
|
|
16194
|
+
if (actualStart !== null && actualFinish !== null && actualStart.getTime() > actualFinish.getTime()) {
|
|
16195
|
+
throw new P6ActivityStatusError(
|
|
16196
|
+
"ACTUAL_FINISH_BEFORE_START",
|
|
16197
|
+
"Actual Start must not be after Actual Finish"
|
|
16198
|
+
);
|
|
16199
|
+
}
|
|
16200
|
+
if (suspendDate !== null) {
|
|
16201
|
+
if (actualStart === null) invalid2("Suspend requires Actual Start");
|
|
16202
|
+
if (actualStart.getTime() > suspendDate.getTime()) {
|
|
16203
|
+
invalid2("Suspend must not be before Actual Start");
|
|
16204
|
+
}
|
|
16205
|
+
if (actualFinish !== null && suspendDate.getTime() > actualFinish.getTime()) {
|
|
16206
|
+
invalid2("Suspend must not be after Actual Finish");
|
|
16207
|
+
}
|
|
16208
|
+
}
|
|
16209
|
+
if (resumeDate === null) return;
|
|
16210
|
+
if (suspendDate === null) invalid2("Resume requires Suspend");
|
|
16211
|
+
if (suspendDate.getTime() > resumeDate.getTime()) {
|
|
16212
|
+
invalid2("Suspend must not be after Resume");
|
|
16213
|
+
}
|
|
16214
|
+
if (actualFinish !== null && resumeDate.getTime() > actualFinish.getTime()) {
|
|
16215
|
+
invalid2("Resume must not be after Actual Finish");
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
function invalid2(reason) {
|
|
16219
|
+
throw new Error(`${INVALID_STATUS}: ${reason}`);
|
|
16220
|
+
}
|
|
16221
|
+
|
|
16222
|
+
// src/p6/lookahead-progress-transition.ts
|
|
16223
|
+
var LookaheadActualTransitionError = class extends Error {
|
|
16224
|
+
constructor(code) {
|
|
16225
|
+
super(code);
|
|
16226
|
+
this.code = code;
|
|
16227
|
+
this.name = "LookaheadActualTransitionError";
|
|
16228
|
+
}
|
|
16229
|
+
code;
|
|
16230
|
+
};
|
|
16231
|
+
var ACTUAL_DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
16232
|
+
function resolveLookaheadActualDateSelection(input) {
|
|
16233
|
+
if (!validDate(input.timeSource)) invalid3("INVALID_ACTUAL_TIME_SOURCE");
|
|
16234
|
+
const parts = actualDayParts(input.selectedDay);
|
|
16235
|
+
const [year, month, day] = parts;
|
|
16236
|
+
const result = new Date(input.timeSource);
|
|
16237
|
+
result.setUTCFullYear(year, month - 1, day);
|
|
16238
|
+
if (!sameUtcDay2(result, parts)) invalid3("INVALID_ACTUAL_DAY");
|
|
16239
|
+
return result;
|
|
16240
|
+
}
|
|
16241
|
+
function actualDayParts(value) {
|
|
16242
|
+
const match = ACTUAL_DAY_PATTERN.exec(value);
|
|
16243
|
+
if (!match) invalid3("INVALID_ACTUAL_DAY");
|
|
16244
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
16245
|
+
}
|
|
16246
|
+
function planLookaheadProgressActuals(input) {
|
|
16247
|
+
validateInput(input);
|
|
16248
|
+
if (input.dataDate === null) {
|
|
16249
|
+
return { start: null, finish: null, uncomplete: null };
|
|
16250
|
+
}
|
|
16251
|
+
const start = input.activity.executionStatus === P6_EXECUTION_STATUS.NOT_STARTED && input.nextProgress > NOT_STARTED_PROGRESS ? { required: true, suggestedAt: new Date(input.dataDate) } : null;
|
|
16252
|
+
const finish = input.activity.executionStatus !== P6_EXECUTION_STATUS.COMPLETED && input.nextProgress === COMPLETED_PROGRESS ? {
|
|
16253
|
+
optional: true,
|
|
16254
|
+
suggestedAt: input.displayedFinish ? new Date(input.displayedFinish) : null
|
|
16255
|
+
} : null;
|
|
16256
|
+
const uncomplete = input.activity.executionStatus === P6_EXECUTION_STATUS.COMPLETED && input.activity.actualFinish !== null && input.nextProgress < COMPLETED_PROGRESS ? {
|
|
16257
|
+
required: true,
|
|
16258
|
+
removes: new Date(input.activity.actualFinish)
|
|
16259
|
+
} : null;
|
|
16260
|
+
return { start, finish, uncomplete };
|
|
16261
|
+
}
|
|
16262
|
+
function prepareLookaheadProgressActuals(input) {
|
|
16263
|
+
const plan = planLookaheadProgressActuals(input);
|
|
16264
|
+
if (input.dataDate === null && hasIntent(input.intent)) {
|
|
16265
|
+
invalid3("DATA_DATE_INACTIVE");
|
|
16266
|
+
}
|
|
16267
|
+
if (plan.start && input.intent?.actualStart === void 0) {
|
|
16268
|
+
invalid3("ACTUAL_START_REQUIRED");
|
|
16269
|
+
}
|
|
16270
|
+
if (input.intent?.actualFinish instanceof Date && input.nextProgress !== COMPLETED_PROGRESS) {
|
|
16271
|
+
invalid3("ACTUAL_FINISH_REQUIRES_100");
|
|
16272
|
+
}
|
|
16273
|
+
if (plan.uncomplete && input.intent?.actualFinish !== null) {
|
|
16274
|
+
invalid3("ACTUAL_FINISH_REMOVAL_REQUIRED");
|
|
16275
|
+
}
|
|
16276
|
+
if (!plan.uncomplete && input.intent?.actualFinish === null) {
|
|
16277
|
+
invalid3("ACTUAL_FINISH_REMOVAL_NOT_APPLICABLE");
|
|
16278
|
+
}
|
|
16279
|
+
const actuals = normalizeP6ActualDatePatch(
|
|
16280
|
+
input.activity,
|
|
16281
|
+
input.intent ?? {}
|
|
16282
|
+
);
|
|
16283
|
+
if (input.dataDate === null) return actuals;
|
|
16284
|
+
return withMirroredPercent(input.activity, actuals, input.nextProgress);
|
|
16285
|
+
}
|
|
16286
|
+
function prepareLookaheadProgressActualsForPersistence(input) {
|
|
16287
|
+
const { resolveCalendar, ...progressInput } = input;
|
|
16288
|
+
const preparedActuals = prepareLookaheadProgressActuals(progressInput);
|
|
16289
|
+
if (input.dataDate === null) {
|
|
16290
|
+
return preparedActuals;
|
|
16291
|
+
}
|
|
16292
|
+
const actualStart = input.intent?.actualStart;
|
|
16293
|
+
const needsActualStartNormalization = actualStart !== void 0 && isUtcMidnight(actualStart);
|
|
16294
|
+
if (!needsActualStartNormalization) return preparedActuals;
|
|
16295
|
+
const intent = normalizeActualStart(
|
|
16296
|
+
input.intent,
|
|
16297
|
+
input.activity.actualStart,
|
|
16298
|
+
resolveCalendar
|
|
16299
|
+
);
|
|
16300
|
+
if (intent === void 0) {
|
|
16301
|
+
return preparedActuals;
|
|
16302
|
+
}
|
|
16303
|
+
return prepareLookaheadProgressActuals({ ...progressInput, intent });
|
|
16304
|
+
}
|
|
16305
|
+
function normalizeActualStart(intent, existingActualStart, resolveCalendar) {
|
|
16306
|
+
if (intent?.actualStart === void 0) return intent;
|
|
16307
|
+
if (!isUtcMidnight(intent.actualStart)) return intent;
|
|
16308
|
+
if (existingActualStart !== null) {
|
|
16309
|
+
return {
|
|
16310
|
+
...intent,
|
|
16311
|
+
actualStart: resolveLookaheadActualDateSelection({
|
|
16312
|
+
selectedDay: intent.actualStart.toISOString().slice(0, 10),
|
|
16313
|
+
timeSource: existingActualStart
|
|
16314
|
+
})
|
|
16315
|
+
};
|
|
16316
|
+
}
|
|
16317
|
+
const calendar = resolveCalendar();
|
|
16318
|
+
if (calendar === null) {
|
|
16319
|
+
invalid3("ACTIVITY_CALENDAR_REQUIRED");
|
|
16320
|
+
}
|
|
16321
|
+
return {
|
|
16322
|
+
...intent,
|
|
16323
|
+
actualStart: defaultActualStartTime(intent.actualStart, calendar)
|
|
16324
|
+
};
|
|
16325
|
+
}
|
|
16326
|
+
function withMirroredPercent(activity, actuals, nextProgress) {
|
|
16327
|
+
const executionStatus = actuals.executionStatus ?? activity.executionStatus;
|
|
16328
|
+
if (executionStatus !== P6_EXECUTION_STATUS.IN_PROGRESS) return actuals;
|
|
16329
|
+
switch (activity.percentCompleteType) {
|
|
16330
|
+
case P6_PERCENT_COMPLETE_TYPE.PHYSICAL:
|
|
16331
|
+
return { ...actuals, physicalPercentComplete: nextProgress };
|
|
16332
|
+
case P6_PERCENT_COMPLETE_TYPE.DURATION:
|
|
16333
|
+
return {
|
|
16334
|
+
...actuals,
|
|
16335
|
+
remainingDurationHours: activity.originalDurationHours * (1 - nextProgress / COMPLETED_PROGRESS)
|
|
16336
|
+
};
|
|
16337
|
+
default:
|
|
16338
|
+
return actuals;
|
|
16339
|
+
}
|
|
16340
|
+
}
|
|
16341
|
+
function validateInput(input) {
|
|
16342
|
+
if (!Number.isFinite(input.nextProgress) || input.nextProgress < NOT_STARTED_PROGRESS || input.nextProgress > COMPLETED_PROGRESS) {
|
|
16343
|
+
invalid3("INVALID_PROGRESS");
|
|
16344
|
+
}
|
|
16345
|
+
if (input.dataDate !== null && !validDate(input.dataDate)) {
|
|
16346
|
+
invalid3("INVALID_DATA_DATE");
|
|
16347
|
+
}
|
|
16348
|
+
if (input.displayedFinish != null && !validDate(input.displayedFinish)) {
|
|
16349
|
+
invalid3("INVALID_DISPLAYED_FINISH");
|
|
16350
|
+
}
|
|
16351
|
+
}
|
|
16352
|
+
function validDate(value) {
|
|
16353
|
+
return value instanceof Date && Number.isFinite(value.getTime());
|
|
16354
|
+
}
|
|
16355
|
+
function sameUtcDay2(value, [year, month, day]) {
|
|
16356
|
+
return value.getUTCFullYear() === year && value.getUTCMonth() === month - 1 && value.getUTCDate() === day;
|
|
16357
|
+
}
|
|
16358
|
+
function hasIntent(intent) {
|
|
16359
|
+
return intent?.actualStart !== void 0 || intent?.actualFinish !== void 0;
|
|
16360
|
+
}
|
|
16361
|
+
function invalid3(code) {
|
|
16362
|
+
throw new LookaheadActualTransitionError(code);
|
|
16363
|
+
}
|
|
16364
|
+
|
|
16365
|
+
// src/p6/lookahead-reconciliation.ts
|
|
16366
|
+
function preparePersistedLookaheadDataDate(action, activity, deps) {
|
|
16367
|
+
const settings = deps.dataDateSettings;
|
|
16368
|
+
const capability = deps.dataDateCapability;
|
|
16369
|
+
if (action.persistedProgress === void 0 || activity?.p6 === void 0 || capability === null || !hasActiveDataDate(settings, deps.dataDateEnabled) || settings?.dataDate == null)
|
|
16370
|
+
return null;
|
|
16371
|
+
const patch = prepareLookaheadProgressActuals({
|
|
16372
|
+
dataDate: settings.dataDate,
|
|
16373
|
+
activity: activity.p6,
|
|
16374
|
+
nextProgress: action.persistedProgress,
|
|
16375
|
+
...action.persistedActualTransition === void 0 ? {} : { intent: action.persistedActualTransition }
|
|
16376
|
+
});
|
|
16377
|
+
const prepared = capability.prepareActivityUpdate(
|
|
16378
|
+
activity.p6,
|
|
16379
|
+
{
|
|
16380
|
+
originalDurationHours: activity.p6.originalDurationHours,
|
|
16381
|
+
...patch.actualStart === void 0 ? {} : { actualStart: patch.actualStart },
|
|
16382
|
+
...patch.actualFinish === void 0 ? {} : { actualFinish: patch.actualFinish },
|
|
16383
|
+
...patch.remainingDurationHours == null ? {} : { remainingDurationHours: patch.remainingDurationHours },
|
|
16384
|
+
...patch.physicalPercentComplete == null ? {} : { physicalPercentComplete: patch.physicalPercentComplete }
|
|
16385
|
+
},
|
|
16386
|
+
activity.constraintType
|
|
16387
|
+
);
|
|
16388
|
+
const calendar = deps.adapter.calendarReader.getCalendar(activity.calendarId);
|
|
16389
|
+
const projection = calendar === null ? { p6: prepared.next, startDate: void 0, endDate: void 0 } : capability.projectLocalActivity(activity.p6, prepared.next, {
|
|
16390
|
+
calendar,
|
|
16391
|
+
dataDate: settings.dataDate,
|
|
16392
|
+
totalFloatMethod: settings.totalFloatMethod
|
|
16393
|
+
});
|
|
16394
|
+
return { activityId: activity.id, ...projection };
|
|
16395
|
+
}
|
|
16396
|
+
|
|
16120
16397
|
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
16121
16398
|
var EMPTY_OWNERS = /* @__PURE__ */ new Map();
|
|
16122
16399
|
function persistedOwnersOf(entities) {
|
|
@@ -16335,6 +16612,30 @@ async function dispatchActivityLookaheadSync(action, options, deps) {
|
|
|
16335
16612
|
if (snapshots.some((snapshot) => !snapshot)) {
|
|
16336
16613
|
return { ok: false, reason: REJECTION_REASON.ACTIVITY_NOT_FOUND };
|
|
16337
16614
|
}
|
|
16615
|
+
const persistedDataDate = preparePersistedLookaheadDataDate(
|
|
16616
|
+
action,
|
|
16617
|
+
snapshots[0],
|
|
16618
|
+
deps
|
|
16619
|
+
);
|
|
16620
|
+
if (persistedDataDate !== null) {
|
|
16621
|
+
deps.adapter.setActivityField(
|
|
16622
|
+
persistedDataDate.activityId,
|
|
16623
|
+
"p6",
|
|
16624
|
+
persistedDataDate.p6
|
|
16625
|
+
);
|
|
16626
|
+
if (persistedDataDate.startDate !== void 0)
|
|
16627
|
+
deps.adapter.setActivityField(
|
|
16628
|
+
persistedDataDate.activityId,
|
|
16629
|
+
"startDate",
|
|
16630
|
+
persistedDataDate.startDate
|
|
16631
|
+
);
|
|
16632
|
+
if (persistedDataDate.endDate !== void 0)
|
|
16633
|
+
deps.adapter.setActivityField(
|
|
16634
|
+
persistedDataDate.activityId,
|
|
16635
|
+
"endDate",
|
|
16636
|
+
persistedDataDate.endDate
|
|
16637
|
+
);
|
|
16638
|
+
}
|
|
16338
16639
|
const activities = [];
|
|
16339
16640
|
for (const [index, id] of ids.entries()) {
|
|
16340
16641
|
const snapshot = snapshots[index];
|
|
@@ -16375,7 +16676,7 @@ async function dispatchActivityLookaheadSync(action, options, deps) {
|
|
|
16375
16676
|
[{ activityId: ids[0], progress: action.persistedProgress }],
|
|
16376
16677
|
deps
|
|
16377
16678
|
);
|
|
16378
|
-
if (progressChanges.length > 0) {
|
|
16679
|
+
if (progressChanges.length > 0 || persistedDataDate !== null) {
|
|
16379
16680
|
await runPostMutation(
|
|
16380
16681
|
{
|
|
16381
16682
|
adapter: deps.adapter,
|
|
@@ -17617,7 +17918,7 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
17617
17918
|
const statusRouting = resolveDataDateProgressButton(
|
|
17618
17919
|
activitySnap,
|
|
17619
17920
|
action.newValue,
|
|
17620
|
-
|
|
17921
|
+
progressChanges,
|
|
17621
17922
|
deps,
|
|
17622
17923
|
options.confirmations
|
|
17623
17924
|
);
|
|
@@ -17625,17 +17926,14 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
17625
17926
|
return rejectedRouting(statusRouting);
|
|
17626
17927
|
}
|
|
17627
17928
|
const changes = statusRouting === null ? progressChanges : statusRouting.changes;
|
|
17628
|
-
const writesProgress = statusRouting === null || editGate.allowed;
|
|
17629
17929
|
const touchedIds = collectTouchedIds(action.activityId, changes);
|
|
17630
|
-
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
17631
|
-
applyFieldChanges(adapter, action.activityId, changes);
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
);
|
|
17638
|
-
}
|
|
17930
|
+
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
17931
|
+
applyFieldChanges(adapter, action.activityId, changes);
|
|
17932
|
+
setExplicitSummaryProgressFallbacks(
|
|
17933
|
+
action.activityId,
|
|
17934
|
+
action.newValue,
|
|
17935
|
+
adapter
|
|
17936
|
+
);
|
|
17639
17937
|
runPostProcessorsOnAdapter(
|
|
17640
17938
|
action.activityId,
|
|
17641
17939
|
changes.postProcessors ?? [],
|
|
@@ -26797,140 +27095,6 @@ function changed(before, after) {
|
|
|
26797
27095
|
return serializeCanonicalSchedule(before) !== serializeCanonicalSchedule(after);
|
|
26798
27096
|
}
|
|
26799
27097
|
|
|
26800
|
-
// src/p6/status.ts
|
|
26801
|
-
var INVALID_STATUS = "Invalid P6 activity status";
|
|
26802
|
-
var P6ActivityStatusError = class extends Error {
|
|
26803
|
-
constructor(code, reason) {
|
|
26804
|
-
super(`${INVALID_STATUS}: ${reason}`);
|
|
26805
|
-
this.code = code;
|
|
26806
|
-
this.name = "P6ActivityStatusError";
|
|
26807
|
-
}
|
|
26808
|
-
code;
|
|
26809
|
-
};
|
|
26810
|
-
var COMPLETED_PHYSICAL_PERCENT2 = 100;
|
|
26811
|
-
var NOT_STARTED_PHYSICAL_PERCENT2 = 0;
|
|
26812
|
-
function validateP6ActivityStatus(activity) {
|
|
26813
|
-
validateRemainingDuration(activity.remainingDurationHours);
|
|
26814
|
-
validateDates(activity);
|
|
26815
|
-
validateExecutionStatus(activity);
|
|
26816
|
-
validateDateOrder(activity);
|
|
26817
|
-
}
|
|
26818
|
-
function validateP6ActivityDraftStatus(activity) {
|
|
26819
|
-
validateDraftRemainingDuration(activity.remainingDurationHours);
|
|
26820
|
-
validateDates(activity);
|
|
26821
|
-
validateDraftExecutionStatus(activity);
|
|
26822
|
-
validateDateOrder(activity);
|
|
26823
|
-
}
|
|
26824
|
-
function normalizeP6ActualDatePatch(current, patch) {
|
|
26825
|
-
if (patch.actualStart === void 0 && patch.actualFinish === void 0) {
|
|
26826
|
-
return patch;
|
|
26827
|
-
}
|
|
26828
|
-
const actualStart = patch.actualStart !== void 0 ? patch.actualStart : current.actualStart;
|
|
26829
|
-
const actualFinish = patch.actualFinish !== void 0 ? patch.actualFinish : current.actualFinish;
|
|
26830
|
-
const executionStatus = actualFinish !== null ? "completed" : actualStart !== null ? "in_progress" : "not_started";
|
|
26831
|
-
const unStarting = actualStart === null && actualFinish === null && current.actualStart !== null;
|
|
26832
|
-
const normalized2 = {
|
|
26833
|
-
...patch,
|
|
26834
|
-
executionStatus,
|
|
26835
|
-
...actualFinish !== null ? {
|
|
26836
|
-
remainingDurationHours: 0,
|
|
26837
|
-
physicalPercentComplete: COMPLETED_PHYSICAL_PERCENT2
|
|
26838
|
-
} : {},
|
|
26839
|
-
...unStarting ? {
|
|
26840
|
-
remainingDurationHours: current.originalDurationHours,
|
|
26841
|
-
physicalPercentComplete: NOT_STARTED_PHYSICAL_PERCENT2
|
|
26842
|
-
} : {}
|
|
26843
|
-
};
|
|
26844
|
-
validateP6ActivityDraftStatus({ ...current, ...normalized2 });
|
|
26845
|
-
return normalized2;
|
|
26846
|
-
}
|
|
26847
|
-
function validateRemainingDuration(remainingDurationHours) {
|
|
26848
|
-
if (!Number.isFinite(remainingDurationHours) || remainingDurationHours < 0) {
|
|
26849
|
-
invalid2("Remaining Duration must be finite and non-negative");
|
|
26850
|
-
}
|
|
26851
|
-
}
|
|
26852
|
-
function validateDraftRemainingDuration(remainingDurationHours) {
|
|
26853
|
-
if (remainingDurationHours === null) return;
|
|
26854
|
-
validateRemainingDuration(remainingDurationHours);
|
|
26855
|
-
}
|
|
26856
|
-
function validateDates(activity) {
|
|
26857
|
-
const dates = [
|
|
26858
|
-
activity.actualStart,
|
|
26859
|
-
activity.actualFinish,
|
|
26860
|
-
activity.suspendDate,
|
|
26861
|
-
activity.resumeDate
|
|
26862
|
-
];
|
|
26863
|
-
if (dates.some((date2) => date2 !== null && Number.isNaN(date2.getTime()))) {
|
|
26864
|
-
invalid2("actual, suspend and resume dates must be valid");
|
|
26865
|
-
}
|
|
26866
|
-
}
|
|
26867
|
-
function validateExecutionStatus(activity) {
|
|
26868
|
-
const hasActualStart = activity.actualStart !== null;
|
|
26869
|
-
const hasActualFinish = activity.actualFinish !== null;
|
|
26870
|
-
if (activity.executionStatus === "not_started") {
|
|
26871
|
-
if (hasActualStart || hasActualFinish) {
|
|
26872
|
-
invalid2("not_started cannot have actual dates");
|
|
26873
|
-
}
|
|
26874
|
-
return;
|
|
26875
|
-
}
|
|
26876
|
-
if (activity.executionStatus === "in_progress") {
|
|
26877
|
-
if (!hasActualStart || hasActualFinish) {
|
|
26878
|
-
invalid2("in_progress requires Actual Start and no Actual Finish");
|
|
26879
|
-
}
|
|
26880
|
-
return;
|
|
26881
|
-
}
|
|
26882
|
-
if (!hasActualStart || !hasActualFinish || activity.remainingDurationHours !== 0) {
|
|
26883
|
-
invalid2(
|
|
26884
|
-
"completed requires Actual Start, Actual Finish and zero Remaining Duration"
|
|
26885
|
-
);
|
|
26886
|
-
}
|
|
26887
|
-
}
|
|
26888
|
-
function validateDraftExecutionStatus(activity) {
|
|
26889
|
-
const hasActualStart = activity.actualStart !== null;
|
|
26890
|
-
const hasActualFinish = activity.actualFinish !== null;
|
|
26891
|
-
if (hasActualFinish && !hasActualStart) {
|
|
26892
|
-
invalid2("Actual Finish requires Actual Start");
|
|
26893
|
-
}
|
|
26894
|
-
if (activity.executionStatus === "not_started" && hasActualStart) {
|
|
26895
|
-
invalid2("not_started cannot have actual dates");
|
|
26896
|
-
}
|
|
26897
|
-
if (activity.executionStatus === "in_progress" && hasActualFinish) {
|
|
26898
|
-
invalid2("in_progress cannot have Actual Finish");
|
|
26899
|
-
}
|
|
26900
|
-
if (activity.executionStatus === "completed" && activity.remainingDurationHours !== null && activity.remainingDurationHours !== 0) {
|
|
26901
|
-
invalid2("completed requires zero Remaining Duration");
|
|
26902
|
-
}
|
|
26903
|
-
}
|
|
26904
|
-
function validateDateOrder(activity) {
|
|
26905
|
-
const { actualStart, actualFinish, suspendDate, resumeDate } = activity;
|
|
26906
|
-
if (actualStart !== null && actualFinish !== null && actualStart.getTime() > actualFinish.getTime()) {
|
|
26907
|
-
throw new P6ActivityStatusError(
|
|
26908
|
-
"ACTUAL_FINISH_BEFORE_START",
|
|
26909
|
-
"Actual Start must not be after Actual Finish"
|
|
26910
|
-
);
|
|
26911
|
-
}
|
|
26912
|
-
if (suspendDate !== null) {
|
|
26913
|
-
if (actualStart === null) invalid2("Suspend requires Actual Start");
|
|
26914
|
-
if (actualStart.getTime() > suspendDate.getTime()) {
|
|
26915
|
-
invalid2("Suspend must not be before Actual Start");
|
|
26916
|
-
}
|
|
26917
|
-
if (actualFinish !== null && suspendDate.getTime() > actualFinish.getTime()) {
|
|
26918
|
-
invalid2("Suspend must not be after Actual Finish");
|
|
26919
|
-
}
|
|
26920
|
-
}
|
|
26921
|
-
if (resumeDate === null) return;
|
|
26922
|
-
if (suspendDate === null) invalid2("Resume requires Suspend");
|
|
26923
|
-
if (suspendDate.getTime() > resumeDate.getTime()) {
|
|
26924
|
-
invalid2("Suspend must not be after Resume");
|
|
26925
|
-
}
|
|
26926
|
-
if (actualFinish !== null && resumeDate.getTime() > actualFinish.getTime()) {
|
|
26927
|
-
invalid2("Resume must not be after Actual Finish");
|
|
26928
|
-
}
|
|
26929
|
-
}
|
|
26930
|
-
function invalid2(reason) {
|
|
26931
|
-
throw new Error(`${INVALID_STATUS}: ${reason}`);
|
|
26932
|
-
}
|
|
26933
|
-
|
|
26934
27098
|
// src/p6/derived.ts
|
|
26935
27099
|
var INVALID_INPUT = "Invalid P6 derived input";
|
|
26936
27100
|
var PERCENT_SCALE2 = 100;
|
|
@@ -30899,48 +31063,48 @@ function optionalP6Date(rawValue) {
|
|
|
30899
31063
|
function yesNo(rawValue) {
|
|
30900
31064
|
if (rawValue === "Y") return true;
|
|
30901
31065
|
if (rawValue === "N") return false;
|
|
30902
|
-
|
|
31066
|
+
invalid4(`expected Y/N, got "${rawValue}"`);
|
|
30903
31067
|
}
|
|
30904
31068
|
function enumValue(map, rawValue) {
|
|
30905
|
-
if (!Object.hasOwn(map, rawValue))
|
|
31069
|
+
if (!Object.hasOwn(map, rawValue)) invalid4(`unknown enum "${rawValue}"`);
|
|
30906
31070
|
return map[rawValue];
|
|
30907
31071
|
}
|
|
30908
31072
|
function outOfSequencePolicy(schedule) {
|
|
30909
31073
|
const retained = yesNo(schedule.sched_retained_logic);
|
|
30910
31074
|
const override = yesNo(schedule.sched_progress_override);
|
|
30911
31075
|
if (retained && override)
|
|
30912
|
-
|
|
31076
|
+
invalid4("retained logic and progress override conflict");
|
|
30913
31077
|
if (retained) return "retained_logic";
|
|
30914
31078
|
if (override) return "progress_override";
|
|
30915
31079
|
return "actual_dates";
|
|
30916
31080
|
}
|
|
30917
31081
|
function nonNegativeNumber(rawValue, field) {
|
|
30918
31082
|
const value = finiteNumber(rawValue, field);
|
|
30919
|
-
if (value < 0)
|
|
31083
|
+
if (value < 0) invalid4(`${field} must be a non-negative number`);
|
|
30920
31084
|
return value;
|
|
30921
31085
|
}
|
|
30922
31086
|
function finiteNumber(rawValue, field) {
|
|
30923
31087
|
const value = Number(rawValue);
|
|
30924
31088
|
if (rawValue === "" || !Number.isFinite(value)) {
|
|
30925
|
-
|
|
31089
|
+
invalid4(`${field} must be a finite number`);
|
|
30926
31090
|
}
|
|
30927
31091
|
return value;
|
|
30928
31092
|
}
|
|
30929
31093
|
function nonNegativeInteger(rawValue, field) {
|
|
30930
31094
|
const value = nonNegativeNumber(rawValue, field);
|
|
30931
|
-
if (!Number.isInteger(value))
|
|
31095
|
+
if (!Number.isInteger(value)) invalid4(`${field} must be an integer`);
|
|
30932
31096
|
return value;
|
|
30933
31097
|
}
|
|
30934
31098
|
function endingActivityId(rawValue, resolveActivityId) {
|
|
30935
31099
|
if (rawValue === "") return null;
|
|
30936
31100
|
if (resolveActivityId === void 0) {
|
|
30937
|
-
|
|
31101
|
+
invalid4("ending activity requires an ID resolver");
|
|
30938
31102
|
}
|
|
30939
31103
|
const resolved = resolveActivityId(rawValue);
|
|
30940
|
-
if (resolved === null)
|
|
31104
|
+
if (resolved === null) invalid4(`unknown ending activity "${rawValue}"`);
|
|
30941
31105
|
return resolved;
|
|
30942
31106
|
}
|
|
30943
|
-
function
|
|
31107
|
+
function invalid4(reason) {
|
|
30944
31108
|
throw new Error(`${INVALID_OPTIONS}: ${reason}`);
|
|
30945
31109
|
}
|
|
30946
31110
|
|
|
@@ -30971,13 +31135,11 @@ function prepareDataDateSettingsUpdate(current, patch) {
|
|
|
30971
31135
|
};
|
|
30972
31136
|
}
|
|
30973
31137
|
function prepareDataDateActivityUpdate(current, patch, primaryConstraint) {
|
|
30974
|
-
const
|
|
31138
|
+
const synchronized = synchronizeNotStartedDurations(current, patch);
|
|
31139
|
+
const percentRouted = routeActivityPercentComplete(current, synchronized);
|
|
30975
31140
|
validateActivityInputPatch(percentRouted);
|
|
30976
31141
|
validateSecondaryConstraint(percentRouted, primaryConstraint);
|
|
30977
|
-
const routed =
|
|
30978
|
-
current,
|
|
30979
|
-
gatePhysicalPercentInput(current, percentRouted)
|
|
30980
|
-
);
|
|
31142
|
+
const routed = gatePhysicalPercentInput(current, percentRouted);
|
|
30981
31143
|
const next = cloneDomainValue({
|
|
30982
31144
|
...current,
|
|
30983
31145
|
...routed,
|
|
@@ -30990,7 +31152,7 @@ function prepareDataDateActivityUpdate(current, patch, primaryConstraint) {
|
|
|
30990
31152
|
};
|
|
30991
31153
|
}
|
|
30992
31154
|
function synchronizeNotStartedDurations(current, patch) {
|
|
30993
|
-
if (current.executionStatus !== P6_EXECUTION_STATUS.NOT_STARTED || patch.remainingDurationHours === void 0 || patch.originalDurationHours !== void 0) {
|
|
31155
|
+
if (current.executionStatus !== P6_EXECUTION_STATUS.NOT_STARTED || patch.actualStart != null || patch.activityPercentComplete !== void 0 || patch.remainingDurationHours === void 0 || patch.originalDurationHours !== void 0) {
|
|
30994
31156
|
return patch;
|
|
30995
31157
|
}
|
|
30996
31158
|
return {
|
|
@@ -31035,7 +31197,7 @@ function routeActivityPercentComplete(current, patch) {
|
|
|
31035
31197
|
case P6_PERCENT_COMPLETE_TYPE.DURATION:
|
|
31036
31198
|
return {
|
|
31037
31199
|
...rest,
|
|
31038
|
-
remainingDurationHours: current.originalDurationHours * (1 - activityPercentComplete / FULL_PERCENT)
|
|
31200
|
+
remainingDurationHours: (rest.originalDurationHours ?? current.originalDurationHours) * (1 - activityPercentComplete / FULL_PERCENT)
|
|
31039
31201
|
};
|
|
31040
31202
|
case P6_PERCENT_COMPLETE_TYPE.UNITS:
|
|
31041
31203
|
throw new Error(
|
|
@@ -37210,136 +37372,6 @@ function serializeP6State(input) {
|
|
|
37210
37372
|
// src/boundary/save/unsaved.ts
|
|
37211
37373
|
var getUnsavedActivities = (activities = []) => (activities ?? []).filter((activity) => !activity.proplannerId);
|
|
37212
37374
|
|
|
37213
|
-
// src/p6/lookahead-progress-transition.ts
|
|
37214
|
-
var LookaheadActualTransitionError = class extends Error {
|
|
37215
|
-
constructor(code) {
|
|
37216
|
-
super(code);
|
|
37217
|
-
this.code = code;
|
|
37218
|
-
this.name = "LookaheadActualTransitionError";
|
|
37219
|
-
}
|
|
37220
|
-
code;
|
|
37221
|
-
};
|
|
37222
|
-
var ACTUAL_DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
37223
|
-
function resolveLookaheadActualDateSelection(input) {
|
|
37224
|
-
if (!validDate(input.timeSource)) invalid4("INVALID_ACTUAL_TIME_SOURCE");
|
|
37225
|
-
const parts = actualDayParts(input.selectedDay);
|
|
37226
|
-
const [year, month, day] = parts;
|
|
37227
|
-
const result = new Date(input.timeSource);
|
|
37228
|
-
result.setUTCFullYear(year, month - 1, day);
|
|
37229
|
-
if (!sameUtcDay2(result, parts)) invalid4("INVALID_ACTUAL_DAY");
|
|
37230
|
-
return result;
|
|
37231
|
-
}
|
|
37232
|
-
function actualDayParts(value) {
|
|
37233
|
-
const match = ACTUAL_DAY_PATTERN.exec(value);
|
|
37234
|
-
if (!match) invalid4("INVALID_ACTUAL_DAY");
|
|
37235
|
-
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
37236
|
-
}
|
|
37237
|
-
function planLookaheadProgressActuals(input) {
|
|
37238
|
-
validateInput(input);
|
|
37239
|
-
if (input.dataDate === null) {
|
|
37240
|
-
return { start: null, finish: null, uncomplete: null };
|
|
37241
|
-
}
|
|
37242
|
-
const start = input.activity.executionStatus === P6_EXECUTION_STATUS.NOT_STARTED && input.nextProgress > NOT_STARTED_PROGRESS ? { required: true, suggestedAt: new Date(input.dataDate) } : null;
|
|
37243
|
-
const finish = input.activity.executionStatus !== P6_EXECUTION_STATUS.COMPLETED && input.nextProgress === COMPLETED_PROGRESS ? {
|
|
37244
|
-
optional: true,
|
|
37245
|
-
suggestedAt: input.displayedFinish ? new Date(input.displayedFinish) : null
|
|
37246
|
-
} : null;
|
|
37247
|
-
const uncomplete = input.activity.executionStatus === P6_EXECUTION_STATUS.COMPLETED && input.activity.actualFinish !== null && input.nextProgress < COMPLETED_PROGRESS ? {
|
|
37248
|
-
required: true,
|
|
37249
|
-
removes: new Date(input.activity.actualFinish)
|
|
37250
|
-
} : null;
|
|
37251
|
-
return { start, finish, uncomplete };
|
|
37252
|
-
}
|
|
37253
|
-
function prepareLookaheadProgressActuals(input) {
|
|
37254
|
-
const plan = planLookaheadProgressActuals(input);
|
|
37255
|
-
if (input.dataDate === null && hasIntent(input.intent)) {
|
|
37256
|
-
invalid4("DATA_DATE_INACTIVE");
|
|
37257
|
-
}
|
|
37258
|
-
if (plan.start && input.intent?.actualStart === void 0) {
|
|
37259
|
-
invalid4("ACTUAL_START_REQUIRED");
|
|
37260
|
-
}
|
|
37261
|
-
if (input.intent?.actualFinish instanceof Date && input.nextProgress !== COMPLETED_PROGRESS) {
|
|
37262
|
-
invalid4("ACTUAL_FINISH_REQUIRES_100");
|
|
37263
|
-
}
|
|
37264
|
-
if (plan.uncomplete && input.intent?.actualFinish !== null) {
|
|
37265
|
-
invalid4("ACTUAL_FINISH_REMOVAL_REQUIRED");
|
|
37266
|
-
}
|
|
37267
|
-
if (!plan.uncomplete && input.intent?.actualFinish === null) {
|
|
37268
|
-
invalid4("ACTUAL_FINISH_REMOVAL_NOT_APPLICABLE");
|
|
37269
|
-
}
|
|
37270
|
-
const actuals = normalizeP6ActualDatePatch(
|
|
37271
|
-
input.activity,
|
|
37272
|
-
input.intent ?? {}
|
|
37273
|
-
);
|
|
37274
|
-
if (input.dataDate === null) return actuals;
|
|
37275
|
-
return withMirroredPercent(input.activity, actuals, input.nextProgress);
|
|
37276
|
-
}
|
|
37277
|
-
function prepareLookaheadProgressActualsForPersistence(input) {
|
|
37278
|
-
const { resolveCalendar, ...progressInput } = input;
|
|
37279
|
-
const preparedActuals = prepareLookaheadProgressActuals(progressInput);
|
|
37280
|
-
if (input.dataDate === null) {
|
|
37281
|
-
return preparedActuals;
|
|
37282
|
-
}
|
|
37283
|
-
const actualStart = input.intent?.actualStart;
|
|
37284
|
-
const needsActualStartNormalization = actualStart !== void 0 && isUtcMidnight(actualStart);
|
|
37285
|
-
if (!needsActualStartNormalization) return preparedActuals;
|
|
37286
|
-
const intent = normalizeActualStart(input.intent, resolveCalendar);
|
|
37287
|
-
if (intent === void 0) {
|
|
37288
|
-
return preparedActuals;
|
|
37289
|
-
}
|
|
37290
|
-
return prepareLookaheadProgressActuals({ ...progressInput, intent });
|
|
37291
|
-
}
|
|
37292
|
-
function normalizeActualStart(intent, resolveCalendar) {
|
|
37293
|
-
if (intent?.actualStart === void 0) return intent;
|
|
37294
|
-
if (!isUtcMidnight(intent.actualStart)) return intent;
|
|
37295
|
-
const calendar = resolveCalendar();
|
|
37296
|
-
if (calendar === null) {
|
|
37297
|
-
invalid4("ACTIVITY_CALENDAR_REQUIRED");
|
|
37298
|
-
}
|
|
37299
|
-
return {
|
|
37300
|
-
...intent,
|
|
37301
|
-
actualStart: defaultActualStartTime(intent.actualStart, calendar)
|
|
37302
|
-
};
|
|
37303
|
-
}
|
|
37304
|
-
function withMirroredPercent(activity, actuals, nextProgress) {
|
|
37305
|
-
const executionStatus = actuals.executionStatus ?? activity.executionStatus;
|
|
37306
|
-
if (executionStatus !== P6_EXECUTION_STATUS.IN_PROGRESS) return actuals;
|
|
37307
|
-
switch (activity.percentCompleteType) {
|
|
37308
|
-
case P6_PERCENT_COMPLETE_TYPE.PHYSICAL:
|
|
37309
|
-
return { ...actuals, physicalPercentComplete: nextProgress };
|
|
37310
|
-
case P6_PERCENT_COMPLETE_TYPE.DURATION:
|
|
37311
|
-
return {
|
|
37312
|
-
...actuals,
|
|
37313
|
-
remainingDurationHours: activity.originalDurationHours * (1 - nextProgress / COMPLETED_PROGRESS)
|
|
37314
|
-
};
|
|
37315
|
-
default:
|
|
37316
|
-
return actuals;
|
|
37317
|
-
}
|
|
37318
|
-
}
|
|
37319
|
-
function validateInput(input) {
|
|
37320
|
-
if (!Number.isFinite(input.nextProgress) || input.nextProgress < NOT_STARTED_PROGRESS || input.nextProgress > COMPLETED_PROGRESS) {
|
|
37321
|
-
invalid4("INVALID_PROGRESS");
|
|
37322
|
-
}
|
|
37323
|
-
if (input.dataDate !== null && !validDate(input.dataDate)) {
|
|
37324
|
-
invalid4("INVALID_DATA_DATE");
|
|
37325
|
-
}
|
|
37326
|
-
if (input.displayedFinish != null && !validDate(input.displayedFinish)) {
|
|
37327
|
-
invalid4("INVALID_DISPLAYED_FINISH");
|
|
37328
|
-
}
|
|
37329
|
-
}
|
|
37330
|
-
function validDate(value) {
|
|
37331
|
-
return value instanceof Date && Number.isFinite(value.getTime());
|
|
37332
|
-
}
|
|
37333
|
-
function sameUtcDay2(value, [year, month, day]) {
|
|
37334
|
-
return value.getUTCFullYear() === year && value.getUTCMonth() === month - 1 && value.getUTCDate() === day;
|
|
37335
|
-
}
|
|
37336
|
-
function hasIntent(intent) {
|
|
37337
|
-
return intent?.actualStart !== void 0 || intent?.actualFinish !== void 0;
|
|
37338
|
-
}
|
|
37339
|
-
function invalid4(code) {
|
|
37340
|
-
throw new LookaheadActualTransitionError(code);
|
|
37341
|
-
}
|
|
37342
|
-
|
|
37343
37375
|
// src/p6/expected-finish-selection.ts
|
|
37344
37376
|
function resolveExpectedFinishDateSelection(input) {
|
|
37345
37377
|
return resolveLookaheadActualDateSelection({
|