implemented all controller/service verbs

This commit is contained in:
Joe Arndt 2025-12-11 22:33:29 -06:00
parent 085e84b086
commit f150fe84f2
9 changed files with 246 additions and 65 deletions

View file

@ -0,0 +1,11 @@
meta {
name: LOC DEL Expense
type: http
seq: 3
}
delete {
url: {{localBaseUrl}}/expenses/2aa94170-2c57-4c4f-a1e7-13544ba72917
body: none
auth: inherit
}

View file

@ -0,0 +1,11 @@
meta {
name: LOC GET Expense By ID
type: http
seq: 2
}
get {
url: {{localBaseUrl}}/expenses/2aa94170-2c57-4c4f-a1e7-13544ba72917
body: none
auth: inherit
}

View file

@ -1,5 +1,5 @@
meta { meta {
name: Expenses name: LOC GET Expenses
type: http type: http
seq: 1 seq: 1
} }

View file

@ -0,0 +1,23 @@
meta {
name: LOC POST Expense Full
type: http
seq: 4
}
post {
url: {{localBaseUrl}}/expenses
body: json
auth: inherit
}
body:json {
{
"date": "2025-12-01",
"cents": 987,
"categoryId": "1",
"merchantId": "1",
"subcategoryIds": ["1","2"],
"tagIds": ["1","2"],
"description": "NEW FULL expense"
}
}

View file

@ -0,0 +1,20 @@
meta {
name: LOC POST Expense Partial
type: http
seq: 5
}
post {
url: {{localBaseUrl}}/expenses
body: json
auth: inherit
}
body:json {
{
"date": "2025-12-01",
"cents": 987,
"categoryId": "1",
"description": "NEW PARTIAL expense"
}
}

View file

@ -1,19 +1,24 @@
import { PartialType } from '@nestjs/mapped-types'; import { PartialType } from '@nestjs/mapped-types';
export class CreateExpenseDto { export class CreateExpenseDto {
year: string; date: Date;
month: string;
day: string;
cents: number; cents: number;
category: string; categoryId: string;
merchant: string; merchantId?: string;
subcategory: string[]; subcategoryIds?: string[];
tags: string[]; tagIds?: string[];
description?: string; description?: string;
} }
export class UpdateExpenseDto extends PartialType(CreateExpenseDto) { } export class UpdateExpenseDto extends PartialType(CreateExpenseDto) {}
export class GetExpenseDto extends CreateExpenseDto{ export class GetExpenseDto {
id: number; id: string;
date: Date;
cents: number;
category: string;
merchant?: string;
subcategories?: string[];
tags?: string[];
description?: string;
} }

View file

@ -1,32 +1,30 @@
export class Expense { export class Expense {
id: number; id: string;
year: string; date: Date;
month: string;
day: string;
cents: number; cents: number;
category: Category; categoryId: string;
subcategory?: SubCategory[]; merchantId?: string;
merchant?: Merchant; subcategoryIds: string[];
tags?: Tag[]; tagIds: string[];
description?: string; description?: string;
} }
export class Category { export class Category {
id: number; id: string;
category: string; category: string;
} }
export class SubCategory { export class SubCategory {
id: number; id: string;
subcategory: string; subcategory: string;
} }
export class Merchant { export class Merchant {
id: number; id: string;
merchant: string; merchant: string;
} }
export class Tag { export class Tag {
id: number; id: string;
tag: string; tag: string;
} }

View file

@ -1,6 +1,6 @@
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; import { Controller, Get, Post, Body, Patch, Param, Delete, NotFoundException, HttpCode } from '@nestjs/common';
import { ExpensesService } from '../../services/expenses.service'; import { ExpensesService } from '../../services/expenses.service';
import { CreateExpenseDto, GetExpenseDto, UpdateExpenseDto } from './expense.dto'; import { CreateExpenseDto, UpdateExpenseDto } from './expense.dto';
@Controller('expenses') @Controller('expenses')
export class ExpensesController { export class ExpensesController {
@ -12,22 +12,33 @@ export class ExpensesController {
} }
@Get() @Get()
findAll(): GetExpenseDto[] { findAll() {
return this.expensesService.findAll(); return this.expensesService.findAll();
} }
@Get(':id') @Get(':id')
findOne(@Param('id') id: string) { findOne(@Param('id') id: string) {
return this.expensesService.findOne(+id); const expense = this.expensesService.findOne(id);
if (!expense) {
throw new NotFoundException();
} }
// @Patch(':id') return expense;
// update(@Param('id') id: string, @Body() updateExpenseDto: UpdateExpenseDto) { }
// return this.expensesService.update(+id, updateExpenseDto);
// } @Patch(':id')
// update(@Param('id') id: string, @Body() updateExpenseDto: UpdateExpenseDto) {
// @Delete(':id') const expense = this.expensesService.update(id, updateExpenseDto);
// remove(@Param('id') id: string) { if (!expense) {
// return this.expensesService.remove(+id); throw new NotFoundException();
// } }
return expense;
}
@Delete(':id')
@HttpCode(204)
remove(@Param('id') id: string) {
return this.expensesService.remove(id);
}
} }

