Files
Investidor-V2/resources/js/lib/investment-preparation.ts
T

144 lines
4.1 KiB
TypeScript

import { createOperationKey } from './operation-key.ts';
export const swotDimensions = {
strength: 'Forças — internas ao objecto',
weakness: 'Fraquezas — internas ao objecto',
opportunity: 'Oportunidades — externas ao objecto',
threat: 'Ameaças — externas ao objecto',
} as const;
export type SwotRow = {
id: string;
dimension: keyof typeof swotDimensions;
text: string;
reference: string;
source_key: string | null;
date: string | null;
classification: 'documented_fact' | 'hypothesis' | 'unconfirmed';
};
export type SwotDraft = {
sources_snapshot?: unknown;
snapshot_fingerprint?: string;
object_key: string;
scope: string | null;
rows: SwotRow[];
source_fingerprint: string;
review?: { reason: string; at: string } | null;
actions: {
id: string;
title: string;
kind: string;
href: string;
review_version: number;
}[];
};
export type Workspace = {
historical?: boolean;
initial_scope?: boolean;
saved_scopes?: { key: string; label: string; href: string }[];
case: { id: string; title: string; closed: boolean };
opportunity: string | null;
opportunity_label?: string | null;
version: number;
apiex: {
note: string | null;
additional_documents: string[];
review: { reason: string; at: string; fingerprint: string } | null;
exports: { id: string; at: string; context_revision: number }[];
external: {
id: string;
kind: string;
date: string;
reference: string;
proof_document: string;
related_id?: string;
export_id: string;
outcome?: string;
}[];
};
swot: SwotDraft;
api_state: string;
api_issues: string[];
api_fingerprint: string;
swot_fingerprint: string;
swot_review_required: boolean;
can_write: boolean;
can_review: boolean;
links: Record<string, string>;
objects: { key: string; label: string; kind: string }[];
sources: {
key: string;
label: string;
consulted?: unknown;
current?: unknown;
notice?: string;
}[];
reused?: Record<string, unknown>;
context: { revision: number; fields: Record<string, unknown> };
assessment: {
requirements: {
key: string;
label: string;
state: string;
required: boolean;
available: boolean;
reason: string;
document_id: string | null;
source: { reference: string; url: string };
}[];
};
documents: {
id: string;
document_id: string;
file_name: string;
available: boolean;
version_no: number;
}[];
history_next?: number | null;
history: {
version: number;
action: string;
at: string;
actor: number;
operation_key?: string;
}[];
};
/** A lost response retains the exact intent; editing fields never mutates a retry. */
export class PreparationAttempt {
private value: Record<string, unknown> | null = null;
start(
version: number,
opportunity: string | null,
action: string,
data: Record<string, unknown>,
reason: string,
) {
if (this.value)
throw Error('Resolva a tentativa anterior antes de iniciar outra.');
this.value = JSON.parse(
JSON.stringify({
...data,
version,
opportunity,
action,
reason,
operation_key: createOperationKey(),
}),
) as Record<string, unknown>;
return this.current()!;
}
current() {
return this.value ? structuredClone(this.value) : null;
}
complete() {
this.value = null;
}
canAdopt(view: Pick<Workspace, 'version' | 'history'>) {
return (
!this.value ||
view.version > Number(this.value.version) ||
view.history.some(
(h) => h.operation_key === this.value?.operation_key,
)
);
}
}