fix admn controller
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import type { Response } from 'express';
|
import type { Response } from 'express';
|
||||||
import { createRequire } from 'node:module';
|
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
@@ -41,14 +40,11 @@ const userUpdateSchema = z.object({
|
|||||||
|
|
||||||
type PackageJson = { version?: string };
|
type PackageJson = { version?: string };
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
const readPackageJsonSafe = (filePath: string | null): PackageJson | null => {
|
const readPackageJsonSafe = (filePath: string | null): PackageJson | null => {
|
||||||
if (!filePath || !fs.existsSync(filePath)) {
|
if (!filePath || !fs.existsSync(filePath)) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as PackageJson;
|
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as PackageJson;
|
||||||
@@ -62,15 +58,10 @@ const findNearestPackageJson = (startDir: string): string | null => {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const candidate = path.join(currentDir, 'package.json');
|
const candidate = path.join(currentDir, 'package.json');
|
||||||
if (fs.existsSync(candidate)) {
|
if (fs.existsSync(candidate)) return candidate;
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parentDir = path.dirname(currentDir);
|
const parentDir = path.dirname(currentDir);
|
||||||
if (parentDir === currentDir) {
|
if (parentDir == currentDir) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDir = parentDir;
|
currentDir = parentDir;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
@Entity('app_settings')
|
@Entity('app_settings')
|
||||||
export class AppSetting {
|
export class AppSetting {
|
||||||
@@ -44,9 +45,9 @@ export class AppSetting {
|
|||||||
@Column({ type: 'varchar', length: 160, nullable: true })
|
@Column({ type: 'varchar', length: 160, nullable: true })
|
||||||
smtpFromEmail!: string | null;
|
smtpFromEmail!: string | null;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'datetime' })
|
@UpdateDateColumn({ type: dateTimeColumnType })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Category } from './Category.js';
|
import { Category } from './Category.js';
|
||||||
import { User } from './User.js';
|
import { User } from './User.js';
|
||||||
import { decimalTransformer } from '../utils/decimal.js';
|
import { decimalTransformer } from '../utils/decimal.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
@Entity('budgets')
|
@Entity('budgets')
|
||||||
export class Budget {
|
export class Budget {
|
||||||
@@ -24,15 +24,15 @@ export class Budget {
|
|||||||
@Column({ type: 'boolean', default: true })
|
@Column({ type: 'boolean', default: true })
|
||||||
isActive!: boolean;
|
isActive!: boolean;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'datetime' })
|
@UpdateDateColumn({ type: dateTimeColumnType })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||||
user!: Relation<User>;
|
user!: User;
|
||||||
|
|
||||||
@ManyToOne(() => Category, { eager: true, nullable: true, onDelete: 'SET NULL' })
|
@ManyToOne(() => Category, { eager: true, nullable: true, onDelete: 'SET NULL' })
|
||||||
category!: Relation<Category> | null;
|
category!: Category | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Expense } from './Expense.js';
|
import { Expense } from './Expense.js';
|
||||||
import { User } from './User.js';
|
import { User } from './User.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
@Entity('categories')
|
@Entity('categories')
|
||||||
export class Category {
|
export class Category {
|
||||||
@@ -17,12 +17,12 @@ export class Category {
|
|||||||
@Column({ type: 'boolean', default: false })
|
@Column({ type: 'boolean', default: false })
|
||||||
isSystem!: boolean;
|
isSystem!: boolean;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.categories, { nullable: true, onDelete: 'CASCADE' })
|
@ManyToOne(() => User, (user) => user.categories, { nullable: true, onDelete: 'CASCADE' })
|
||||||
user!: Relation<User> | null;
|
user!: User | null;
|
||||||
|
|
||||||
@OneToMany(() => Expense, (expense) => expense.category)
|
@OneToMany(() => Expense, (expense) => expense.category)
|
||||||
expenses!: Relation<Expense[]>;
|
expenses!: Expense[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Category } from './Category.js';
|
import { Category } from './Category.js';
|
||||||
import { Proof } from './Proof.js';
|
import { Proof } from './Proof.js';
|
||||||
import { User } from './User.js';
|
import { User } from './User.js';
|
||||||
import { decimalTransformer } from '../utils/decimal.js';
|
import { decimalTransformer } from '../utils/decimal.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
export type ExpenseStatus = 'DRAFT' | 'PENDING' | 'APPROVED' | 'REJECTED';
|
export type ExpenseStatus = 'DRAFT' | 'PENDING' | 'APPROVED' | 'REJECTED';
|
||||||
export type DuplicateReviewStatus = 'OPEN' | 'CONFIRMED' | 'DISMISSED';
|
export type DuplicateReviewStatus = 'OPEN' | 'CONFIRMED' | 'DISMISSED';
|
||||||
@@ -49,24 +49,24 @@ export class Expense {
|
|||||||
@Column({ type: 'varchar', length: 20, nullable: true })
|
@Column({ type: 'varchar', length: 20, nullable: true })
|
||||||
duplicateStatus!: DuplicateReviewStatus | null;
|
duplicateStatus!: DuplicateReviewStatus | null;
|
||||||
|
|
||||||
@Column({ type: 'datetime', nullable: true })
|
@Column({ type: dateTimeColumnType, nullable: true })
|
||||||
duplicateReviewedAt!: Date | null;
|
duplicateReviewedAt!: Date | null;
|
||||||
|
|
||||||
@Column({ type: 'varchar', length: 36, nullable: true })
|
@Column({ type: 'varchar', length: 36, nullable: true })
|
||||||
recurringSourceId!: string | null;
|
recurringSourceId!: string | null;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'datetime' })
|
@UpdateDateColumn({ type: dateTimeColumnType })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' })
|
@ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' })
|
||||||
user!: Relation<User>;
|
user!: User;
|
||||||
|
|
||||||
@ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' })
|
@ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' })
|
||||||
category!: Relation<Category>;
|
category!: Category;
|
||||||
|
|
||||||
@OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true })
|
@OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true })
|
||||||
proofs!: Relation<Proof[]>;
|
proofs!: Proof[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { User } from './User.js';
|
import { User } from './User.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
@Entity('merchants')
|
@Entity('merchants')
|
||||||
export class Merchant {
|
export class Merchant {
|
||||||
@@ -19,12 +19,12 @@ export class Merchant {
|
|||||||
@Column({ type: 'boolean', default: true })
|
@Column({ type: 'boolean', default: true })
|
||||||
isActive!: boolean;
|
isActive!: boolean;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'datetime' })
|
@UpdateDateColumn({ type: dateTimeColumnType })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||||
user!: Relation<User>;
|
user!: User;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Expense } from './Expense.js';
|
import { Expense } from './Expense.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
export type ProofType = 'RECEIPT' | 'INVOICE' | 'NOTE' | 'BANK_STATEMENT' | 'OTHER';
|
export type ProofType = 'RECEIPT' | 'INVOICE' | 'NOTE' | 'BANK_STATEMENT' | 'OTHER';
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ export class Proof {
|
|||||||
@Column({ type: 'int', nullable: true })
|
@Column({ type: 'int', nullable: true })
|
||||||
fileSize!: number | null;
|
fileSize!: number | null;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => Expense, (expense) => expense.proofs, { onDelete: 'CASCADE' })
|
@ManyToOne(() => Expense, (expense) => expense.proofs, { onDelete: 'CASCADE' })
|
||||||
expense!: Relation<Expense>;
|
expense!: Expense;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Category } from './Category.js';
|
import { Category } from './Category.js';
|
||||||
import { User } from './User.js';
|
import { User } from './User.js';
|
||||||
import { decimalTransformer } from '../utils/decimal.js';
|
import { decimalTransformer } from '../utils/decimal.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
export type RecurringFrequency = 'WEEKLY' | 'MONTHLY' | 'YEARLY';
|
export type RecurringFrequency = 'WEEKLY' | 'MONTHLY' | 'YEARLY';
|
||||||
|
|
||||||
@@ -65,15 +65,15 @@ export class RecurringExpense {
|
|||||||
@Column({ type: 'boolean', default: true })
|
@Column({ type: 'boolean', default: true })
|
||||||
isActive!: boolean;
|
isActive!: boolean;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'datetime' })
|
@UpdateDateColumn({ type: dateTimeColumnType })
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
|
||||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||||
user!: Relation<User>;
|
user!: User;
|
||||||
|
|
||||||
@ManyToOne(() => Category, { eager: true, onDelete: 'RESTRICT' })
|
@ManyToOne(() => Category, { eager: true, onDelete: 'RESTRICT' })
|
||||||
category!: Relation<Category>;
|
category!: Category;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
import type { Relation } from 'typeorm';
|
|
||||||
import { Category } from './Category.js';
|
import { Category } from './Category.js';
|
||||||
import { Expense } from './Expense.js';
|
import { Expense } from './Expense.js';
|
||||||
|
import { dateTimeColumnType } from '../utils/db-column-types.js';
|
||||||
|
|
||||||
export type UserRole = 'ADMIN' | 'USER';
|
export type UserRole = 'ADMIN' | 'USER';
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ export class User {
|
|||||||
defaultListId?: string | null;
|
defaultListId?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'datetime' })
|
@CreateDateColumn({ type: dateTimeColumnType })
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@OneToMany(() => Category, (category) => category.user)
|
@OneToMany(() => Category, (category) => category.user)
|
||||||
categories!: Relation<Category[]>;
|
categories!: Category[];
|
||||||
|
|
||||||
@OneToMany(() => Expense, (expense) => expense.user)
|
@OneToMany(() => Expense, (expense) => expense.user)
|
||||||
expenses!: Relation<Expense[]>;
|
expenses!: Expense[];
|
||||||
}
|
}
|
||||||
|
|||||||
5
api/src/utils/db-column-types.ts
Normal file
5
api/src/utils/db-column-types.ts
Normal file
@@ -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';
|
||||||
Reference in New Issue
Block a user