- Description
- Technologies
- Database Schema Documentation
- API Documentation
- Installation
- Running the app
A web application for tracking daily spending to help users manage their finances more efficiently.
The main functions are:
- User registration and authentication.
- Enter incomings and expenses with additional information about them.
- View transactions history with filters.
- Expense analytics with the ability to filter data to obtain insights about financial behavior.
Fraimwork: Nest.js
API Query Language: GraphQL
Database: PostgreSQL
ORM: TypeORM
Description: Stores information about users who are registered in the Expense Tracker application.
Field | Type | Description |
---|---|---|
id | UUID | Primary key, unique identifier for each user. |
VARCHAR(255) | User's email address, used for logging in. | |
password_hash | VARCHAR(255) | Hashed password for user's account security. |
name | VARCHAR(50) | User's full name (optional). |
created_at | TIMESTAMP | The date and time when the account was created. |
updated_at | TIMESTAMP | The date and time of the last account update. |
Description: Records financial transactions made by users.
Field | Type | Description |
---|---|---|
id | UUID | Primary key, unique identifier for each transaction. |
user_id | UUID | Foreign key linking to the Users table. |
amount | DECIMAL | The monetary value of the transaction. |
type | transaction_type | The type of transaction, defined as an ENUM |
category_id | UUID | The category of the transaction (e.g., "Food", "Rent"). |
description | TEXT | A description of the transaction. |
date | TIMESTAMP | The date and time when the transaction occurred. |
created_at | TIMESTAMP | The date and time when the transaction was recorded. |
updated_at | TIMESTAMP | The date and time when the transaction record was updated. |
transaction_type ENUM:
- Description: Represents the types of transactions.
- Values:
income
: Represents an incoming transaction.expense
: Represents an outgoing transaction.
Description: Contains predefined categories that can be used to classify transactions as well as custom categories created by users.
Field | Type | Description |
---|---|---|
id | UUID | Primary key, unique identifier for each category. |
name | VARCHAR(50) | The name of the category. |
description | TEXT | A brief description of the category (optional). |
user_id | UUID | Foreign key linking to the Users table (optional). Identifies the user who created the category. |
Transactions to Categories: Many-to-One. Each transaction can be assigned to one category, making it easier to classify and analyze expenses. This would require adding a category_id
field to the Transactions
table to establish a foreign key relationship with the Categories
table.
Users to Transactions: One-to-Many. A single user can have multiple transactions, but each transaction is associated with one user. This relationship is established through the user_id
field in the Transactions
table, which acts as a foreign key to the Users
table.
Users to Categories: One-to-Many. A single user can have multiple custom categories, but category is associated with one user (default category isn't associated with any user). This relationship is established through the user_id
field in the Categories
table, which acts as a foreign key to the Users
table.
Endpoint: /graphql
Method: POST
Headers:
Content-Type: application/json
Authorization: Bearer <token>
(for protected routes)
Allows a new user to register an account by providing their email, password and name. Upon successful registration, returns the user's ID, email and name.
mutation RegisterUser {
registerUser(registerUserInput: { email: "user@example.com", password: "password123", name: "John Doe" }) {
id
email
name
}
}
Authenticates a user with their email and password. Upon successful authentication, returns an access token that can be used for authenticated requests to the API.
mutation AuthenticateUser {
loginUser(loginUserInput: { email: "user@example.com", password: "password123" }) {
access_token
refresh_token
}
}
Allows a user to refresh their access token using a refresh token. Upon successful token refresh, returns a new access token.
Protected route.
mutation RefreshAccessToken {
refreshToken(refreshTokenInput: { refresh_token: "your_refresh_token_here" }) {
access_token
}
}
Allows a user to update the details of own profile (email and/or name).
Protected route.
mutation UpdateUserProfile {
updateUserProfile(
updateUserInput: {
name: "John Doe",
email: "user@example.com"
}
) {
name
email
}
}
Allows a user to change password.
Protected route.
mutation ChangeUserPassword {
changeUserPassword(
changeUserPasswordInput: {
oldPassword: "password123",
newPassword: "password111"
}
) {
success
}
}
Allows a user to add a new transaction. The user must provide the amount
, type
(as an ENUM of either 'income' or 'expense'), category
(with ID
and name
), description
and the date
of the transaction.
Protected route.
mutation AddTransaction {
createTransaction(createTransactionInput: {
amount: 50.00,
type: INCOME,
categoryId: "uuid-of-the-category",
description: "Freelance payment",
date: "2024-02-16T12:00:00Z"
}) {
id
amount
type
category {
id
name
}
description
date
}
}
Retrieves a list of transactions for a user. The query can be filtered by various criteria (next query). By default, it returns all transactions associated with the user's account.
Protected route.
query GetUserTransactions {
getUserTransactions {
id
amount
type
category {
id
name
}
description
date
}
}
Users can filter the transactions by date range (startDate
and/or endDate
), category
, or type
. This query returns all transactions associated with the user's account that match the given filters.
Protected route.
query GetUserTransactions {
getUserTransactions(
filters: {
startDate: "2024-01-01",
endDate: "2024-01-31",
categoryId: "uuid-of-the-category",
type: EXPENSE
}
) {
id
amount
type
category {
id
name
}
description
date
}
}
Allows a user to update the details of an existing transaction. The user can modify fields such as amount
, type
, categoryId
, description
, and date
. The id
of the transaction must be provided to specify which transaction is to be updated.
Protected route.
mutation UpdateTransaction {
updateTransaction(
id: "uuid-of-the-transaction",
updateTransactionInput: {
amount: 15.99,
type: EXPENSE,
categoryId: "uuid-of-the-category",
description: "Updated lunch",
date: "2024-02-16T12:00:00Z"
}
) {
id
amount
type
category {
id
name
}
description
date
}
}
Allows a user to delete an existing own transaction. The user must provide the transaction ID.
Protected route.
mutation DeleteTransaction {
deleteTransaction(
id: "uuid-of-the-category"
) {
success
}
}
Retrieves financial analytics for a user over a specified date range (startDate
and endDate
). This could include total income, total expenses, and a breakdown by categories.
Protected route.
query GetUserFinancialAnalytics {
financialAnalytics(
startDate: "2024-01-01",
endDate: "2024-01-31"
) {
totalIncome
totalExpenses
byCategory {
categoryId
categoryName
totalAmount
}
}
}
Allows a user to create a new custom category. The user must provide the name
of the category, and optionally a description
.
Protected route.
mutation AddCategory {
createCategory(createCategoryInput: {
name: "New Category",
description: "Description of the new category"
}) {
id
name
description
}
}
Retrieves a list of available categories (custom and default) for the user.
Protected route.
query GetUserCategories {
getUserCategories {
id
name
description
user {
id
}
}
}
Allows a user to update the details of an existing own custom category. The user must provide the category ID and can update the name and/or description.
Protected route.
mutation UpdateCategory {
updateCategory(
id: "uuid-of-the-category",
updateCategoryInput: {
name: "Updated Category Name",
description: "Updated description of the category"
}
) {
id
name
description
}
}
Allows a user to delete an existing own custom category. The user must provide the category ID.
Protected route.
mutation DeleteCategory {
deleteCategory(
id: "uuid-of-the-category"
) {
success
}
}
# installation of dependences
$ npm install
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prod