import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; import { accountingPeriod } from "./accountingPeriod"; import { journalEntryLifecycle } from "./journalEntry.lifecycle.generated"; export const JOURNAL_ENTRY_SOURCE_DOCUMENT_TYPES = [ "ACCOUNT_PAYABLE_DOCUMENT", "OUTGOING_PAYMENT", "INCOMING_PAYMENT", "BANK_RECONCILIATION", "SALES_INVOICE", "INVENTORY_LEDGER", "STANDARD_COST_REVISION", "ACQUISITION_COST_ADJUSTMENT", "PRODUCTION_ORDER", "YEAR_END_CLOSE", ] as const; const builtins = (params: { companyType?: TailorAnyDBType }) => { const companyId = db.uuid().description("Foreign key to Company"); return { companyId: params.companyType ? companyId.relation({ type: "n-1", toward: { type: params.companyType, as: "company" }, backward: "journalEntries", }) : companyId, accountingPeriodId: db .uuid() .relation({ type: "n-1", toward: { type: accountingPeriod, as: "accountingPeriod" }, backward: "journalEntries", }) .description("Foreign key to AccountingPeriod"), entryDate: db.date().description("Journal entry document date"), status: db .enum(journalEntryLifecycle.states) .description("Journal entry lifecycle status (DRAFT, CANCELLED, POSTED)"), description: db .string({ optional: true }) .description("Optional description of the journal entry"), sourceDocumentType: db .enum(JOURNAL_ENTRY_SOURCE_DOCUMENT_TYPES, { optional: true }) .description("Optional source document type that produced the accounting entry"), sourceDocumentId: db .uuid({ optional: true }) .description("Optional source document ID. Generic reference, not a typed foreign key."), reversalOfId: db .uuid({ optional: true }) .relation({ type: "1-1", toward: { type: "self" }, backward: "reversals", }) .description("Optional self-referencing FK to the original JournalEntry being reversed"), postedAt: db.datetime({ optional: true }).description("Timestamp when the entry was posted"), }; }; type ReservedFields = keyof ReturnType | CommonReservedFields; export interface CreateJournalEntryTypeParams> { fields?: NoReservedFields; companyType?: TailorAnyDBType; } export function createJournalEntryType>( params: CreateJournalEntryTypeParams, ) { return db .table("JournalEntry", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .indexes({ fields: ["sourceDocumentType", "sourceDocumentId", "reversalOfId"], unique: false, name: "journal_entry_source_reversal_idx", }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const journalEntry = createJournalEntryType({});