This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// The tables of the documents module (spec §16). Two, both project-owned.
|
||||
//
|
||||
// `documents_document` is one uploaded file's processing state. `documents_line` holds only what a
|
||||
// person has APPROVED: an extracted line lives as a proposal (kit-proposals) until somebody
|
||||
// decides it, and the proposal's writer inserts the line in the approving transaction. That is how
|
||||
// "nothing is exported without approval" is a property of the schema and not of a filter: the
|
||||
// export reads this table, and nothing but an approval writes to it.
|
||||
|
||||
import { defineEntity, idSchema, instantSchema } from "@conusai-kit/data"
|
||||
import { z } from "zod"
|
||||
import { DOCUMENT_STATUSES, FAILURE_CODES, PAGE_CLASSES } from "./constants.js"
|
||||
|
||||
export const documents = defineEntity({
|
||||
name: "document",
|
||||
table: "documents_document",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
/** The row of the files module this document was made from: an opaque id, never a foreign key (spec §4.4). */
|
||||
fileId: idSchema,
|
||||
filename: z.string().min(1).max(255),
|
||||
status: z.enum(DOCUMENT_STATUSES),
|
||||
/** The platform's OCR job id, recorded as soon as the job is accepted so a retry resumes it. */
|
||||
ocrJobId: z.number().int().nonnegative().nullable(),
|
||||
pageCount: z.number().int().nonnegative().nullable(),
|
||||
/** How many lines the extraction proposed; the proposals themselves are the reviewer's queue. */
|
||||
proposedCount: z.number().int().nonnegative().nullable(),
|
||||
failureCode: z.enum(FAILURE_CODES).nullable(),
|
||||
/** The pages the extraction left out, with the class that excluded each, so a reviewer sees what was not read. Null until extracted. */
|
||||
skippedPages: z
|
||||
.array(z.object({ page: z.number().int().min(1), pageClass: z.enum(PAGE_CLASSES) }).strict())
|
||||
.nullable(),
|
||||
finishedAt: instantSchema.nullable(),
|
||||
},
|
||||
// One document per file: the job that creates it is retried, and a second row would be a second queue.
|
||||
unique: [["fileId"]],
|
||||
indexes: [["status"]],
|
||||
})
|
||||
|
||||
export const lines = defineEntity({
|
||||
name: "line",
|
||||
table: "documents_line",
|
||||
tenancy: "project",
|
||||
fields: {
|
||||
documentId: idSchema,
|
||||
/** The approved proposal this line came from: its provenance, and the reason a line is written once. */
|
||||
proposalId: idSchema,
|
||||
label: z.string().min(1).max(200),
|
||||
value: z.string().min(1).max(2_000),
|
||||
/** 1-based page of the source document. */
|
||||
page: z.number().int().min(1),
|
||||
/** Reading order within the document: the export's order, which a creation time cannot give. */
|
||||
position: z.number().int().min(0),
|
||||
/** The words the value was read from, verbatim. */
|
||||
quote: z.string().min(1).max(2_000),
|
||||
/** True when a reviewer changed the label or value before it was approved. */
|
||||
edited: z.boolean(),
|
||||
approvedBy: z.string().min(1).max(128),
|
||||
},
|
||||
unique: [["proposalId"]],
|
||||
indexes: [["documentId"]],
|
||||
})
|
||||
|
||||
/** Every table this module owns, in the order a migration creates them. */
|
||||
export const DOCUMENTS_ENTITIES = Object.freeze([documents, lines])
|
||||
Reference in New Issue
Block a user