Initial commit: Buildfor Life Budget app
Multi-company budget/project tracking tool built with SvelteKit 5, PostgreSQL (Drizzle ORM), and Tailwind CSS v4. Features: - Auth: local (email/password with Argon2) + generic OIDC - 4 roles per company: admin, manager, user, viewer - Multi-company with per-company user membership - Projects with budget allocation from company pool - Expense submission with approval workflow - Categories and tags for expense organization - Reports with spending breakdowns (by category, project, time) - CSV import for Actual Budget migration - Company audit log tracking all budget and admin actions - Remaining budget hero display on overview and budget pages - Admin-only company creation; new users wait for invitation - Deployment configs for systemd + nginx (bare metal/Proxmox) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { relations } from 'drizzle-orm';
|
||||
import { users } from './users.js';
|
||||
import { sessions } from './sessions.js';
|
||||
import { companies } from './companies.js';
|
||||
import { companyMembers } from './company-members.js';
|
||||
import { projects } from './projects.js';
|
||||
import { categories } from './categories.js';
|
||||
import { expenses } from './expenses.js';
|
||||
import { tags, expenseTags } from './tags.js';
|
||||
import { budgetAllocations } from './budget-allocations.js';
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
sessions: many(sessions),
|
||||
companyMemberships: many(companyMembers),
|
||||
submittedExpenses: many(expenses, { relationName: 'submittedExpenses' }),
|
||||
approvedExpenses: many(expenses, { relationName: 'approvedExpenses' })
|
||||
}));
|
||||
|
||||
export const sessionsRelations = relations(sessions, ({ one }) => ({
|
||||
user: one(users, { fields: [sessions.userId], references: [users.id] })
|
||||
}));
|
||||
|
||||
export const companiesRelations = relations(companies, ({ many }) => ({
|
||||
members: many(companyMembers),
|
||||
projects: many(projects),
|
||||
categories: many(categories),
|
||||
tags: many(tags),
|
||||
budgetAllocations: many(budgetAllocations)
|
||||
}));
|
||||
|
||||
export const companyMembersRelations = relations(companyMembers, ({ one }) => ({
|
||||
user: one(users, { fields: [companyMembers.userId], references: [users.id] }),
|
||||
company: one(companies, { fields: [companyMembers.companyId], references: [companies.id] })
|
||||
}));
|
||||
|
||||
export const projectsRelations = relations(projects, ({ one, many }) => ({
|
||||
company: one(companies, { fields: [projects.companyId], references: [companies.id] }),
|
||||
expenses: many(expenses),
|
||||
budgetAllocations: many(budgetAllocations)
|
||||
}));
|
||||
|
||||
export const categoriesRelations = relations(categories, ({ one, many }) => ({
|
||||
company: one(companies, { fields: [categories.companyId], references: [companies.id] }),
|
||||
expenses: many(expenses)
|
||||
}));
|
||||
|
||||
export const expensesRelations = relations(expenses, ({ one, many }) => ({
|
||||
project: one(projects, { fields: [expenses.projectId], references: [projects.id] }),
|
||||
category: one(categories, { fields: [expenses.categoryId], references: [categories.id] }),
|
||||
submitter: one(users, {
|
||||
fields: [expenses.submittedBy],
|
||||
references: [users.id],
|
||||
relationName: 'submittedExpenses'
|
||||
}),
|
||||
approver: one(users, {
|
||||
fields: [expenses.approvedBy],
|
||||
references: [users.id],
|
||||
relationName: 'approvedExpenses'
|
||||
}),
|
||||
expenseTags: many(expenseTags)
|
||||
}));
|
||||
|
||||
export const tagsRelations = relations(tags, ({ one, many }) => ({
|
||||
company: one(companies, { fields: [tags.companyId], references: [companies.id] }),
|
||||
expenseTags: many(expenseTags)
|
||||
}));
|
||||
|
||||
export const expenseTagsRelations = relations(expenseTags, ({ one }) => ({
|
||||
expense: one(expenses, { fields: [expenseTags.expenseId], references: [expenses.id] }),
|
||||
tag: one(tags, { fields: [expenseTags.tagId], references: [tags.id] })
|
||||
}));
|
||||
|
||||
export const budgetAllocationsRelations = relations(budgetAllocations, ({ one }) => ({
|
||||
company: one(companies, {
|
||||
fields: [budgetAllocations.companyId],
|
||||
references: [companies.id]
|
||||
}),
|
||||
project: one(projects, {
|
||||
fields: [budgetAllocations.projectId],
|
||||
references: [projects.id]
|
||||
}),
|
||||
allocator: one(users, { fields: [budgetAllocations.allocatedBy], references: [users.id] })
|
||||
}));
|
||||
Reference in New Issue
Block a user