forked from jappel/leistungsbilanz-ts
Integrate rough estimate balance
This commit is contained in:
commit
573487666c
45 changed files with 9378 additions and 58 deletions
|
|
@ -3,6 +3,8 @@ import { ProjectStateConflictError } from "../../domain/errors/project-state-con
|
|||
import {
|
||||
assertProjectStateRestoreCommand,
|
||||
createProjectStateRestoreCommand,
|
||||
createProjectTransferRestoreCommand,
|
||||
projectStateRestoreCommandSchemaVersion,
|
||||
} from "../../domain/models/project-state-restore-command.model.js";
|
||||
import {
|
||||
parseProjectStateSnapshot,
|
||||
|
|
@ -13,6 +15,8 @@ import type {
|
|||
ProjectStateRestoreCommandStore,
|
||||
} from "../../domain/ports/project-state-restore-command.store.js";
|
||||
import type { AppDatabase } from "../database-context.js";
|
||||
import { canonicalEstimateBalance } from "../../estimate-balance/domain/estimate-balance-command.model.js";
|
||||
import type { EstimateBalanceSnapshot } from "../../shared/estimate-balance/estimate-balance.js";
|
||||
import { circuitDeviceRows } from "../schema/circuit-device-rows.js";
|
||||
import { circuitLists } from "../schema/circuit-lists.js";
|
||||
import { circuitProtectionDevices } from "../schema/circuit-protection-devices.js";
|
||||
|
|
@ -32,6 +36,11 @@ import { externalImportBatches } from "../schema/external-import-batches.js";
|
|||
import { externalModelObjects } from "../schema/external-model-objects.js";
|
||||
import { externalModelSources } from "../schema/external-model-sources.js";
|
||||
import { externalRoomMappings } from "../schema/external-room-mappings.js";
|
||||
import { estimateBalances } from "../schema/estimate-balances.js";
|
||||
import {
|
||||
insertEstimateBalance,
|
||||
readEstimateBalances,
|
||||
} from "./estimate-balance.persistence.js";
|
||||
import { executeProjectCommandTransaction } from "./project-command-transaction.persistence.js";
|
||||
import {
|
||||
readProjectStateSnapshot,
|
||||
|
|
@ -66,10 +75,39 @@ export class ProjectStateRestoreCommandRepository
|
|||
if (!current) {
|
||||
throw new Error("Project not found.");
|
||||
}
|
||||
const currentEstimateBalances = readEstimateBalances(tx, input.projectId);
|
||||
const transferCommand =
|
||||
input.command.schemaVersion === projectStateRestoreCommandSchemaVersion
|
||||
? input.command
|
||||
: null;
|
||||
if (
|
||||
current.payloadSha256 !==
|
||||
input.command.payload.expectedStateSha256 &&
|
||||
!matchesHistoryRestoreTarget(tx, input, current.state)
|
||||
!matchesHistoryRestoreTarget(
|
||||
tx,
|
||||
input,
|
||||
current.state,
|
||||
currentEstimateBalances
|
||||
)
|
||||
) {
|
||||
throw new ProjectStateConflictError(
|
||||
input.projectId,
|
||||
input.command.payload.expectedStateSha256,
|
||||
current.payloadSha256
|
||||
);
|
||||
}
|
||||
if (
|
||||
transferCommand &&
|
||||
canonicalEstimateBalances(currentEstimateBalances) !==
|
||||
canonicalEstimateBalances(
|
||||
transferCommand.payload.expectedEstimateBalances
|
||||
) &&
|
||||
!matchesHistoryRestoreTarget(
|
||||
tx,
|
||||
input,
|
||||
current.state,
|
||||
currentEstimateBalances
|
||||
)
|
||||
) {
|
||||
throw new ProjectStateConflictError(
|
||||
input.projectId,
|
||||
|
|
@ -82,14 +120,28 @@ export class ProjectStateRestoreCommandRepository
|
|||
input.command.payload.targetState
|
||||
);
|
||||
replaceProjectState(tx, targetState);
|
||||
if (transferCommand) {
|
||||
replaceEstimateBalances(
|
||||
tx,
|
||||
input.projectId,
|
||||
transferCommand.payload.targetEstimateBalances
|
||||
);
|
||||
}
|
||||
const persistedTarget = readProjectStateSnapshot(tx, input.projectId);
|
||||
if (!persistedTarget) {
|
||||
throw new Error("Restored project could not be loaded.");
|
||||
}
|
||||
const inverse = createProjectStateRestoreCommand(
|
||||
persistedTarget.payloadSha256,
|
||||
current.state
|
||||
);
|
||||
const inverse = transferCommand
|
||||
? createProjectTransferRestoreCommand(
|
||||
persistedTarget.payloadSha256,
|
||||
current.state,
|
||||
transferCommand.payload.targetEstimateBalances,
|
||||
currentEstimateBalances
|
||||
)
|
||||
: createProjectStateRestoreCommand(
|
||||
persistedTarget.payloadSha256,
|
||||
current.state
|
||||
);
|
||||
|
||||
return inverse;
|
||||
}
|
||||
|
|
@ -98,7 +150,8 @@ export class ProjectStateRestoreCommandRepository
|
|||
function matchesHistoryRestoreTarget(
|
||||
database: AppDatabase,
|
||||
input: ExecuteProjectStateRestoreCommandInput,
|
||||
currentState: ProjectStateSnapshot
|
||||
currentState: ProjectStateSnapshot,
|
||||
currentEstimateBalances: EstimateBalanceSnapshot[]
|
||||
) {
|
||||
if (
|
||||
(input.source !== "undo" && input.source !== "redo") ||
|
||||
|
|
@ -122,25 +175,45 @@ function matchesHistoryRestoreTarget(
|
|||
input.source === "undo"
|
||||
? changeSet.forwardPayloadJson
|
||||
: changeSet.inversePayloadJson;
|
||||
const command = JSON.parse(serialized) as {
|
||||
type?: unknown;
|
||||
payload?: { targetState?: unknown };
|
||||
};
|
||||
if (command.type !== "project.restore-state") {
|
||||
const command = JSON.parse(serialized) as unknown;
|
||||
assertProjectStateRestoreCommand(command);
|
||||
const expectedState = parseProjectStateSnapshot(command.payload.targetState);
|
||||
const stateMatches =
|
||||
canonicalProjectState(expectedState) ===
|
||||
canonicalProjectState(currentState);
|
||||
if (!stateMatches) {
|
||||
return false;
|
||||
}
|
||||
const expectedState = parseProjectStateSnapshot(
|
||||
command.payload?.targetState
|
||||
);
|
||||
return (
|
||||
canonicalProjectState(expectedState) ===
|
||||
canonicalProjectState(currentState)
|
||||
);
|
||||
return command.schemaVersion !== projectStateRestoreCommandSchemaVersion ||
|
||||
canonicalEstimateBalances(command.payload.targetEstimateBalances) ===
|
||||
canonicalEstimateBalances(currentEstimateBalances);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function canonicalEstimateBalances(balances: EstimateBalanceSnapshot[]) {
|
||||
return JSON.stringify(
|
||||
[...balances]
|
||||
.sort((left, right) => left.id.localeCompare(right.id))
|
||||
.map((balance) => canonicalEstimateBalance(balance))
|
||||
);
|
||||
}
|
||||
|
||||
function replaceEstimateBalances(
|
||||
database: AppDatabase,
|
||||
projectId: string,
|
||||
balances: EstimateBalanceSnapshot[]
|
||||
) {
|
||||
database
|
||||
.delete(estimateBalances)
|
||||
.where(eq(estimateBalances.projectId, projectId))
|
||||
.run();
|
||||
for (const balance of balances) {
|
||||
insertEstimateBalance(database, balance);
|
||||
}
|
||||
}
|
||||
|
||||
function canonicalProjectState(state: ProjectStateSnapshot) {
|
||||
return JSON.stringify({
|
||||
...state,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue