import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; import type { Relation } from 'typeorm'; import { Category } from './Category.js'; import { Proof } from './Proof.js'; import { User } from './User.js'; import { decimalTransformer } from '../utils/decimal.js'; import { dateTimeColumnType } from '../utils/db-column-types.js'; export type ExpenseStatus = 'DRAFT' | 'PENDING' | 'APPROVED' | 'REJECTED'; export type DuplicateReviewStatus = 'OPEN' | 'CONFIRMED' | 'DISMISSED'; @Entity('expenses') export class Expense { @PrimaryGeneratedColumn('uuid') id!: string; @Column({ type: 'varchar', length: 140 }) title!: string; @Column({ type: 'text', nullable: true }) description!: string | null; @Column({ type: 'decimal', precision: 12, scale: 2, transformer: decimalTransformer }) amount!: number; @Column({ type: 'date' }) expenseDate!: string; @Column({ type: 'varchar', length: 80, nullable: true }) merchant!: string | null; @Column({ type: 'varchar', length: 50, nullable: true }) paymentMethod!: string | null; @Column({ type: 'varchar', length: 12, default: 'PLN' }) currency!: string; @Column({ type: 'varchar', length: 20, default: 'PENDING' }) status!: ExpenseStatus; @Column({ type: 'simple-json', nullable: true }) tags!: string[] | null; @Column({ type: 'simple-json', nullable: true }) customFields!: Record | null; @Column({ type: 'boolean', default: false }) possibleDuplicate!: boolean; @Column({ type: 'varchar', length: 20, nullable: true }) duplicateStatus!: DuplicateReviewStatus | null; @Column({ type: dateTimeColumnType, nullable: true }) duplicateReviewedAt!: Date | null; @Column({ type: 'varchar', length: 36, nullable: true }) recurringSourceId!: string | null; @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; @ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' }) user!: Relation; @ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' }) category!: Relation; @OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true }) proofs!: Relation; }