From 75990801062095f80c6f7c7c2a3170c1ba41b479 Mon Sep 17 00:00:00 2001 From: Joe Arndt Date: Sun, 8 Feb 2026 17:27:45 -0600 Subject: [PATCH] added sub-categories resource --- src/app.module.ts | 9 ++- .../dto/create-sub-category.dto.ts | 3 + .../dto/update-sub-category.dto.ts | 4 + .../entities/sub-category.entity.ts | 10 +++ .../sub-categories.controller.ts | 75 +++++++++++++++++++ src/sub-categories/sub-categories.module.ts | 10 +++ src/sub-categories/sub-categories.service.ts | 35 +++++++++ .../sub-category-data.service.ts | 33 ++++++++ 8 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 src/sub-categories/dto/create-sub-category.dto.ts create mode 100644 src/sub-categories/dto/update-sub-category.dto.ts create mode 100644 src/sub-categories/entities/sub-category.entity.ts create mode 100644 src/sub-categories/sub-categories.controller.ts create mode 100644 src/sub-categories/sub-categories.module.ts create mode 100644 src/sub-categories/sub-categories.service.ts create mode 100644 src/sub-categories/sub-category-data.service.ts diff --git a/src/app.module.ts b/src/app.module.ts index 8cdb8f8..fd2edf1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,18 +1,20 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; -import { MerchantsModule } from './merchants/merchants.module'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; +import { MerchantsModule } from './merchants/merchants.module'; import { Merchant } from './merchants/entities/merchant.entity'; import { TagsModule } from './tags/tags.module'; import { Tag } from './tags/entities/tag.entity'; import { CategoriesModule } from './categories/categories.module'; import { Category } from './categories/entities/category.entity'; +import { SubCategoriesModule } from './sub-categories/sub-categories.module'; +import { SubCategory } from './sub-categories/entities/sub-category.entity'; const sqliteConfig: TypeOrmModuleOptions = { synchronize: true, // typeorm -h (schema:sync) type: 'sqlite', database: 'common-cents.db', - entities: [Merchant, Tag, Category] + entities: [Merchant, Tag, Category, SubCategory] } @Module({ @@ -20,7 +22,8 @@ const sqliteConfig: TypeOrmModuleOptions = { TypeOrmModule.forRoot(sqliteConfig), MerchantsModule, TagsModule, - CategoriesModule + CategoriesModule, + SubCategoriesModule ], controllers: [AppController], providers: [] diff --git a/src/sub-categories/dto/create-sub-category.dto.ts b/src/sub-categories/dto/create-sub-category.dto.ts new file mode 100644 index 0000000..3837548 --- /dev/null +++ b/src/sub-categories/dto/create-sub-category.dto.ts @@ -0,0 +1,3 @@ +export class CreateSubCategoryDto { + name: string; +} diff --git a/src/sub-categories/dto/update-sub-category.dto.ts b/src/sub-categories/dto/update-sub-category.dto.ts new file mode 100644 index 0000000..0541922 --- /dev/null +++ b/src/sub-categories/dto/update-sub-category.dto.ts @@ -0,0 +1,4 @@ +export class UpdateSubCategoryDto { + id: string; + name: string; +} diff --git a/src/sub-categories/entities/sub-category.entity.ts b/src/sub-categories/entities/sub-category.entity.ts new file mode 100644 index 0000000..a83bdfe --- /dev/null +++ b/src/sub-categories/entities/sub-category.entity.ts @@ -0,0 +1,10 @@ +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity() +export class SubCategory { + @PrimaryGeneratedColumn() + id: string; + + @Column() + name: string; +} diff --git a/src/sub-categories/sub-categories.controller.ts b/src/sub-categories/sub-categories.controller.ts new file mode 100644 index 0000000..a39b1e7 --- /dev/null +++ b/src/sub-categories/sub-categories.controller.ts @@ -0,0 +1,75 @@ +import { + Controller, + Get, + Post, + Put, + Delete, + Body, + Param, + HttpCode, + HttpStatus, + BadRequestException, + NotFoundException, + InternalServerErrorException +} from '@nestjs/common'; +import { SubCategoriesService } from './sub-categories.service'; +import { CreateSubCategoryDto } from './dto/create-sub-category.dto'; +import { UpdateSubCategoryDto } from './dto/update-sub-category.dto'; +import { SubCategory } from './entities/sub-category.entity'; + +@Controller('sub-categories') +export class SubCategoriesController { + constructor(private readonly subCategoriesService: SubCategoriesService) { } + + @Get() + @HttpCode(HttpStatus.OK) + public async findAll(): Promise { + return await this.subCategoriesService.findAll(); + } + + @Get(':id') + @HttpCode(HttpStatus.OK) + public async findOne(@Param('id') id: string): Promise { + if (!id) { + throw new BadRequestException('No ID provided.'); + } + + try { + return await this.subCategoriesService.findById(id); + } + catch (error) { + throw new NotFoundException(error); + } + } + + @Post() + @HttpCode(HttpStatus.CREATED) + public async create(@Body() subCategory: CreateSubCategoryDto): Promise { + if (!subCategory.name) { + throw new BadRequestException('Sub-category name cannot be empty.'); + } + + try { + return this.subCategoriesService.create(subCategory); + } + catch (error) { + throw new InternalServerErrorException(error); + } + } + + @Put() + @HttpCode(HttpStatus.OK) + public async update(@Body() subCategory: UpdateSubCategoryDto): Promise { + if (!subCategory.id) { + throw new BadRequestException('Sub-category ID cannot be empty.'); + } + + return await this.subCategoriesService.update(subCategory); + } + + @Delete(':id') + @HttpCode(HttpStatus.NO_CONTENT) + public async remove(@Param('id') id: string): Promise { + return await this.subCategoriesService.remove(id); + } +} diff --git a/src/sub-categories/sub-categories.module.ts b/src/sub-categories/sub-categories.module.ts new file mode 100644 index 0000000..f47230a --- /dev/null +++ b/src/sub-categories/sub-categories.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { SubCategoriesService } from './sub-categories.service'; +import { SubCategoriesController } from './sub-categories.controller'; +import { SubCategoryDataService } from './sub-category-data.service'; + +@Module({ + controllers: [SubCategoriesController], + providers: [SubCategoriesService, SubCategoryDataService] +}) +export class SubCategoriesModule { } diff --git a/src/sub-categories/sub-categories.service.ts b/src/sub-categories/sub-categories.service.ts new file mode 100644 index 0000000..15c35b1 --- /dev/null +++ b/src/sub-categories/sub-categories.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { CreateSubCategoryDto } from './dto/create-sub-category.dto'; +import { UpdateSubCategoryDto } from './dto/update-sub-category.dto'; +import { SubCategoryDataService } from './sub-category-data.service'; +import { SubCategory } from './entities/sub-category.entity'; + +@Injectable() +export class SubCategoriesService { + public constructor(private subCategoryDataService: SubCategoryDataService) { } + + public async findAll(): Promise { + return await this.subCategoryDataService.getAll(); + } + + public async findById(id: string): Promise { + const subCategory = await this.subCategoryDataService.getById(id); + if (!subCategory) { + throw new Error('No sub-category found'); + } + + return subCategory; + } + + public async create(subCategory: CreateSubCategoryDto): Promise { + return await this.subCategoryDataService.create(subCategory.name); + } + + public async update(subCategory: UpdateSubCategoryDto): Promise { + return await this.subCategoryDataService.update(subCategory); + } + + public async remove(id: string): Promise { + await this.subCategoryDataService.delete(id); + } +} diff --git a/src/sub-categories/sub-category-data.service.ts b/src/sub-categories/sub-category-data.service.ts new file mode 100644 index 0000000..3d57e66 --- /dev/null +++ b/src/sub-categories/sub-category-data.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { DataSource, Repository } from 'typeorm'; +import { SubCategory } from './entities/sub-category.entity'; +import { UpdateSubCategoryDto } from './dto/update-sub-category.dto'; + +@Injectable() +export class SubCategoryDataService { + private subCategories: Repository; + + public constructor(private dataSource: DataSource) { + this.subCategories = this.dataSource.getRepository(SubCategory); + } + + public async getAll(): Promise { + return await this.subCategories.find(); + } + + public async getById(id: string): Promise { + return await this.subCategories.findOneBy({ id }); + } + + public async create(name: string): Promise { + return await this.subCategories.save({ name }); + } + + public async update(subCategory: UpdateSubCategoryDto): Promise { + return await this.subCategories.save(subCategory); + } + + public async delete(id: string): Promise { + await this.subCategories.delete({ id }); + } +}