View file

@ -1,40 +1,142 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { Expense } from '../controllers/expenses/expense.entities'; import { Category, Expense, Merchant, SubCategory, Tag } from '../controllers/expenses/expense.entities';
import { CreateExpenseDto, GetExpenseDto, UpdateExpenseDto } from '../controllers/expenses/expense.dto'; import { CreateExpenseDto, GetExpenseDto, UpdateExpenseDto } from '../controllers/expenses/expense.dto';
import { randomUUID } from 'node:crypto';
@Injectable() @Injectable()
export class ExpensesService { export class ExpensesService {
private fakeTempData: GetExpenseDto[] = [ private categories: Category[] = [
{ {
id: 123, id: '1',
year: '2025', category: 'Category 1'
month: '12', }
day: '10', ];
cents: 987, private merchants: Merchant[] = [
category: 'Automotive', {
merchant: '', id: '1',
subcategory: [], merchant: 'Merchant 1'
tags: [] }
];
private subcategories: SubCategory[] = [
{
id: '1',
subcategory: 'Subcategory 1'
},
{
id: '2',
subcategory: 'Subcategory 2'
}
];
private tags: Tag[] = [
{
id: '1',
tag: 'Tag 1'
},
{
id: '2',
tag: 'Tag 2'
}
];
private expenses: Expense[] = [
{
id: '2aa94170-2c57-4c4f-a1e7-13544ba72917',
date: new Date('2025-12-01'),
cents: 15443,
categoryId: '1',
merchantId: '1',
subcategoryIds: ['1', '2'],
tagIds: ['1', '2'],
description: 'Full existing expense'
},
{
id: '0708e7f7-3a2a-4b93-81da-38954925ca78',
date: new Date('2025-12-02'),
cents: 8723,
categoryId: '1',
subcategoryIds: [],
tagIds: [],
description: 'Partial existing expense'
} }
]; ];
create(createExpenseDto: CreateExpenseDto) { create(createExpenseDto: CreateExpenseDto) {
return 'This action adds a new expense'; const expense = {
id: randomUUID(),
date: new Date(createExpenseDto.date),
cents: createExpenseDto.cents,
categoryId: createExpenseDto.categoryId,
merchantId: createExpenseDto.merchantId,
subcategoryIds: createExpenseDto.subcategoryIds ?? [],
tagIds: createExpenseDto.tagIds ?? [],
description: createExpenseDto.description
} as Expense;
this.expenses.push(expense);
return this.mapExpense(expense);
} }
findAll(): GetExpenseDto[] { findAll() {
return this.fakeTempData; return this.expenses.map((expense) => {
return this.mapExpense(expense);
});
} }
findOne(id: number) { findOne(id: string) {
return `This action returns a #${id} expense`; const expense = this.getExpense(id);
return expense ? this.mapExpense(expense) : undefined;
} }
// update(id: number, updateExpenseDto: UpdateExpenseDto) { update(id: string, updateExpenseDto: UpdateExpenseDto) {
// return `This action updates a #${id} expense`; const index = this.expenses.findIndex((expense) => expense.id === id);
// } if (index) {
// const expense = this.expenses[index];
// remove(id: number) { this.expenses[index] = {
// return `This action removes a #${id} expense`; ...expense,
// } ...updateExpenseDto
// date: updateExpenseDto.date ?? expense.date,
// cents: updateExpenseDto.cents ?? expense.cents,
// categoryId: updateExpenseDto.categoryId ?? expense.categoryId,
// merchant: updateExpenseDto.merchantId ?? expense.merchantId,
// subcategoryIds: updateExpenseDto.subcategoryIds ?? expense.subcategoryIds,
// tagIds: updateExpenseDto.tagIds ?? expense.tagIds,
// description: updateExpenseDto.description ?? expense.description
};
return this.mapExpense(this.expenses[index]);
}
return undefined;
}
remove(id: string) {
this.expenses = this.expenses.filter((expense) => expense.id !== id);
}
private getExpense(id: string) {
return this.expenses.find((expense) => expense.id === id);
}
private getSubcategories(ids: string[]) {
return this.subcategories.filter((sub) => ids.includes(sub.id)).map((s) => s.subcategory);
}
private getTags(ids: string[]) {
return this.tags.filter((tag) => ids.includes(tag.id)).map((t) => t.tag);
}
private mapExpense(expense: Expense) {
const category = this.categories.find((category) => category.id === expense.categoryId);
const merchant = this.merchants.find((merchant) => merchant.id === expense.merchantId);
return {
id: expense.id,
date: expense.date,
cents: expense.cents,
category: category?.category,
merchant: merchant?.merchant,
subcategories: this.getSubcategories(expense.subcategoryIds),
tags: this.getTags(expense.tagIds),
description: expense.description
} as GetExpenseDto;
}
} }