import { type CommonReservedFields, type NoReservedFields, defaultGqlPermission, defaultPermission, } from "@tailor-platform/erp-kit/core"; import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk"; import { accountPayableDocumentLifecycle } from "./accountPayableDocument.lifecycle.generated"; export const ACCOUNT_PAYABLE_DOCUMENT_TYPES = ["INVOICE", "CREDIT_MEMO"] as const; const builtins = (params: { companyType?: TailorAnyDBType; supplierAccountType?: TailorAnyDBType; currencyType?: TailorAnyDBType; accountType?: TailorAnyDBType; }) => { const companyId = db.uuid().description("Foreign key to Company"); const supplierAccountId = db.uuid().description("Foreign key to SupplierAccount"); const currencyId = db.uuid().description("Foreign key to transaction Currency"); const payableControlAccountId = db .uuid() .description("Foreign key to the AP payable control Account"); return { companyId: params.companyType ? companyId.relation({ type: "n-1", toward: { type: params.companyType, as: "company" }, backward: "accountPayableDocuments", }) : companyId, supplierAccountId: params.supplierAccountType ? supplierAccountId.relation({ type: "n-1", toward: { type: params.supplierAccountType, as: "supplierAccount" }, backward: "accountPayableDocuments", }) : supplierAccountId, currencyId: params.currencyType ? currencyId.relation({ type: "n-1", toward: { type: params.currencyType, as: "currency" }, backward: "accountPayableDocuments", }) : currencyId, payableControlAccountId: params.accountType ? payableControlAccountId.relation({ type: "n-1", toward: { type: params.accountType, as: "payableControlAccount" }, backward: "accountPayableDocuments", }) : payableControlAccountId, documentType: db.enum(ACCOUNT_PAYABLE_DOCUMENT_TYPES).description("AP document type"), correctionOfId: db .uuid({ optional: true }) .relation({ type: "n-1", toward: { type: "self" }, backward: "correctionDocuments", }) .description("Optional self-reference to the posted AP document being corrected"), documentNumber: db .string() .index() .unique() .serial({ start: 1, maxValue: 99999999, format: "AP-%08d", }) .description("System-generated AP document number"), externalDocumentNumber: db .string({ optional: true }) .description("Optional external document number from the business partner"), documentDate: db.date().description("AP document date"), postingDate: db.date().description("Accounting posting date"), totalAmount: db.decimal().description("Total AP document amount in transaction currency"), description: db.string({ optional: true }).description("Optional AP document description"), status: db .enum(accountPayableDocumentLifecycle.states) .description("AP document lifecycle status"), registeredAt: db.datetime({ optional: true }).description("Timestamp when registered"), postedAt: db.datetime({ optional: true }).description("Timestamp when posted"), cancelledAt: db.datetime({ optional: true }).description("Timestamp when cancelled"), }; }; type ReservedFields = keyof ReturnType | CommonReservedFields; export interface CreateAccountPayableDocumentTypeParams< F extends Record, > { fields?: NoReservedFields; companyType?: TailorAnyDBType; supplierAccountType?: TailorAnyDBType; currencyType?: TailorAnyDBType; accountType?: TailorAnyDBType; } export function createAccountPayableDocumentType>( params: CreateAccountPayableDocumentTypeParams, ) { return db .table("AccountPayableDocument", { ...builtins(params), ...((params.fields ?? {}) as F), ...db.fields.timestamps(), }) .permission(defaultPermission) .gqlPermission(defaultGqlPermission); } export const accountPayableDocument = createAccountPayableDocumentType({});