first commit
This commit is contained in:
52
api/src/entities/AppSetting.ts
Normal file
52
api/src/entities/AppSetting.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('app_settings')
|
||||
export class AppSetting {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 120, default: 'Expense Control' })
|
||||
appName!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 8, default: 'PLN' })
|
||||
defaultCurrency!: string;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
registrationEnabled!: boolean;
|
||||
|
||||
@Column({ type: 'simple-json' })
|
||||
allowedProofTypes!: string[];
|
||||
|
||||
@Column({ type: 'simple-json' })
|
||||
uiPreferences!: Record<string, string | number | boolean>;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
smtpEnabled!: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 120, nullable: true })
|
||||
smtpHost!: string | null;
|
||||
|
||||
@Column({ type: 'int', default: 587 })
|
||||
smtpPort!: number;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
smtpSecure!: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 160, nullable: true })
|
||||
smtpUser!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
smtpPassword!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 120, nullable: true })
|
||||
smtpFromName!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 160, nullable: true })
|
||||
smtpFromEmail!: string | null;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'datetime' })
|
||||
updatedAt!: Date;
|
||||
}
|
||||
27
api/src/entities/Category.ts
Normal file
27
api/src/entities/Category.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Expense } from './Expense.js';
|
||||
import { User } from './User.js';
|
||||
|
||||
@Entity('categories')
|
||||
export class Category {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 80 })
|
||||
name!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 32, default: '#0d6efd' })
|
||||
color!: string;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isSystem!: boolean;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.categories, { nullable: true, onDelete: 'CASCADE' })
|
||||
user!: User | null;
|
||||
|
||||
@OneToMany(() => Expense, (expense) => expense.category)
|
||||
expenses!: Expense[];
|
||||
}
|
||||
50
api/src/entities/Expense.ts
Normal file
50
api/src/entities/Expense.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { Category } from './Category.js';
|
||||
import { Proof } from './Proof.js';
|
||||
import { User } from './User.js';
|
||||
import { decimalTransformer } from '../utils/decimal.js';
|
||||
|
||||
@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: 'boolean', default: false })
|
||||
possibleDuplicate!: boolean;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'datetime' })
|
||||
updatedAt!: Date;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.expenses, { onDelete: 'CASCADE' })
|
||||
user!: User;
|
||||
|
||||
@ManyToOne(() => Category, (category) => category.expenses, { eager: true, onDelete: 'RESTRICT' })
|
||||
category!: Category;
|
||||
|
||||
@OneToMany(() => Proof, (proof) => proof.expense, { eager: true, cascade: true })
|
||||
proofs!: Proof[];
|
||||
}
|
||||
29
api/src/entities/Merchant.ts
Normal file
29
api/src/entities/Merchant.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { User } from './User.js';
|
||||
|
||||
@Entity('merchants')
|
||||
export class Merchant {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 120 })
|
||||
name!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 30, default: 'MERCHANT' })
|
||||
kind!: 'MERCHANT' | 'SERVICE_PROVIDER' | 'OTHER';
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes!: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
isActive!: boolean;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'datetime' })
|
||||
updatedAt!: Date;
|
||||
|
||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||
user!: User;
|
||||
}
|
||||
37
api/src/entities/Proof.ts
Normal file
37
api/src/entities/Proof.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Expense } from './Expense.js';
|
||||
|
||||
export type ProofType = 'RECEIPT' | 'INVOICE' | 'NOTE' | 'BANK_STATEMENT' | 'OTHER';
|
||||
|
||||
@Entity('proofs')
|
||||
export class Proof {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 30, default: 'OTHER' })
|
||||
type!: ProofType;
|
||||
|
||||
@Column({ type: 'varchar', length: 150, nullable: true })
|
||||
label!: string | null;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
note!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
originalName!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 255, nullable: true })
|
||||
storedName!: string | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 120, nullable: true })
|
||||
mimeType!: string | null;
|
||||
|
||||
@Column({ type: 'int', nullable: true })
|
||||
fileSize!: number | null;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@ManyToOne(() => Expense, (expense) => expense.proofs, { onDelete: 'CASCADE' })
|
||||
expense!: Expense;
|
||||
}
|
||||
47
api/src/entities/User.ts
Normal file
47
api/src/entities/User.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Category } from './Category.js';
|
||||
import { Expense } from './Expense.js';
|
||||
|
||||
export type UserRole = 'ADMIN' | 'USER';
|
||||
|
||||
@Entity('users')
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 120 })
|
||||
fullName!: string;
|
||||
|
||||
@Column({ type: 'varchar', unique: true, length: 160 })
|
||||
email!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 255 })
|
||||
passwordHash!: string;
|
||||
|
||||
@Column({ type: 'varchar', length: 20, default: 'USER' })
|
||||
role!: UserRole;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
isActive!: boolean;
|
||||
|
||||
@Column({ type: 'varchar', length: 8, default: 'PLN' })
|
||||
defaultCurrency!: string;
|
||||
|
||||
@Column({ type: 'simple-json', nullable: true })
|
||||
reportPreferences!: {
|
||||
enabled?: boolean;
|
||||
frequency?: 'monthly' | 'yearly' | 'threshold';
|
||||
thresholdAmount?: number;
|
||||
sendToEmail?: string | null;
|
||||
categoryIds?: string[];
|
||||
} | null;
|
||||
|
||||
@CreateDateColumn({ type: 'datetime' })
|
||||
createdAt!: Date;
|
||||
|
||||
@OneToMany(() => Category, (category) => category.user)
|
||||
categories!: Category[];
|
||||
|
||||
@OneToMany(() => Expense, (expense) => expense.user)
|
||||
expenses!: Expense[];
|
||||
}
|
||||
Reference in New Issue
Block a user