From 723e3441df47c996cfb82a6e19e2d4bfc9d5f83d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Mon, 6 Apr 2026 16:29:58 +0200 Subject: [PATCH] fix admn controller --- api/src/controllers/admin.controller.ts | 15 +++------------ api/src/entities/AppSetting.ts | 5 +++-- api/src/entities/Budget.ts | 10 +++++----- api/src/entities/Category.ts | 8 ++++---- api/src/entities/Expense.ts | 14 +++++++------- api/src/entities/Merchant.ts | 8 ++++---- api/src/entities/Proof.ts | 6 +++--- api/src/entities/RecurringExpense.ts | 10 +++++----- api/src/entities/User.ts | 8 ++++---- api/src/utils/db-column-types.ts | 5 +++++ 10 files changed, 43 insertions(+), 46 deletions(-) create mode 100644 api/src/utils/db-column-types.ts diff --git a/api/src/controllers/admin.controller.ts b/api/src/controllers/admin.controller.ts index 916024f..154801e 100644 --- a/api/src/controllers/admin.controller.ts +++ b/api/src/controllers/admin.controller.ts @@ -1,5 +1,4 @@ import type { Response } from 'express'; -import { createRequire } from 'node:module'; import fs from 'node:fs'; import path from 'node:path'; import process from 'node:process'; @@ -41,14 +40,11 @@ const userUpdateSchema = z.object({ type PackageJson = { version?: string }; -const require = createRequire(import.meta.url); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const readPackageJsonSafe = (filePath: string | null): PackageJson | null => { - if (!filePath || !fs.existsSync(filePath)) { - return null; - } + if (!filePath || !fs.existsSync(filePath)) return null; try { return JSON.parse(fs.readFileSync(filePath, 'utf8')) as PackageJson; @@ -62,15 +58,10 @@ const findNearestPackageJson = (startDir: string): string | null => { while (true) { const candidate = path.join(currentDir, 'package.json'); - if (fs.existsSync(candidate)) { - return candidate; - } + if (fs.existsSync(candidate)) return candidate; const parentDir = path.dirname(currentDir); - if (parentDir === currentDir) { - return null; - } - + if (parentDir == currentDir) return null; currentDir = parentDir; } }; diff --git a/api/src/entities/AppSetting.ts b/api/src/entities/AppSetting.ts index 6220b08..ae8bde5 100644 --- a/api/src/entities/AppSetting.ts +++ b/api/src/entities/AppSetting.ts @@ -1,4 +1,5 @@ import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; @Entity('app_settings') export class AppSetting { @@ -44,9 +45,9 @@ export class AppSetting { @Column({ type: 'varchar', length: 160, nullable: true }) smtpFromEmail!: string | null; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; - @UpdateDateColumn({ type: 'datetime' }) + @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; } diff --git a/api/src/entities/Budget.ts b/api/src/entities/Budget.ts index bdc423d..1634b9c 100644 --- a/api/src/entities/Budget.ts +++ b/api/src/entities/Budget.ts @@ -1,8 +1,8 @@ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { Category } from './Category.js'; import { User } from './User.js'; import { decimalTransformer } from '../utils/decimal.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; @Entity('budgets') export class Budget { @@ -24,15 +24,15 @@ export class Budget { @Column({ type: 'boolean', default: true }) isActive!: boolean; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; - @UpdateDateColumn({ type: 'datetime' }) + @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; @ManyToOne(() => User, { onDelete: 'CASCADE' }) - user!: Relation; + user!: User; @ManyToOne(() => Category, { eager: true, nullable: true, onDelete: 'SET NULL' }) - category!: Relation | null; + category!: Category | null; } diff --git a/api/src/entities/Category.ts b/api/src/entities/Category.ts index affb05c..7160f9a 100644 --- a/api/src/entities/Category.ts +++ b/api/src/entities/Category.ts @@ -1,7 +1,7 @@ import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { Expense } from './Expense.js'; import { User } from './User.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; @Entity('categories') export class Category { @@ -17,12 +17,12 @@ export class Category { @Column({ type: 'boolean', default: false }) isSystem!: boolean; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; @ManyToOne(() => User, (user) => user.categories, { nullable: true, onDelete: 'CASCADE' }) - user!: Relation | null; + user!: User | null; @OneToMany(() => Expense, (expense) => expense.category) - expenses!: Relation; + expenses!: Expense[]; } diff --git a/api/src/entities/Expense.ts b/api/src/entities/Expense.ts index d1af108..23c856a 100644 --- a/api/src/entities/Expense.ts +++ b/api/src/entities/Expense.ts @@ -1,9 +1,9 @@ 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'; @@ -49,24 +49,24 @@ export class Expense { @Column({ type: 'varchar', length: 20, nullable: true }) duplicateStatus!: DuplicateReviewStatus | null; - @Column({ type: 'datetime', nullable: true }) + @Column({ type: dateTimeColumnType, nullable: true }) duplicateReviewedAt!: Date | null; @Column({ type: 'varchar', length: 36, nullable: true }) recurringSourceId!: string | null; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; - @UpdateDateColumn({ type: 'datetime' }) + @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; @ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' }) - user!: Relation; + user!: User; @ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' }) - category!: Relation; + category!: Category; @OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true }) - proofs!: Relation; + proofs!: Proof[]; } diff --git a/api/src/entities/Merchant.ts b/api/src/entities/Merchant.ts index 47963f3..7714940 100644 --- a/api/src/entities/Merchant.ts +++ b/api/src/entities/Merchant.ts @@ -1,6 +1,6 @@ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { User } from './User.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; @Entity('merchants') export class Merchant { @@ -19,12 +19,12 @@ export class Merchant { @Column({ type: 'boolean', default: true }) isActive!: boolean; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; - @UpdateDateColumn({ type: 'datetime' }) + @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; @ManyToOne(() => User, { onDelete: 'CASCADE' }) - user!: Relation; + user!: User; } diff --git a/api/src/entities/Proof.ts b/api/src/entities/Proof.ts index daa8366..6d36398 100644 --- a/api/src/entities/Proof.ts +++ b/api/src/entities/Proof.ts @@ -1,6 +1,6 @@ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { Expense } from './Expense.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; export type ProofType = 'RECEIPT' | 'INVOICE' | 'NOTE' | 'BANK_STATEMENT' | 'OTHER'; @@ -30,9 +30,9 @@ export class Proof { @Column({ type: 'int', nullable: true }) fileSize!: number | null; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; @ManyToOne(() => Expense, (expense) => expense.proofs, { onDelete: 'CASCADE' }) - expense!: Relation; + expense!: Expense; } diff --git a/api/src/entities/RecurringExpense.ts b/api/src/entities/RecurringExpense.ts index e5e5567..6aef3c2 100644 --- a/api/src/entities/RecurringExpense.ts +++ b/api/src/entities/RecurringExpense.ts @@ -1,8 +1,8 @@ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { Category } from './Category.js'; import { User } from './User.js'; import { decimalTransformer } from '../utils/decimal.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; export type RecurringFrequency = 'WEEKLY' | 'MONTHLY' | 'YEARLY'; @@ -65,15 +65,15 @@ export class RecurringExpense { @Column({ type: 'boolean', default: true }) isActive!: boolean; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; - @UpdateDateColumn({ type: 'datetime' }) + @UpdateDateColumn({ type: dateTimeColumnType }) updatedAt!: Date; @ManyToOne(() => User, { onDelete: 'CASCADE' }) - user!: Relation; + user!: User; @ManyToOne(() => Category, { eager: true, onDelete: 'RESTRICT' }) - category!: Relation; + category!: Category; } diff --git a/api/src/entities/User.ts b/api/src/entities/User.ts index ff1ffba..f48d327 100644 --- a/api/src/entities/User.ts +++ b/api/src/entities/User.ts @@ -1,7 +1,7 @@ import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; -import type { Relation } from 'typeorm'; import { Category } from './Category.js'; import { Expense } from './Expense.js'; +import { dateTimeColumnType } from '../utils/db-column-types.js'; export type UserRole = 'ADMIN' | 'USER'; @@ -47,12 +47,12 @@ export class User { defaultListId?: string | null; } | null; - @CreateDateColumn({ type: 'datetime' }) + @CreateDateColumn({ type: dateTimeColumnType }) createdAt!: Date; @OneToMany(() => Category, (category) => category.user) - categories!: Relation; + categories!: Category[]; @OneToMany(() => Expense, (expense) => expense.user) - expenses!: Relation; + expenses!: Expense[]; } diff --git a/api/src/utils/db-column-types.ts b/api/src/utils/db-column-types.ts new file mode 100644 index 0000000..eb67ec2 --- /dev/null +++ b/api/src/utils/db-column-types.ts @@ -0,0 +1,5 @@ +import type { ColumnType } from 'typeorm'; + +const dbType = (process.env.DB_TYPE ?? 'sqlite').toLowerCase(); + +export const dateTimeColumnType: ColumnType = dbType === 'postgres' ? 'timestamp' : 'datetime';