Files
govoplan-records/webui/src/api/records.ts
T
zemion a5eee2c23f
Module Package Release / publish-packages (push) Successful in 12s
feat(records): complete eAkte reference journey
2026-08-22 18:42:09 +02:00

381 lines
11 KiB
TypeScript

import { apiFetch, apiPath, type ApiSettings } from "@govoplan/core-webui";
export type FilePlanNode = {
node_id: string;
revision: number;
parent_node_id?: string | null;
code: string;
label: string;
description?: string | null;
active: boolean;
valid_from?: string | null;
valid_to?: string | null;
recorded_at: string;
closed_at?: string | null;
retention_started_at?: string | null;
retention_due_at?: string | null;
retention_rule: Record<string, unknown>;
appraisal_state?: string | null;
appraisal: Record<string, unknown>;
institutional_context: Record<string, unknown>;
};
export type RecordClass = {
class_id: string;
revision: number;
file_plan_node_id: string;
key: string;
label: string;
description?: string | null;
metadata_requirements: string[];
allowed_source_types: string[];
retention_period_days?: number | null;
closure_trigger?: string | null;
access_mode: "tenant" | "restricted";
active: boolean;
};
export type RecordCatalog = {
file_plan: FilePlanNode[];
classes: RecordClass[];
};
export type RecordEntry = {
record_id: string;
record_number: string;
revision: number;
class_id: string;
file_plan_node_id: string;
title: string;
description?: string | null;
state: "planned" | "open" | string;
source_authority_mode: string;
access_mode: "tenant" | "restricted";
purpose: string;
classification?: string | null;
responsible_unit_id?: string | null;
responsible_function_id?: string | null;
external_reference: Record<string, unknown>;
institutional_context: Record<string, unknown>;
valid_from?: string | null;
valid_to?: string | null;
recorded_at: string;
};
export type RecordVolume = {
volume_id: string;
sequence: number;
label: string;
state: string;
recorded_at: string;
};
export type RecordItem = {
item_id: string;
sequence: number;
volume_id?: string | null;
source: {
source_module: string;
resource_type: string;
resource_id: string;
source_revision: string;
};
label: string;
relationship: string;
filing_reason: string;
purpose: string;
authority_mode: string;
content_sha256?: string | null;
content_type?: string | null;
size_bytes?: number | null;
source_valid_from?: string | null;
source_valid_to?: string | null;
source_recorded_at?: string | null;
launch_url?: string | null;
filed_at: string;
filed_by?: string | null;
institutional_context: Record<string, unknown>;
source_metadata: Record<string, unknown>;
filing_metadata: Record<string, unknown>;
};
export type RecordChronology = {
event_id: string;
event_type: string;
record_revision: number;
summary: string;
occurred_at: string;
actor_id?: string | null;
purpose: string;
payload: Record<string, unknown>;
};
export type RecordHold = {
hold_id: string;
record_id: string;
revision: number;
status: string;
reason: string;
authority: string;
scope: Record<string, unknown>;
effective_from: string;
effective_to?: string | null;
released_at?: string | null;
policy_refs: string[];
recorded_at: string;
};
export type RecordDisposition = {
disposition_id: string;
record_id: string;
revision: number;
action: "retain" | "transfer" | "destroy" | "reclassify";
status: string;
reason: string;
subject_revision: number;
subject_sha256: string;
consequence_preview: Record<string, unknown>;
policy_refs: string[];
approval_request_id?: string | null;
proposed_by?: string | null;
reviewed_by?: string | null;
reviewed_at?: string | null;
recorded_at: string;
};
export type RecordTransferPackage = {
package_id: string;
record_id: string;
disposition_id: string;
revision: number;
record_revision: number;
provider_id: string;
profile: string;
status: string;
authority_mode: string;
manifest: Record<string, unknown>;
manifest_sha256: string;
receipt: Record<string, unknown>;
receipt_sha256?: string | null;
external_reference?: string | null;
recovery_operation_id?: string | null;
simulated: boolean;
institutional_context: Record<string, unknown>;
recorded_at: string;
};
export type RecordDetail = {
record: RecordEntry;
volumes: RecordVolume[];
items: RecordItem[];
chronology: RecordChronology[];
holds: RecordHold[];
dispositions: RecordDisposition[];
transfer_packages: RecordTransferPackage[];
access_explanation: {
decision: string;
reason: string;
purpose: string;
current_authorization: boolean;
access_mode: string;
limitations: string[];
};
};
export type RecordSourceProvider = {
id: string;
source_module: string;
resource_types: string[];
};
export type RecordArchiveProvider = {
id: string;
label: string;
profiles: string[];
authority_modes: string[];
healthy: boolean;
checked_at: string;
last_success_at?: string | null;
freshness_seconds?: number | null;
limitations: string[];
simulated: boolean;
};
export function listRecords(
settings: ApiSettings,
options: {
query?: string;
state?: string;
classId?: string;
filePlanNodeId?: string;
offset?: number;
limit?: number;
},
signal?: AbortSignal
): Promise<{ records: RecordEntry[]; total: number; offset: number; limit: number }> {
return apiFetch(settings, apiPath("/api/v1/records", {
query: options.query,
state: options.state,
class_id: options.classId,
file_plan_node_id: options.filePlanNodeId,
offset: options.offset,
limit: options.limit ?? 50
}), { signal });
}
export function getRecord(settings: ApiSettings, recordId: string, signal?: AbortSignal): Promise<RecordDetail> {
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}`, { signal });
}
export function getRecordCatalog(settings: ApiSettings, signal?: AbortSignal): Promise<RecordCatalog> {
return apiFetch(settings, "/api/v1/records/catalog", { signal });
}
export function getRecordSources(settings: ApiSettings, signal?: AbortSignal): Promise<{ providers: RecordSourceProvider[] }> {
return apiFetch(settings, "/api/v1/records/sources", { signal });
}
export function getRecordArchiveProviders(settings: ApiSettings, signal?: AbortSignal): Promise<{ providers: RecordArchiveProvider[] }> {
return apiFetch(settings, "/api/v1/records/archive-providers", { signal });
}
export function writeFilePlanNode(settings: ApiSettings, payload: Record<string, unknown>): Promise<FilePlanNode> {
return apiFetch(settings, "/api/v1/records/catalog/file-plan", {
method: "POST",
body: JSON.stringify(payload)
});
}
export function writeRecordClass(settings: ApiSettings, payload: Record<string, unknown>): Promise<RecordClass> {
return apiFetch(settings, "/api/v1/records/catalog/classes", {
method: "POST",
body: JSON.stringify(payload)
});
}
export function createRecord(settings: ApiSettings, payload: Record<string, unknown>): Promise<RecordEntry> {
return apiFetch(settings, "/api/v1/records", {
method: "POST",
body: JSON.stringify(payload)
});
}
export function updateRecord(
settings: ApiSettings,
recordId: string,
payload: Record<string, unknown>
): Promise<RecordEntry> {
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}`, {
method: "PATCH",
body: JSON.stringify(payload)
});
}
export function fileRecordItem(
settings: ApiSettings,
recordId: string,
payload: Record<string, unknown>
): Promise<Record<string, unknown>> {
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/items`, {
method: "POST",
body: JSON.stringify(payload)
});
}
export function createRecordVolume(
settings: ApiSettings,
recordId: string,
payload: Record<string, unknown>
): Promise<RecordVolume> {
return recordMutation(settings, recordId, "volumes", payload);
}
export function closeRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
return recordMutation(settings, recordId, "close", payload);
}
export function reopenRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
return recordMutation(settings, recordId, "reopen", payload);
}
export function appraiseRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
return recordMutation(settings, recordId, "appraise", payload);
}
export function applyRecordHold(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordHold> {
return recordMutation(settings, recordId, "holds", payload);
}
export function releaseRecordHold(
settings: ApiSettings,
recordId: string,
holdId: string,
payload: Record<string, unknown>
): Promise<RecordHold> {
return recordMutation(settings, recordId, `holds/${encodeURIComponent(holdId)}/release`, payload);
}
export function proposeRecordDisposition(
settings: ApiSettings,
recordId: string,
payload: Record<string, unknown>
): Promise<RecordDisposition> {
return recordMutation(settings, recordId, "dispositions", payload);
}
export function finalizeRecordDisposition(
settings: ApiSettings,
recordId: string,
dispositionId: string,
payload: Record<string, unknown>
): Promise<{ disposition: RecordDisposition; record: RecordEntry }> {
return recordMutation(settings, recordId, `dispositions/${encodeURIComponent(dispositionId)}/finalize`, payload);
}
export function withdrawRecordDisposition(
settings: ApiSettings,
recordId: string,
dispositionId: string,
payload: Record<string, unknown>
): Promise<RecordDisposition> {
return recordMutation(settings, recordId, `dispositions/${encodeURIComponent(dispositionId)}/withdraw`, payload);
}
export function prepareRecordTransfer(
settings: ApiSettings,
recordId: string,
payload: Record<string, unknown>
): Promise<RecordTransferPackage> {
return recordMutation(settings, recordId, "transfer-packages", payload);
}
export function dispatchRecordTransfer(
settings: ApiSettings,
recordId: string,
packageId: string,
payload: Record<string, unknown>
): Promise<RecordTransferPackage> {
return recordMutation(settings, recordId, `transfer-packages/${encodeURIComponent(packageId)}/dispatch`, payload);
}
export function getRecordRecoveryStatus(
settings: ApiSettings,
recordId: string,
signal?: AbortSignal
): Promise<Record<string, unknown>> {
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/recovery`, { signal });
}
function recordMutation<T>(
settings: ApiSettings,
recordId: string,
path: string,
payload: Record<string, unknown>
): Promise<T> {
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/${path}`, {
method: "POST",
body: JSON.stringify(payload)
});
}