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 {
name: Expenses
name: LOC GET Expenses
type: http
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';
export class CreateExpenseDto {
year: string;
month: string;
day: string;
date: Date;
cents: number;
category: string;
merchant: string;
subcategory: string[];
tags: string[];
categoryId: string;
merchantId?: string;
subcategoryIds?: string[];
tagIds?: string[];
description?: string;
}
export class UpdateExpenseDto extends PartialType(CreateExpenseDto) { }
export class UpdateExpenseDto extends PartialType(CreateExpenseDto) {}
export class GetExpenseDto extends CreateExpenseDto{
id: number;
export class GetExpenseDto {
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 {
id: number;
year: string;
month: string;
day: string;
cents: number;
category: Category;
subcategory?: SubCategory[];
merchant?: Merchant;
tags?: Tag[];
description?: string;
id: string;
date: Date;
cents: number;
categoryId: string;
merchantId?: string;
subcategoryIds: string[];
tagIds: string[];
description?: string;
}
export class Category {
id: number;
category: string;
id: string;
category: string;
}
export class SubCategory {
id: number;
subcategory: string;
id: string;
subcategory: string;
}
export class Merchant {
id: number;
merchant: string;
id: string;
merchant: string;
}
export class Tag {
id: number;
tag: string;
id: 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 { CreateExpenseDto, GetExpenseDto, UpdateExpenseDto } from './expense.dto';
import { CreateExpenseDto, UpdateExpenseDto } from './expense.dto';
@Controller('expenses')
export class ExpensesController {
@ -12,22 +12,33 @@ export class ExpensesController {
}
@Get()
findAll(): GetExpenseDto[] {
findAll() {
return this.expensesService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.expensesService.findOne(+id);
const expense = this.expensesService.findOne(id);
if (!expense) {
throw new NotFoundException();
}
return expense;
}
// @Patch(':id')
// update(@Param('id') id: string, @Body() updateExpenseDto: UpdateExpenseDto) {
// return this.expensesService.update(+id, updateExpenseDto);
// }
//
// @Delete(':id')
// remove(@Param('id') id: string) {
// return this.expensesService.remove(+id);
// }
@Patch(':id')
update(@Param('id') id: string, @Body() updateExpenseDto: UpdateExpenseDto) {
const expense = this.expensesService.update(id, updateExpenseDto);
if (!expense) {
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 { 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 { randomUUID } from 'node:crypto';
@Injectable()
export class ExpensesService {
private fakeTempData: GetExpenseDto[] = [
private categories: Category[] = [
{
id: 123,
year: '2025',
month: '12',
day: '10',
cents: 987,
category: 'Automotive',
merchant: '',
subcategory: [],
tags: []
id: '1',
category: 'Category 1'
}
];
private merchants: Merchant[] = [
{
id: '1',
merchant: 'Merchant 1'
}
];
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) {
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[] {
return this.fakeTempData;
findAll() {
return this.expenses.map((expense) => {
return this.mapExpense(expense);
});
}
findOne(id: number) {
return `This action returns a #${id} expense`;
findOne(id: string) {
const expense = this.getExpense(id);
return expense ? this.mapExpense(expense) : undefined;
}
// update(id: number, updateExpenseDto: UpdateExpenseDto) {
// return `This action updates a #${id} expense`;
// }
//
// remove(id: number) {
// return `This action removes a #${id} expense`;
// }
update(id: string, updateExpenseDto: UpdateExpenseDto) {
const index = this.expenses.findIndex((expense) => expense.id === id);
if (index) {
const expense = this.expenses[index];
this.expenses[index] = {
...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;
}
}