Skip to content
100 changes: 98 additions & 2 deletions backend/src/controllers/CategoriesController.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { Get, Put, Route, Path, Security, Post, Body, Controller, Tags, Request, Example, Query } from 'tsoa'
import { Get, Put, Route, Path, Security, Post, Body, Controller, Tags, Request, Example, Query, Delete } from 'tsoa'
import { Budget } from '../entities/Budget'
import { ExpressRequest } from './requests'
import { ErrorResponse } from './responses'
import { CategoryGroup } from '../entities/CategoryGroup'
import { CategoryGroupRequest, CategoryGroupResponse, CategoryGroupsResponse } from '../models/CategoryGroup'
import { CategoryResponse } from '../models/Category'
import {
CategoryResponse,
DeleteCategoryModel,
DeleteCategoryRequest,
DeleteCategoryResponse,
} from '../models/Category'
import { CategoryRequest } from '../models/Category'
import { Category } from '../entities/Category'
import { CategoryMonthRequest, CategoryMonthResponse, CategoryMonthsResponse } from '../models/CategoryMonth'
import { CategoryMonth } from '../entities/CategoryMonth'
import { getCustomRepository, getRepository, MoreThanOrEqual } from 'typeorm'
import { CategoryMonths } from '../repositories/CategoryMonths'
import { Transaction } from '../entities/Transaction'

@Tags('Categories')
@Route('budgets/{budgetId}/categories')
Expand Down Expand Up @@ -193,6 +199,7 @@ export class CategoriesController extends Controller {
inflow: false,
locked: false,
order: 0,
hidden: false,
created: new Date('2011-10-05T14:48:00.000Z'),
updated: new Date('2011-10-05T14:48:00.000Z'),
},
Expand Down Expand Up @@ -245,6 +252,7 @@ export class CategoriesController extends Controller {
inflow: false,
locked: false,
order: 0,
hidden: false,
created: new Date('2011-10-05T14:48:00.000Z'),
updated: new Date('2011-10-05T14:48:00.000Z'),
},
Expand Down Expand Up @@ -272,6 +280,10 @@ export class CategoriesController extends Controller {

category.name = requestBody.name
category.order = requestBody.order
if (requestBody.hidden !== undefined) {
category.hidden = requestBody.hidden
}

delete category.categoryGroup
category.categoryGroupId = requestBody.categoryGroupId

Expand Down Expand Up @@ -299,6 +311,90 @@ export class CategoriesController extends Controller {
}
}

/**
* Deete a category
*/
@Security('jwtRequired')
@Delete('{id}')
@Example<CategoryResponse>({
message: 'success',
data: {
id: 'abc123',
categoryGroupId: 'def456',
trackingAccountId: null,
name: 'Expenses',
inflow: false,
locked: false,
order: 0,
hidden: false,
created: new Date('2011-10-05T14:48:00.000Z'),
updated: new Date('2011-10-05T14:48:00.000Z'),
},
})
public async deleteCategory(
@Path() budgetId: string,
@Path() id: string,
@Body() requestBody: DeleteCategoryRequest,
@Request() request: ExpressRequest,
): Promise<DeleteCategoryResponse | ErrorResponse> {
try {
const budget = await getRepository(Budget).findOne(budgetId)
if (!budget || budget.userId !== request.user.id) {
this.setStatus(404)
return {
message: 'Not found',
}
}

const response: DeleteCategoryModel = {
transactions: [],
categoryMonths: [],
}

const category = await getRepository(Category).findOne(id, { relations: ['transactions', 'categoryMonths'] })

// First, transfer all existing transactions to the new category
for (const transaction of category.transactions) {
transaction.update({
categoryId: requestBody.newCategoryId,
})
await getRepository(Transaction).update(transaction.id, transaction.getUpdatePayload())

response.transactions.push(transaction)
}

// Next, update all category months for budgeted items to the new category
for (const categoryMonth of category.categoryMonths) {
const newCategoryMonth = await getCustomRepository(CategoryMonths).findOrCreate(
budgetId,
requestBody.newCategoryId,
categoryMonth.month,
)

newCategoryMonth.update({ budgeted: newCategoryMonth.budgeted + categoryMonth.budgeted })
await getRepository(CategoryMonth).update(newCategoryMonth.id, newCategoryMonth.getUpdatePayload())

response.categoryMonths.push(newCategoryMonth)
}

// Delete old category months now
for (const categoryMonth of category.categoryMonths) {
await getRepository(CategoryMonth).remove(categoryMonth)
}

// Finally, delete the category
await getRepository(Category).remove(category)

return {
message: 'success',
data: response,
}
} catch (err) {
console.log(err)
return { message: err.message }
}
}

/**
* Update category month
*/
Expand Down
5 changes: 5 additions & 0 deletions backend/src/entities/Category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export class Category {
@Column({ type: 'int', default: 0 })
order: number = 0

@Column({ type: 'boolean', default: false })
hidden: boolean

@CreateDateColumn()
created: Date

Expand Down Expand Up @@ -73,6 +76,7 @@ export class Category {
inflow: this.inflow,
locked: this.locked,
order: this.order,
hidden: this.hidden,
}
}

Expand All @@ -85,6 +89,7 @@ export class Category {
inflow: this.inflow,
locked: this.locked,
order: this.order,
hidden: this.hidden,
created: this.created,
updated: this.updated,
}
Expand Down
Loading