@outbuild-company/schedule-core 1.35.0 → 1.35.2
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 +366 -264
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -119
- package/dist/index.d.ts +129 -119
- package/dist/index.js +366 -265
- 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,14 +13015,14 @@ 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
|
}
|
|
@@ -16117,6 +16112,315 @@ async function dispatchHistoryRevert(action, options, deps) {
|
|
|
16117
16112
|
};
|
|
16118
16113
|
}
|
|
16119
16114
|
|
|
16115
|
+
// src/p6/status.ts
|
|
16116
|
+
var INVALID_STATUS = "Invalid P6 activity status";
|
|
16117
|
+
var P6ActivityStatusError = class extends Error {
|
|
16118
|
+
constructor(code, reason) {
|
|
16119
|
+
super(`${INVALID_STATUS}: ${reason}`);
|
|
16120
|
+
this.code = code;
|
|
16121
|
+
this.name = "P6ActivityStatusError";
|
|
16122
|
+
}
|
|
16123
|
+
code;
|
|
16124
|
+
};
|
|
16125
|
+
var COMPLETED_PHYSICAL_PERCENT2 = 100;
|
|
16126
|
+
var NOT_STARTED_PHYSICAL_PERCENT2 = 0;
|
|
16127
|
+
function validateP6ActivityStatus(activity) {
|
|
16128
|
+
validateRemainingDuration(activity.remainingDurationHours);
|
|
16129
|
+
validateDates(activity);
|
|
16130
|
+
validateExecutionStatus(activity);
|
|
16131
|
+
validateDateOrder(activity);
|
|
16132
|
+
}
|
|
16133
|
+
function validateP6ActivityDraftStatus(activity) {
|
|
16134
|
+
validateDraftRemainingDuration(activity.remainingDurationHours);
|
|
16135
|
+
validateDates(activity);
|
|
16136
|
+
validateDraftExecutionStatus(activity);
|
|
16137
|
+
validateDateOrder(activity);
|
|
16138
|
+
}
|
|
16139
|
+
function normalizeP6ActualDatePatch(current, patch) {
|
|
16140
|
+
if (patch.actualStart === void 0 && patch.actualFinish === void 0) {
|
|
16141
|
+
return patch;
|
|
16142
|
+
}
|
|
16143
|
+
const actualStart = patch.actualStart !== void 0 ? patch.actualStart : current.actualStart;
|
|
16144
|
+
const actualFinish = patch.actualFinish !== void 0 ? patch.actualFinish : current.actualFinish;
|
|
16145
|
+
const executionStatus = actualFinish !== null ? "completed" : actualStart !== null ? "in_progress" : "not_started";
|
|
16146
|
+
const unStarting = actualStart === null && actualFinish === null && current.actualStart !== null;
|
|
16147
|
+
const normalized2 = {
|
|
16148
|
+
...patch,
|
|
16149
|
+
executionStatus,
|
|
16150
|
+
...actualFinish !== null ? {
|
|
16151
|
+
remainingDurationHours: 0,
|
|
16152
|
+
physicalPercentComplete: COMPLETED_PHYSICAL_PERCENT2
|
|
16153
|
+
} : {},
|
|
16154
|
+
...unStarting ? {
|
|
16155
|
+
remainingDurationHours: current.originalDurationHours,
|
|
16156
|
+
physicalPercentComplete: NOT_STARTED_PHYSICAL_PERCENT2
|
|
16157
|
+
} : {}
|
|
16158
|
+
};
|
|
16159
|
+
validateP6ActivityDraftStatus({ ...current, ...normalized2 });
|
|
16160
|
+
return normalized2;
|
|
16161
|
+
}
|
|
16162
|
+
function validateRemainingDuration(remainingDurationHours) {
|
|
16163
|
+
if (!Number.isFinite(remainingDurationHours) || remainingDurationHours < 0) {
|
|
16164
|
+
invalid2("Remaining Duration must be finite and non-negative");
|
|
16165
|
+
}
|
|
16166
|
+
}
|
|
16167
|
+
function validateDraftRemainingDuration(remainingDurationHours) {
|
|
16168
|
+
if (remainingDurationHours === null) return;
|
|
16169
|
+
validateRemainingDuration(remainingDurationHours);
|
|
16170
|
+
}
|
|
16171
|
+
function validateDates(activity) {
|
|
16172
|
+
const dates = [
|
|
16173
|
+
activity.actualStart,
|
|
16174
|
+
activity.actualFinish,
|
|
16175
|
+
activity.suspendDate,
|
|
16176
|
+
activity.resumeDate
|
|
16177
|
+
];
|
|
16178
|
+
if (dates.some((date2) => date2 !== null && Number.isNaN(date2.getTime()))) {
|
|
16179
|
+
invalid2("actual, suspend and resume dates must be valid");
|
|
16180
|
+
}
|
|
16181
|
+
}
|
|
16182
|
+
function validateExecutionStatus(activity) {
|
|
16183
|
+
const hasActualStart = activity.actualStart !== null;
|
|
16184
|
+
const hasActualFinish = activity.actualFinish !== null;
|
|
16185
|
+
if (activity.executionStatus === "not_started") {
|
|
16186
|
+
if (hasActualStart || hasActualFinish) {
|
|
16187
|
+
invalid2("not_started cannot have actual dates");
|
|
16188
|
+
}
|
|
16189
|
+
return;
|
|
16190
|
+
}
|
|
16191
|
+
if (activity.executionStatus === "in_progress") {
|
|
16192
|
+
if (!hasActualStart || hasActualFinish) {
|
|
16193
|
+
invalid2("in_progress requires Actual Start and no Actual Finish");
|
|
16194
|
+
}
|
|
16195
|
+
return;
|
|
16196
|
+
}
|
|
16197
|
+
if (!hasActualStart || !hasActualFinish || activity.remainingDurationHours !== 0) {
|
|
16198
|
+
invalid2(
|
|
16199
|
+
"completed requires Actual Start, Actual Finish and zero Remaining Duration"
|
|
16200
|
+
);
|
|
16201
|
+
}
|
|
16202
|
+
}
|
|
16203
|
+
function validateDraftExecutionStatus(activity) {
|
|
16204
|
+
const hasActualStart = activity.actualStart !== null;
|
|
16205
|
+
const hasActualFinish = activity.actualFinish !== null;
|
|
16206
|
+
if (hasActualFinish && !hasActualStart) {
|
|
16207
|
+
invalid2("Actual Finish requires Actual Start");
|
|
16208
|
+
}
|
|
16209
|
+
if (activity.executionStatus === "not_started" && hasActualStart) {
|
|
16210
|
+
invalid2("not_started cannot have actual dates");
|
|
16211
|
+
}
|
|
16212
|
+
if (activity.executionStatus === "in_progress" && hasActualFinish) {
|
|
16213
|
+
invalid2("in_progress cannot have Actual Finish");
|
|
16214
|
+
}
|
|
16215
|
+
if (activity.executionStatus === "completed" && activity.remainingDurationHours !== null && activity.remainingDurationHours !== 0) {
|
|
16216
|
+
invalid2("completed requires zero Remaining Duration");
|
|
16217
|
+
}
|
|
16218
|
+
}
|
|
16219
|
+
function validateDateOrder(activity) {
|
|
16220
|
+
const { actualStart, actualFinish, suspendDate, resumeDate } = activity;
|
|
16221
|
+
if (actualStart !== null && actualFinish !== null && actualStart.getTime() > actualFinish.getTime()) {
|
|
16222
|
+
throw new P6ActivityStatusError(
|
|
16223
|
+
"ACTUAL_FINISH_BEFORE_START",
|
|
16224
|
+
"Actual Start must not be after Actual Finish"
|
|
16225
|
+
);
|
|
16226
|
+
}
|
|
16227
|
+
if (suspendDate !== null) {
|
|
16228
|
+
if (actualStart === null) invalid2("Suspend requires Actual Start");
|
|
16229
|
+
if (actualStart.getTime() > suspendDate.getTime()) {
|
|
16230
|
+
invalid2("Suspend must not be before Actual Start");
|
|
16231
|
+
}
|
|
16232
|
+
if (actualFinish !== null && suspendDate.getTime() > actualFinish.getTime()) {
|
|
16233
|
+
invalid2("Suspend must not be after Actual Finish");
|
|
16234
|
+
}
|
|
16235
|
+
}
|
|
16236
|
+
if (resumeDate === null) return;
|
|
16237
|
+
if (suspendDate === null) invalid2("Resume requires Suspend");
|
|
16238
|
+
if (suspendDate.getTime() > resumeDate.getTime()) {
|
|
16239
|
+
invalid2("Suspend must not be after Resume");
|
|
16240
|
+
}
|
|
16241
|
+
if (actualFinish !== null && resumeDate.getTime() > actualFinish.getTime()) {
|
|
16242
|
+
invalid2("Resume must not be after Actual Finish");
|
|
16243
|
+
}
|
|
16244
|
+
}
|
|
16245
|
+
function invalid2(reason) {
|
|
16246
|
+
throw new Error(`${INVALID_STATUS}: ${reason}`);
|
|
16247
|
+
}
|
|
16248
|
+
|
|
16249
|
+
// src/p6/lookahead-progress-transition.ts
|
|
16250
|
+
var LookaheadActualTransitionError = class extends Error {
|
|
16251
|
+
constructor(code) {
|
|
16252
|
+
super(code);
|
|
16253
|
+
this.code = code;
|
|
16254
|
+
this.name = "LookaheadActualTransitionError";
|
|
16255
|
+
}
|
|
16256
|
+
code;
|
|
16257
|
+
};
|
|
16258
|
+
var ACTUAL_DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
16259
|
+
function resolveLookaheadActualDateSelection(input) {
|
|
16260
|
+
if (!validDate(input.timeSource)) invalid3("INVALID_ACTUAL_TIME_SOURCE");
|
|
16261
|
+
const parts = actualDayParts(input.selectedDay);
|
|
16262
|
+
const [year, month, day] = parts;
|
|
16263
|
+
const result = new Date(input.timeSource);
|
|
16264
|
+
result.setUTCFullYear(year, month - 1, day);
|
|
16265
|
+
if (!sameUtcDay2(result, parts)) invalid3("INVALID_ACTUAL_DAY");
|
|
16266
|
+
return result;
|
|
16267
|
+
}
|
|
16268
|
+
function actualDayParts(value) {
|
|
16269
|
+
const match = ACTUAL_DAY_PATTERN.exec(value);
|
|
16270
|
+
if (!match) invalid3("INVALID_ACTUAL_DAY");
|
|
16271
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
16272
|
+
}
|
|
16273
|
+
function planLookaheadProgressActuals(input) {
|
|
16274
|
+
validateInput(input);
|
|
16275
|
+
if (input.dataDate === null) {
|
|
16276
|
+
return { start: null, finish: null, uncomplete: null };
|
|
16277
|
+
}
|
|
16278
|
+
const start = input.activity.executionStatus === P6_EXECUTION_STATUS.NOT_STARTED && input.nextProgress > NOT_STARTED_PROGRESS ? { required: true, suggestedAt: new Date(input.dataDate) } : null;
|
|
16279
|
+
const finish = input.activity.executionStatus !== P6_EXECUTION_STATUS.COMPLETED && input.nextProgress === COMPLETED_PROGRESS ? {
|
|
16280
|
+
optional: true,
|
|
16281
|
+
suggestedAt: input.displayedFinish ? new Date(input.displayedFinish) : null
|
|
16282
|
+
} : null;
|
|
16283
|
+
const uncomplete = input.activity.executionStatus === P6_EXECUTION_STATUS.COMPLETED && input.activity.actualFinish !== null && input.nextProgress < COMPLETED_PROGRESS ? {
|
|
16284
|
+
required: true,
|
|
16285
|
+
removes: new Date(input.activity.actualFinish)
|
|
16286
|
+
} : null;
|
|
16287
|
+
return { start, finish, uncomplete };
|
|
16288
|
+
}
|
|
16289
|
+
function prepareLookaheadProgressActuals(input) {
|
|
16290
|
+
const plan = planLookaheadProgressActuals(input);
|
|
16291
|
+
if (input.dataDate === null && hasIntent(input.intent)) {
|
|
16292
|
+
invalid3("DATA_DATE_INACTIVE");
|
|
16293
|
+
}
|
|
16294
|
+
if (plan.start && input.intent?.actualStart === void 0) {
|
|
16295
|
+
invalid3("ACTUAL_START_REQUIRED");
|
|
16296
|
+
}
|
|
16297
|
+
if (input.intent?.actualFinish instanceof Date && input.nextProgress !== COMPLETED_PROGRESS) {
|
|
16298
|
+
invalid3("ACTUAL_FINISH_REQUIRES_100");
|
|
16299
|
+
}
|
|
16300
|
+
if (plan.uncomplete && input.intent?.actualFinish !== null) {
|
|
16301
|
+
invalid3("ACTUAL_FINISH_REMOVAL_REQUIRED");
|
|
16302
|
+
}
|
|
16303
|
+
if (!plan.uncomplete && input.intent?.actualFinish === null) {
|
|
16304
|
+
invalid3("ACTUAL_FINISH_REMOVAL_NOT_APPLICABLE");
|
|
16305
|
+
}
|
|
16306
|
+
const actuals = normalizeP6ActualDatePatch(
|
|
16307
|
+
input.activity,
|
|
16308
|
+
input.intent ?? {}
|
|
16309
|
+
);
|
|
16310
|
+
if (input.dataDate === null) return actuals;
|
|
16311
|
+
return withMirroredPercent(input.activity, actuals, input.nextProgress);
|
|
16312
|
+
}
|
|
16313
|
+
function prepareLookaheadProgressActualsForPersistence(input) {
|
|
16314
|
+
const { resolveCalendar, ...progressInput } = input;
|
|
16315
|
+
const preparedActuals = prepareLookaheadProgressActuals(progressInput);
|
|
16316
|
+
if (input.dataDate === null) {
|
|
16317
|
+
return preparedActuals;
|
|
16318
|
+
}
|
|
16319
|
+
const actualStart = input.intent?.actualStart;
|
|
16320
|
+
const needsActualStartNormalization = actualStart !== void 0 && isUtcMidnight(actualStart);
|
|
16321
|
+
if (!needsActualStartNormalization) return preparedActuals;
|
|
16322
|
+
const intent = normalizeActualStart(
|
|
16323
|
+
input.intent,
|
|
16324
|
+
input.activity.actualStart,
|
|
16325
|
+
resolveCalendar
|
|
16326
|
+
);
|
|
16327
|
+
if (intent === void 0) {
|
|
16328
|
+
return preparedActuals;
|
|
16329
|
+
}
|
|
16330
|
+
return prepareLookaheadProgressActuals({ ...progressInput, intent });
|
|
16331
|
+
}
|
|
16332
|
+
function normalizeActualStart(intent, existingActualStart, resolveCalendar) {
|
|
16333
|
+
if (intent?.actualStart === void 0) return intent;
|
|
16334
|
+
if (!isUtcMidnight(intent.actualStart)) return intent;
|
|
16335
|
+
if (existingActualStart !== null) {
|
|
16336
|
+
return {
|
|
16337
|
+
...intent,
|
|
16338
|
+
actualStart: resolveLookaheadActualDateSelection({
|
|
16339
|
+
selectedDay: intent.actualStart.toISOString().slice(0, 10),
|
|
16340
|
+
timeSource: existingActualStart
|
|
16341
|
+
})
|
|
16342
|
+
};
|
|
16343
|
+
}
|
|
16344
|
+
const calendar = resolveCalendar();
|
|
16345
|
+
if (calendar === null) {
|
|
16346
|
+
invalid3("ACTIVITY_CALENDAR_REQUIRED");
|
|
16347
|
+
}
|
|
16348
|
+
return {
|
|
16349
|
+
...intent,
|
|
16350
|
+
actualStart: defaultActualStartTime(intent.actualStart, calendar)
|
|
16351
|
+
};
|
|
16352
|
+
}
|
|
16353
|
+
function withMirroredPercent(activity, actuals, nextProgress) {
|
|
16354
|
+
const executionStatus = actuals.executionStatus ?? activity.executionStatus;
|
|
16355
|
+
if (executionStatus !== P6_EXECUTION_STATUS.IN_PROGRESS) return actuals;
|
|
16356
|
+
switch (activity.percentCompleteType) {
|
|
16357
|
+
case P6_PERCENT_COMPLETE_TYPE.PHYSICAL:
|
|
16358
|
+
return { ...actuals, physicalPercentComplete: nextProgress };
|
|
16359
|
+
case P6_PERCENT_COMPLETE_TYPE.DURATION:
|
|
16360
|
+
return {
|
|
16361
|
+
...actuals,
|
|
16362
|
+
remainingDurationHours: activity.originalDurationHours * (1 - nextProgress / COMPLETED_PROGRESS)
|
|
16363
|
+
};
|
|
16364
|
+
default:
|
|
16365
|
+
return actuals;
|
|
16366
|
+
}
|
|
16367
|
+
}
|
|
16368
|
+
function validateInput(input) {
|
|
16369
|
+
if (!Number.isFinite(input.nextProgress) || input.nextProgress < NOT_STARTED_PROGRESS || input.nextProgress > COMPLETED_PROGRESS) {
|
|
16370
|
+
invalid3("INVALID_PROGRESS");
|
|
16371
|
+
}
|
|
16372
|
+
if (input.dataDate !== null && !validDate(input.dataDate)) {
|
|
16373
|
+
invalid3("INVALID_DATA_DATE");
|
|
16374
|
+
}
|
|
16375
|
+
if (input.displayedFinish != null && !validDate(input.displayedFinish)) {
|
|
16376
|
+
invalid3("INVALID_DISPLAYED_FINISH");
|
|
16377
|
+
}
|
|
16378
|
+
}
|
|
16379
|
+
function validDate(value) {
|
|
16380
|
+
return value instanceof Date && Number.isFinite(value.getTime());
|
|
16381
|
+
}
|
|
16382
|
+
function sameUtcDay2(value, [year, month, day]) {
|
|
16383
|
+
return value.getUTCFullYear() === year && value.getUTCMonth() === month - 1 && value.getUTCDate() === day;
|
|
16384
|
+
}
|
|
16385
|
+
function hasIntent(intent) {
|
|
16386
|
+
return intent?.actualStart !== void 0 || intent?.actualFinish !== void 0;
|
|
16387
|
+
}
|
|
16388
|
+
function invalid3(code) {
|
|
16389
|
+
throw new LookaheadActualTransitionError(code);
|
|
16390
|
+
}
|
|
16391
|
+
|
|
16392
|
+
// src/p6/lookahead-reconciliation.ts
|
|
16393
|
+
function preparePersistedLookaheadDataDate(action, activity, deps) {
|
|
16394
|
+
const settings = deps.dataDateSettings;
|
|
16395
|
+
const capability = deps.dataDateCapability;
|
|
16396
|
+
if (action.persistedProgress === void 0 || activity?.p6 === void 0 || capability === null || !hasActiveDataDate(settings, deps.dataDateEnabled) || settings?.dataDate == null)
|
|
16397
|
+
return null;
|
|
16398
|
+
const patch = prepareLookaheadProgressActuals({
|
|
16399
|
+
dataDate: settings.dataDate,
|
|
16400
|
+
activity: activity.p6,
|
|
16401
|
+
nextProgress: action.persistedProgress,
|
|
16402
|
+
...action.persistedActualTransition === void 0 ? {} : { intent: action.persistedActualTransition }
|
|
16403
|
+
});
|
|
16404
|
+
const prepared = capability.prepareActivityUpdate(
|
|
16405
|
+
activity.p6,
|
|
16406
|
+
{
|
|
16407
|
+
originalDurationHours: activity.p6.originalDurationHours,
|
|
16408
|
+
...patch.actualStart === void 0 ? {} : { actualStart: patch.actualStart },
|
|
16409
|
+
...patch.actualFinish === void 0 ? {} : { actualFinish: patch.actualFinish },
|
|
16410
|
+
...patch.remainingDurationHours == null ? {} : { remainingDurationHours: patch.remainingDurationHours },
|
|
16411
|
+
...patch.physicalPercentComplete == null ? {} : { physicalPercentComplete: patch.physicalPercentComplete }
|
|
16412
|
+
},
|
|
16413
|
+
activity.constraintType
|
|
16414
|
+
);
|
|
16415
|
+
const calendar = deps.adapter.calendarReader.getCalendar(activity.calendarId);
|
|
16416
|
+
const projection = calendar === null ? { p6: prepared.next, startDate: void 0, endDate: void 0 } : capability.projectLocalActivity(activity.p6, prepared.next, {
|
|
16417
|
+
calendar,
|
|
16418
|
+
dataDate: settings.dataDate,
|
|
16419
|
+
totalFloatMethod: settings.totalFloatMethod
|
|
16420
|
+
});
|
|
16421
|
+
return { activityId: activity.id, ...projection };
|
|
16422
|
+
}
|
|
16423
|
+
|
|
16120
16424
|
// src/dispatch/handlers/persistence-acknowledge.ts
|
|
16121
16425
|
var EMPTY_OWNERS = /* @__PURE__ */ new Map();
|
|
16122
16426
|
function persistedOwnersOf(entities) {
|
|
@@ -16335,6 +16639,30 @@ async function dispatchActivityLookaheadSync(action, options, deps) {
|
|
|
16335
16639
|
if (snapshots.some((snapshot) => !snapshot)) {
|
|
16336
16640
|
return { ok: false, reason: REJECTION_REASON.ACTIVITY_NOT_FOUND };
|
|
16337
16641
|
}
|
|
16642
|
+
const persistedDataDate = preparePersistedLookaheadDataDate(
|
|
16643
|
+
action,
|
|
16644
|
+
snapshots[0],
|
|
16645
|
+
deps
|
|
16646
|
+
);
|
|
16647
|
+
if (persistedDataDate !== null) {
|
|
16648
|
+
deps.adapter.setActivityField(
|
|
16649
|
+
persistedDataDate.activityId,
|
|
16650
|
+
"p6",
|
|
16651
|
+
persistedDataDate.p6
|
|
16652
|
+
);
|
|
16653
|
+
if (persistedDataDate.startDate !== void 0)
|
|
16654
|
+
deps.adapter.setActivityField(
|
|
16655
|
+
persistedDataDate.activityId,
|
|
16656
|
+
"startDate",
|
|
16657
|
+
persistedDataDate.startDate
|
|
16658
|
+
);
|
|
16659
|
+
if (persistedDataDate.endDate !== void 0)
|
|
16660
|
+
deps.adapter.setActivityField(
|
|
16661
|
+
persistedDataDate.activityId,
|
|
16662
|
+
"endDate",
|
|
16663
|
+
persistedDataDate.endDate
|
|
16664
|
+
);
|
|
16665
|
+
}
|
|
16338
16666
|
const activities = [];
|
|
16339
16667
|
for (const [index, id] of ids.entries()) {
|
|
16340
16668
|
const snapshot = snapshots[index];
|
|
@@ -16375,7 +16703,7 @@ async function dispatchActivityLookaheadSync(action, options, deps) {
|
|
|
16375
16703
|
[{ activityId: ids[0], progress: action.persistedProgress }],
|
|
16376
16704
|
deps
|
|
16377
16705
|
);
|
|
16378
|
-
if (progressChanges.length > 0) {
|
|
16706
|
+
if (progressChanges.length > 0 || persistedDataDate !== null) {
|
|
16379
16707
|
await runPostMutation(
|
|
16380
16708
|
{
|
|
16381
16709
|
adapter: deps.adapter,
|
|
@@ -17617,7 +17945,7 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
17617
17945
|
const statusRouting = resolveDataDateProgressButton(
|
|
17618
17946
|
activitySnap,
|
|
17619
17947
|
action.newValue,
|
|
17620
|
-
|
|
17948
|
+
progressChanges,
|
|
17621
17949
|
deps,
|
|
17622
17950
|
options.confirmations
|
|
17623
17951
|
);
|
|
@@ -17625,17 +17953,14 @@ async function dispatchActivitySetProgress(action, options, deps) {
|
|
|
17625
17953
|
return rejectedRouting(statusRouting);
|
|
17626
17954
|
}
|
|
17627
17955
|
const changes = statusRouting === null ? progressChanges : statusRouting.changes;
|
|
17628
|
-
const writesProgress = statusRouting === null || editGate.allowed;
|
|
17629
17956
|
const touchedIds = collectTouchedIds(action.activityId, changes);
|
|
17630
17957
|
const beforeSnap = await snapshotActivities(adapter, touchedIds);
|
|
17631
17958
|
applyFieldChanges(adapter, action.activityId, changes);
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
);
|
|
17638
|
-
}
|
|
17959
|
+
setExplicitSummaryProgressFallbacks(
|
|
17960
|
+
action.activityId,
|
|
17961
|
+
action.newValue,
|
|
17962
|
+
adapter
|
|
17963
|
+
);
|
|
17639
17964
|
runPostProcessorsOnAdapter(
|
|
17640
17965
|
action.activityId,
|
|
17641
17966
|
changes.postProcessors ?? [],
|
|
@@ -26797,140 +27122,6 @@ function changed(before, after) {
|
|
|
26797
27122
|
return serializeCanonicalSchedule(before) !== serializeCanonicalSchedule(after);
|
|
26798
27123
|
}
|
|
26799
27124
|
|
|
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
27125
|
// src/p6/derived.ts
|
|
26935
27126
|
var INVALID_INPUT = "Invalid P6 derived input";
|
|
26936
27127
|
var PERCENT_SCALE2 = 100;
|
|
@@ -30899,48 +31090,48 @@ function optionalP6Date(rawValue) {
|
|
|
30899
31090
|
function yesNo(rawValue) {
|
|
30900
31091
|
if (rawValue === "Y") return true;
|
|
30901
31092
|
if (rawValue === "N") return false;
|
|
30902
|
-
|
|
31093
|
+
invalid4(`expected Y/N, got "${rawValue}"`);
|
|
30903
31094
|
}
|
|
30904
31095
|
function enumValue(map, rawValue) {
|
|
30905
|
-
if (!Object.hasOwn(map, rawValue))
|
|
31096
|
+
if (!Object.hasOwn(map, rawValue)) invalid4(`unknown enum "${rawValue}"`);
|
|
30906
31097
|
return map[rawValue];
|
|
30907
31098
|
}
|
|
30908
31099
|
function outOfSequencePolicy(schedule) {
|
|
30909
31100
|
const retained = yesNo(schedule.sched_retained_logic);
|
|
30910
31101
|
const override = yesNo(schedule.sched_progress_override);
|
|
30911
31102
|
if (retained && override)
|
|
30912
|
-
|
|
31103
|
+
invalid4("retained logic and progress override conflict");
|
|
30913
31104
|
if (retained) return "retained_logic";
|
|
30914
31105
|
if (override) return "progress_override";
|
|
30915
31106
|
return "actual_dates";
|
|
30916
31107
|
}
|
|
30917
31108
|
function nonNegativeNumber(rawValue, field) {
|
|
30918
31109
|
const value = finiteNumber(rawValue, field);
|
|
30919
|
-
if (value < 0)
|
|
31110
|
+
if (value < 0) invalid4(`${field} must be a non-negative number`);
|
|
30920
31111
|
return value;
|
|
30921
31112
|
}
|
|
30922
31113
|
function finiteNumber(rawValue, field) {
|
|
30923
31114
|
const value = Number(rawValue);
|
|
30924
31115
|
if (rawValue === "" || !Number.isFinite(value)) {
|
|
30925
|
-
|
|
31116
|
+
invalid4(`${field} must be a finite number`);
|
|
30926
31117
|
}
|
|
30927
31118
|
return value;
|
|
30928
31119
|
}
|
|
30929
31120
|
function nonNegativeInteger(rawValue, field) {
|
|
30930
31121
|
const value = nonNegativeNumber(rawValue, field);
|
|
30931
|
-
if (!Number.isInteger(value))
|
|
31122
|
+
if (!Number.isInteger(value)) invalid4(`${field} must be an integer`);
|
|
30932
31123
|
return value;
|
|
30933
31124
|
}
|
|
30934
31125
|
function endingActivityId(rawValue, resolveActivityId) {
|
|
30935
31126
|
if (rawValue === "") return null;
|
|
30936
31127
|
if (resolveActivityId === void 0) {
|
|
30937
|
-
|
|
31128
|
+
invalid4("ending activity requires an ID resolver");
|
|
30938
31129
|
}
|
|
30939
31130
|
const resolved = resolveActivityId(rawValue);
|
|
30940
|
-
if (resolved === null)
|
|
31131
|
+
if (resolved === null) invalid4(`unknown ending activity "${rawValue}"`);
|
|
30941
31132
|
return resolved;
|
|
30942
31133
|
}
|
|
30943
|
-
function
|
|
31134
|
+
function invalid4(reason) {
|
|
30944
31135
|
throw new Error(`${INVALID_OPTIONS}: ${reason}`);
|
|
30945
31136
|
}
|
|
30946
31137
|
|
|
@@ -37210,109 +37401,6 @@ function serializeP6State(input) {
|
|
|
37210
37401
|
// src/boundary/save/unsaved.ts
|
|
37211
37402
|
var getUnsavedActivities = (activities = []) => (activities ?? []).filter((activity) => !activity.proplannerId);
|
|
37212
37403
|
|
|
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 withMirroredPercent(activity, actuals, nextProgress) {
|
|
37278
|
-
const executionStatus = actuals.executionStatus ?? activity.executionStatus;
|
|
37279
|
-
if (executionStatus !== P6_EXECUTION_STATUS.IN_PROGRESS) return actuals;
|
|
37280
|
-
switch (activity.percentCompleteType) {
|
|
37281
|
-
case P6_PERCENT_COMPLETE_TYPE.PHYSICAL:
|
|
37282
|
-
return { ...actuals, physicalPercentComplete: nextProgress };
|
|
37283
|
-
case P6_PERCENT_COMPLETE_TYPE.DURATION:
|
|
37284
|
-
return {
|
|
37285
|
-
...actuals,
|
|
37286
|
-
remainingDurationHours: activity.originalDurationHours * (1 - nextProgress / COMPLETED_PROGRESS)
|
|
37287
|
-
};
|
|
37288
|
-
default:
|
|
37289
|
-
return actuals;
|
|
37290
|
-
}
|
|
37291
|
-
}
|
|
37292
|
-
function validateInput(input) {
|
|
37293
|
-
if (!Number.isFinite(input.nextProgress) || input.nextProgress < NOT_STARTED_PROGRESS || input.nextProgress > COMPLETED_PROGRESS) {
|
|
37294
|
-
invalid4("INVALID_PROGRESS");
|
|
37295
|
-
}
|
|
37296
|
-
if (input.dataDate !== null && !validDate(input.dataDate)) {
|
|
37297
|
-
invalid4("INVALID_DATA_DATE");
|
|
37298
|
-
}
|
|
37299
|
-
if (input.displayedFinish != null && !validDate(input.displayedFinish)) {
|
|
37300
|
-
invalid4("INVALID_DISPLAYED_FINISH");
|
|
37301
|
-
}
|
|
37302
|
-
}
|
|
37303
|
-
function validDate(value) {
|
|
37304
|
-
return value instanceof Date && Number.isFinite(value.getTime());
|
|
37305
|
-
}
|
|
37306
|
-
function sameUtcDay2(value, [year, month, day]) {
|
|
37307
|
-
return value.getUTCFullYear() === year && value.getUTCMonth() === month - 1 && value.getUTCDate() === day;
|
|
37308
|
-
}
|
|
37309
|
-
function hasIntent(intent) {
|
|
37310
|
-
return intent?.actualStart !== void 0 || intent?.actualFinish !== void 0;
|
|
37311
|
-
}
|
|
37312
|
-
function invalid4(code) {
|
|
37313
|
-
throw new LookaheadActualTransitionError(code);
|
|
37314
|
-
}
|
|
37315
|
-
|
|
37316
37404
|
// src/p6/expected-finish-selection.ts
|
|
37317
37405
|
function resolveExpectedFinishDateSelection(input) {
|
|
37318
37406
|
return resolveLookaheadActualDateSelection({
|
|
@@ -37344,7 +37432,20 @@ function createScheduleCalendars(input) {
|
|
|
37344
37432
|
function createLookaheadDerivedFields(input) {
|
|
37345
37433
|
const { resolveCalendar } = createScheduleCalendars(input);
|
|
37346
37434
|
return {
|
|
37347
|
-
|
|
37435
|
+
getCalendar(calendarId) {
|
|
37436
|
+
const calendar = resolveCalendar(calendarId);
|
|
37437
|
+
if (!calendar) {
|
|
37438
|
+
throw new LookaheadActualTransitionError("ACTIVITY_CALENDAR_REQUIRED");
|
|
37439
|
+
}
|
|
37440
|
+
return calendar;
|
|
37441
|
+
},
|
|
37442
|
+
derive({
|
|
37443
|
+
previous,
|
|
37444
|
+
next,
|
|
37445
|
+
calendarId,
|
|
37446
|
+
dataDate,
|
|
37447
|
+
totalFloatMethod
|
|
37448
|
+
}) {
|
|
37348
37449
|
if (!isP6ActivityState(next)) return null;
|
|
37349
37450
|
const calendar = resolveCalendar(calendarId);
|
|
37350
37451
|
if (!calendar) return null;
|
|
@@ -38126,6 +38227,7 @@ exports.parseP6DayAsCalendarStart = parseP6DayAsCalendarStart;
|
|
|
38126
38227
|
exports.parseP6WallDateAsUtc = parseP6WallDateAsUtc;
|
|
38127
38228
|
exports.planLookaheadProgressActuals = planLookaheadProgressActuals;
|
|
38128
38229
|
exports.prepareLookaheadProgressActuals = prepareLookaheadProgressActuals;
|
|
38230
|
+
exports.prepareLookaheadProgressActualsForPersistence = prepareLookaheadProgressActualsForPersistence;
|
|
38129
38231
|
exports.rescheduledOnLoad = rescheduledOnLoad;
|
|
38130
38232
|
exports.resolveExpectedFinishDateSelection = resolveExpectedFinishDateSelection;
|
|
38131
38233
|
exports.resolveLookaheadActualDateSelection = resolveLookaheadActualDateSelection;
|