base con autenticacion, registro, modulo encuestas

This commit is contained in:
2025-06-16 12:02:22 -04:00
commit 475e0754df
411 changed files with 26265 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
import { Roles } from '@/common/decorators';
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CategoryTypesService } from './category-types.service';
import { CreateCategoryTypeDto } from './dto/create-category-type.dto';
import { UpdateCategoryTypeDto } from './dto/update-category-type.dto';
import { CategoryType } from './entities/category-type.entity';
@ApiTags('Category Types')
@Controller('configurations/category-types')
export class CategoryTypesController {
constructor(private readonly categoryTypesService: CategoryTypesService) {}
@Get()
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get all category types' })
@ApiResponse({
status: 200,
description: 'Return all category types',
type: [CategoryType],
})
findAll() {
return this.categoryTypesService.findAll();
}
@Get(':id')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get a category type by id' })
@ApiResponse({
status: 200,
description: 'Return a category type',
type: CategoryType,
})
@ApiResponse({ status: 404, description: 'Category type not found' })
findOne(@Param('id', ParseIntPipe) id: number) {
return this.categoryTypesService.findOne(id);
}
@Get('group/:group')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get category types by group' })
@ApiResponse({
status: 200,
description: 'Return category types by group',
type: [CategoryType],
})
findByGroup(@Param('group') group: string) {
return this.categoryTypesService.findByGroup(group);
}
@Post()
@Roles('admin')
@ApiOperation({ summary: 'Create a new category type' })
@ApiResponse({
status: 201,
description: 'Category type created',
type: CategoryType,
})
create(@Body() createCategoryTypeDto: CreateCategoryTypeDto) {
return this.categoryTypesService.create(createCategoryTypeDto);
}
@Patch(':id')
@Roles('admin')
@ApiOperation({ summary: 'Update a category type' })
@ApiResponse({
status: 200,
description: 'Category type updated',
type: CategoryType,
})
@ApiResponse({ status: 404, description: 'Category type not found' })
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateCategoryTypeDto: UpdateCategoryTypeDto,
) {
return this.categoryTypesService.update(id, updateCategoryTypeDto);
}
@Delete(':id')
@Roles('admin')
@ApiOperation({ summary: 'Delete a category type' })
@ApiResponse({ status: 200, description: 'Category type deleted' })
@ApiResponse({ status: 404, description: 'Category type not found' })
remove(@Param('id', ParseIntPipe) id: number) {
return this.categoryTypesService.remove(id);
}
}

View File

@@ -0,0 +1,12 @@
import { DrizzleModule } from '@/database/drizzle.module';
import { Module } from '@nestjs/common';
import { CategoryTypesController } from './category-types.controller';
import { CategoryTypesService } from './category-types.service';
@Module({
imports: [DrizzleModule],
controllers: [CategoryTypesController],
providers: [CategoryTypesService],
exports: [CategoryTypesService],
})
export class CategoryTypesModule {}

View File

@@ -0,0 +1,81 @@
import { DRIZZLE_PROVIDER } from '@/database/drizzle-provider';
import * as schema from '@/database/index';
import { categoryType } from '@/database/schema/general';
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
import { CreateCategoryTypeDto } from './dto/create-category-type.dto';
import { UpdateCategoryTypeDto } from './dto/update-category-type.dto';
import { CategoryType } from './entities/category-type.entity';
@Injectable()
export class CategoryTypesService {
constructor(
@Inject(DRIZZLE_PROVIDER) private drizzle: NodePgDatabase<typeof schema>,
) {}
async findAll(): Promise<CategoryType[]> {
return await this.drizzle.select().from(categoryType);
}
async findOne(id: number): Promise<CategoryType> {
const category = await this.drizzle
.select()
.from(categoryType)
.where(eq(categoryType.id, id));
if (category.length === 0) {
throw new HttpException('Category type not found', HttpStatus.NOT_FOUND);
}
return category[0];
}
async findByGroup(group: string): Promise<CategoryType[]> {
return await this.drizzle
.select()
.from(categoryType)
.where(eq(categoryType.group, group));
}
async create(
createCategoryTypeDto: CreateCategoryTypeDto,
): Promise<CategoryType> {
const [category] = await this.drizzle
.insert(categoryType)
.values({
group: createCategoryTypeDto.group,
description: createCategoryTypeDto.description,
})
.returning();
return category;
}
async update(
id: number,
updateCategoryTypeDto: UpdateCategoryTypeDto,
): Promise<CategoryType> {
// Check if category type exists
await this.findOne(id);
await this.drizzle
.update(categoryType)
.set({
group: updateCategoryTypeDto.group,
description: updateCategoryTypeDto.description,
})
.where(eq(categoryType.id, id));
return this.findOne(id);
}
async remove(id: number): Promise<{ message: string }> {
// Check if category type exists
await this.findOne(id);
await this.drizzle.delete(categoryType).where(eq(categoryType.id, id));
return { message: 'Category type deleted successfully' };
}
}

View File

@@ -0,0 +1,21 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
export class CreateCategoryTypeDto {
@ApiProperty({
description: 'The group of the category type',
example: 'PAYROLL_TYPE',
})
@IsNotEmpty()
@IsString()
group: string;
@ApiProperty({
description: 'The description of the category type',
example: 'Quincenal',
})
@IsNotEmpty()
@IsString()
description: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateCategoryTypeDto } from './create-category-type.dto';
export class UpdateCategoryTypeDto extends PartialType(CreateCategoryTypeDto) {}

View File

@@ -0,0 +1,33 @@
import { ApiProperty } from '@nestjs/swagger';
export class CategoryType {
@ApiProperty({
description: 'The unique identifier of the category type',
example: 1,
})
id: number;
@ApiProperty({
description: 'The group of the category type',
example: 'PAYROLL_TYPE',
})
group: string;
@ApiProperty({
description: 'The description of the category type',
example: 'Quincenal',
})
description: string;
@ApiProperty({
description: 'The date when the category type was created',
example: '2023-01-01T00:00:00.000Z',
})
created_at?: Date;
@ApiProperty({
description: 'The date when the category type was last updated',
example: '2023-01-01T00:00:00.000Z',
})
updated_at?: Date | null;
}

View File

@@ -0,0 +1,15 @@
import { Module } from '@nestjs/common';
import { CategoryTypesModule } from './category-types/category-types.module';
import { MunicipalitiesModule } from './municipalities/municipalities.module';
import { ParishesModule } from './parishes/parishes.module';
import { StatesModule } from './states/states.module';
@Module({
imports: [
StatesModule,
MunicipalitiesModule,
ParishesModule,
CategoryTypesModule,
],
})
export class ConfigurationsModule {}

View File

@@ -0,0 +1,20 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
export class CreateMunicipalityDto {
@ApiProperty({
description: 'The name of the municipality',
example: 'Los Angeles',
})
@IsNotEmpty()
@IsString()
name: string;
@ApiProperty({
description: 'The ID of the state this municipality belongs to',
example: 1,
})
@IsNotEmpty()
@IsNumber()
stateId: number;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateMunicipalityDto } from './create-municipality.dto';
export class UpdateMunicipalityDto extends PartialType(CreateMunicipalityDto) {}

View File

@@ -0,0 +1,39 @@
import { ApiProperty } from '@nestjs/swagger';
export class Municipality {
@ApiProperty({
description: 'The unique identifier of the municipality',
example: 1,
})
id: number;
@ApiProperty({
description: 'The name of the municipality',
example: 'Los Angeles',
})
name: string;
@ApiProperty({
description: 'The ID of the state this municipality belongs to',
example: 1,
})
stateId: number;
@ApiProperty({
description: 'The name of the state this municipality belongs to',
example: 'California',
})
stateName?: string | null;
@ApiProperty({
description: 'The date when the municipality was created',
example: '2023-01-01T00:00:00.000Z',
})
created_at?: Date | null;
@ApiProperty({
description: 'The date when the municipality was last updated',
example: '2023-01-01T00:00:00.000Z',
})
updated_at?: Date | null;
}

View File

@@ -0,0 +1,97 @@
import { Roles } from '@/common/decorators';
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CreateMunicipalityDto } from './dto/create-municipality.dto';
import { UpdateMunicipalityDto } from './dto/update-municipality.dto';
import { Municipality } from './entities/municipality.entity';
import { MunicipalitiesService } from './municipalities.service';
@ApiTags('Municipalities')
@Controller('configurations/municipalities')
export class MunicipalitiesController {
constructor(private readonly municipalitiesService: MunicipalitiesService) {}
@Get()
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get all municipalities' })
@ApiResponse({
status: 200,
description: 'Return all municipalities',
type: [Municipality],
})
findAll() {
return this.municipalitiesService.findAll();
}
@Get(':id')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get a municipality by id' })
@ApiResponse({
status: 200,
description: 'Return a municipality',
type: Municipality,
})
@ApiResponse({ status: 404, description: 'Municipality not found' })
findOne(@Param('id', ParseIntPipe) id: number) {
return this.municipalitiesService.findOne(id);
}
@Get('state/:stateId')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get municipalities by state id' })
@ApiResponse({
status: 200,
description: 'Return municipalities by state',
type: [Municipality],
})
@ApiResponse({ status: 404, description: 'State not found' })
findByState(@Param('stateId', ParseIntPipe) stateId: number) {
return this.municipalitiesService.findByState(stateId);
}
@Post()
@Roles('ADMIN')
@ApiOperation({ summary: 'Create a new municipality' })
@ApiResponse({
status: 201,
description: 'Municipality created',
type: Municipality,
})
create(@Body() createMunicipalityDto: CreateMunicipalityDto) {
return this.municipalitiesService.create(createMunicipalityDto);
}
@Patch(':id')
@Roles('ADMIN')
@ApiOperation({ summary: 'Update a municipality' })
@ApiResponse({
status: 200,
description: 'Municipality updated',
type: Municipality,
})
@ApiResponse({ status: 404, description: 'Municipality not found' })
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateMunicipalityDto: UpdateMunicipalityDto,
) {
return this.municipalitiesService.update(id, updateMunicipalityDto);
}
@Delete(':id')
@Roles('ADMIN')
@ApiOperation({ summary: 'Delete a municipality' })
@ApiResponse({ status: 200, description: 'Municipality deleted' })
@ApiResponse({ status: 404, description: 'Municipality not found' })
remove(@Param('id', ParseIntPipe) id: number) {
return this.municipalitiesService.remove(id);
}
}

View File

@@ -0,0 +1,13 @@
import { DrizzleModule } from '@/database/drizzle.module';
import { Module } from '@nestjs/common';
import { StatesModule } from '../states/states.module';
import { MunicipalitiesController } from './municipalities.controller';
import { MunicipalitiesService } from './municipalities.service';
@Module({
imports: [DrizzleModule, StatesModule],
controllers: [MunicipalitiesController],
providers: [MunicipalitiesService],
exports: [MunicipalitiesService],
})
export class MunicipalitiesModule {}

View File

@@ -0,0 +1,120 @@
import { DRIZZLE_PROVIDER } from '@/database/drizzle-provider';
import * as schema from '@/database/index';
import { municipalities, states } from '@/database/schema/general';
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
import { StatesService } from '../states/states.service';
import { CreateMunicipalityDto } from './dto/create-municipality.dto';
import { UpdateMunicipalityDto } from './dto/update-municipality.dto';
import { Municipality } from './entities/municipality.entity';
@Injectable()
export class MunicipalitiesService {
constructor(
@Inject(DRIZZLE_PROVIDER) private drizzle: NodePgDatabase<typeof schema>,
private statesService: StatesService,
) {}
async findAll(): Promise<Municipality[]> {
return await this.drizzle
.select({
id: municipalities.id,
name: municipalities.name,
stateId: municipalities.stateId,
stateName: states.name,
created_at: municipalities.created_at,
updated_at: municipalities.updated_at,
})
.from(municipalities)
.leftJoin(states, eq(municipalities.stateId, states.id));
}
async findOne(id: number): Promise<Municipality> {
const municipality = await this.drizzle
.select({
id: municipalities.id,
name: municipalities.name,
stateId: municipalities.stateId,
stateName: states.name,
created_at: municipalities.created_at,
updated_at: municipalities.updated_at,
})
.from(municipalities)
.leftJoin(states, eq(municipalities.stateId, states.id))
.where(eq(municipalities.id, id));
if (municipality.length === 0) {
throw new HttpException('Municipality not found', HttpStatus.NOT_FOUND);
}
return municipality[0];
}
async findByState(stateId: number): Promise<Municipality[]> {
// Verify state exists
await this.statesService.findOne(stateId);
return await this.drizzle
.select({
id: municipalities.id,
name: municipalities.name,
stateId: municipalities.stateId,
stateName: states.name,
created_at: municipalities.created_at,
updated_at: municipalities.updated_at,
})
.from(municipalities)
.leftJoin(states, eq(municipalities.stateId, states.id))
.where(eq(municipalities.stateId, stateId));
}
async create(
createMunicipalityDto: CreateMunicipalityDto,
): Promise<Municipality> {
// Verify state exists
await this.statesService.findOne(createMunicipalityDto.stateId);
const [municipality] = await this.drizzle
.insert(municipalities)
.values({
name: createMunicipalityDto.name,
stateId: createMunicipalityDto.stateId,
})
.returning();
return this.findOne(municipality.id);
}
async update(
id: number,
updateMunicipalityDto: UpdateMunicipalityDto,
): Promise<Municipality> {
// Check if municipality exists
await this.findOne(id);
// If stateId is provided, verify it exists
if (updateMunicipalityDto.stateId) {
await this.statesService.findOne(updateMunicipalityDto.stateId);
}
await this.drizzle
.update(municipalities)
.set({
name: updateMunicipalityDto.name,
stateId: updateMunicipalityDto.stateId,
})
.where(eq(municipalities.id, id));
return this.findOne(id);
}
async remove(id: number): Promise<{ message: string }> {
// Check if municipality exists
await this.findOne(id);
await this.drizzle.delete(municipalities).where(eq(municipalities.id, id));
return { message: 'Municipality deleted successfully' };
}
}

View File

@@ -0,0 +1,20 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
export class CreateParishDto {
@ApiProperty({
description: 'The name of the parish',
example: 'Downtown',
})
@IsNotEmpty()
@IsString()
name: string;
@ApiProperty({
description: 'The ID of the municipality this parish belongs to',
example: 1,
})
@IsNotEmpty()
@IsNumber()
municipalityId: number;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateParishDto } from './create-parish.dto';
export class UpdateParishDto extends PartialType(CreateParishDto) {}

View File

@@ -0,0 +1,39 @@
import { ApiProperty } from '@nestjs/swagger';
export class Parish {
@ApiProperty({
description: 'The unique identifier of the parish',
example: 1,
})
id: number;
@ApiProperty({
description: 'The name of the parish',
example: 'Downtown',
})
name: string;
@ApiProperty({
description: 'The ID of the municipality this parish belongs to',
example: 1,
})
municipalityId: number;
@ApiProperty({
description: 'The name of the municipality this parish belongs to',
example: 'Los Angeles',
})
municipalityName?: string | null;
@ApiProperty({
description: 'The date when the parish was created',
example: '2023-01-01T00:00:00.000Z',
})
created_at?: Date | null;
@ApiProperty({
description: 'The date when the parish was last updated',
example: '2023-01-01T00:00:00.000Z',
})
updated_at: Date | null;
}

View File

@@ -0,0 +1,99 @@
import { Roles } from '@/common/decorators';
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CreateParishDto } from './dto/create-parish.dto';
import { UpdateParishDto } from './dto/update-parish.dto';
import { Parish } from './entities/parish.entity';
import { ParishesService } from './parishes.service';
@ApiTags('Parishes')
@Controller('configurations/parishes')
export class ParishesController {
constructor(private readonly parishesService: ParishesService) {}
@Get()
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get all parishes' })
@ApiResponse({
status: 200,
description: 'Return all parishes',
type: [Parish],
})
findAll() {
return this.parishesService.findAll();
}
@Get(':id')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get a parish by id' })
@ApiResponse({
status: 200,
description: 'Return a parish',
type: Parish,
})
@ApiResponse({ status: 404, description: 'Parish not found' })
findOne(@Param('id', ParseIntPipe) id: number) {
return this.parishesService.findOne(id);
}
@Get('municipality/:municipalityId')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get parishes by municipality id' })
@ApiResponse({
status: 200,
description: 'Return parishes by municipality',
type: [Parish],
})
@ApiResponse({ status: 404, description: 'Municipality not found' })
findByMunicipality(
@Param('municipalityId', ParseIntPipe) municipalityId: number,
) {
return this.parishesService.findByMunicipality(municipalityId);
}
@Post()
@Roles('ADMIN')
@ApiOperation({ summary: 'Create a new parish' })
@ApiResponse({
status: 201,
description: 'Parish created',
type: Parish,
})
create(@Body() createParishDto: CreateParishDto) {
return this.parishesService.create(createParishDto);
}
@Patch(':id')
@Roles('ADMIN')
@ApiOperation({ summary: 'Update a parish' })
@ApiResponse({
status: 200,
description: 'Parish updated',
type: Parish,
})
@ApiResponse({ status: 404, description: 'Parish not found' })
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateParishDto: UpdateParishDto,
) {
return this.parishesService.update(id, updateParishDto);
}
@Delete(':id')
@Roles('ADMIN')
@ApiOperation({ summary: 'Delete a parish' })
@ApiResponse({ status: 200, description: 'Parish deleted' })
@ApiResponse({ status: 404, description: 'Parish not found' })
remove(@Param('id', ParseIntPipe) id: number) {
return this.parishesService.remove(id);
}
}

View File

@@ -0,0 +1,13 @@
import { DrizzleModule } from '@/database/drizzle.module';
import { Module } from '@nestjs/common';
import { MunicipalitiesModule } from '../municipalities/municipalities.module';
import { ParishesController } from './parishes.controller';
import { ParishesService } from './parishes.service';
@Module({
imports: [DrizzleModule, MunicipalitiesModule],
controllers: [ParishesController],
providers: [ParishesService],
exports: [ParishesService],
})
export class ParishesModule {}

View File

@@ -0,0 +1,115 @@
import { DRIZZLE_PROVIDER } from '@/database/drizzle-provider';
import * as schema from '@/database/index';
import { municipalities, parishes } from '@/database/schema/general';
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
import { MunicipalitiesService } from '../municipalities/municipalities.service';
import { CreateParishDto } from './dto/create-parish.dto';
import { UpdateParishDto } from './dto/update-parish.dto';
import { Parish } from './entities/parish.entity';
@Injectable()
export class ParishesService {
constructor(
@Inject(DRIZZLE_PROVIDER) private drizzle: NodePgDatabase<typeof schema>,
private municipalitiesService: MunicipalitiesService,
) {}
async findAll(): Promise<Parish[]> {
return await this.drizzle
.select({
id: parishes.id,
name: parishes.name,
municipalityId: parishes.municipalityId,
municipalityName: municipalities.name,
created_at: parishes.created_at,
updated_at: parishes.updated_at,
})
.from(parishes)
.leftJoin(municipalities, eq(parishes.municipalityId, municipalities.id));
}
async findOne(id: number): Promise<Parish> {
const parish = await this.drizzle
.select({
id: parishes.id,
name: parishes.name,
municipalityId: parishes.municipalityId,
municipalityName: municipalities.name,
created_at: parishes.created_at,
updated_at: parishes.updated_at,
})
.from(parishes)
.leftJoin(municipalities, eq(parishes.municipalityId, municipalities.id))
.where(eq(parishes.id, id));
if (parish.length === 0) {
throw new HttpException('Parish not found', HttpStatus.NOT_FOUND);
}
return parish[0];
}
async findByMunicipality(municipalityId: number): Promise<Parish[]> {
// Verify municipality exists
await this.municipalitiesService.findOne(municipalityId);
return await this.drizzle
.select({
id: parishes.id,
name: parishes.name,
municipalityId: parishes.municipalityId,
municipalityName: municipalities.name,
created_at: parishes.created_at,
updated_at: parishes.updated_at,
})
.from(parishes)
.leftJoin(municipalities, eq(parishes.municipalityId, municipalities.id))
.where(eq(parishes.municipalityId, municipalityId));
}
async create(createParishDto: CreateParishDto): Promise<Parish> {
// Verify municipality exists
await this.municipalitiesService.findOne(createParishDto.municipalityId);
const [parish] = await this.drizzle
.insert(parishes)
.values({
name: createParishDto.name,
municipalityId: createParishDto.municipalityId,
})
.returning();
return this.findOne(parish.id);
}
async update(id: number, updateParishDto: UpdateParishDto): Promise<Parish> {
// Check if parish exists
await this.findOne(id);
// If municipalityId is provided, verify it exists
if (updateParishDto.municipalityId) {
await this.municipalitiesService.findOne(updateParishDto.municipalityId);
}
await this.drizzle
.update(parishes)
.set({
name: updateParishDto.name,
municipalityId: updateParishDto.municipalityId,
})
.where(eq(parishes.id, id));
return this.findOne(id);
}
async remove(id: number): Promise<{ message: string }> {
// Check if parish exists
await this.findOne(id);
await this.drizzle.delete(parishes).where(eq(parishes.id, id));
return { message: 'Parish deleted successfully' };
}
}

View File

@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class CreateStateDto {
@ApiProperty({
description: 'The name of the state',
example: 'California',
})
@IsNotEmpty()
@IsString()
name: string;
}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateStateDto } from './create-state.dto';
export class UpdateStateDto extends PartialType(CreateStateDto) {}

View File

@@ -0,0 +1,27 @@
import { ApiProperty } from '@nestjs/swagger';
export class State {
@ApiProperty({
description: 'The unique identifier of the state',
example: 1,
})
id: number;
@ApiProperty({
description: 'The name of the state',
example: 'California',
})
name: string;
@ApiProperty({
description: 'The date when the state was created',
example: '2023-01-01T00:00:00.000Z',
})
created_at?: Date | null;
@ApiProperty({
description: 'The date when the state was last updated',
example: '2023-01-01T00:00:00.000Z',
})
updated_at?: Date | null;
}

View File

@@ -0,0 +1,68 @@
import { Roles } from '@/common/decorators';
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { UpdateStateDto } from './dto//update-state.dto';
import { CreateStateDto } from './dto/create-state.dto';
import { State } from './entities/state.entity';
import { StatesService } from './states.service';
@ApiTags('States')
@Controller('configurations/states')
export class StatesController {
constructor(private readonly statesService: StatesService) {}
@Get()
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get all states' })
@ApiResponse({ status: 200, description: 'Return all states', type: [State] })
findAll() {
return this.statesService.findAll();
}
@Get(':id')
@Roles('admin', 'user')
@ApiOperation({ summary: 'Get a state by id' })
@ApiResponse({ status: 200, description: 'Return a state', type: State })
@ApiResponse({ status: 404, description: 'State not found' })
findOne(@Param('id', ParseIntPipe) id: number) {
return this.statesService.findOne(id);
}
@Post()
@Roles('admin')
@ApiOperation({ summary: 'Create a new state' })
@ApiResponse({ status: 201, description: 'State created', type: State })
create(@Body() createStateDto: CreateStateDto) {
return this.statesService.create(createStateDto);
}
@Patch(':id')
@Roles('admin')
@ApiOperation({ summary: 'Update a state' })
@ApiResponse({ status: 200, description: 'State updated', type: State })
@ApiResponse({ status: 404, description: 'State not found' })
update(
@Param('id', ParseIntPipe) id: number,
@Body() updateStateDto: UpdateStateDto,
) {
return this.statesService.update(id, updateStateDto);
}
@Delete(':id')
@Roles('admin')
@ApiOperation({ summary: 'Delete a state' })
@ApiResponse({ status: 200, description: 'State deleted' })
@ApiResponse({ status: 404, description: 'State not found' })
remove(@Param('id', ParseIntPipe) id: number) {
return this.statesService.remove(id);
}
}

View File

@@ -0,0 +1,12 @@
import { DrizzleModule } from '@/database/drizzle.module';
import { Module } from '@nestjs/common';
import { StatesController } from './states.controller';
import { StatesService } from './states.service';
@Module({
imports: [DrizzleModule],
controllers: [StatesController],
providers: [StatesService],
exports: [StatesService],
})
export class StatesModule {}

View File

@@ -0,0 +1,67 @@
import { DRIZZLE_PROVIDER } from '@/database/drizzle-provider';
import * as schema from '@/database/index';
import { states } from '@/database/schema/general';
import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
import { CreateStateDto } from './dto/create-state.dto';
import { UpdateStateDto } from './dto/update-state.dto';
import { State } from './entities/state.entity';
@Injectable()
export class StatesService {
constructor(
@Inject(DRIZZLE_PROVIDER) private drizzle: NodePgDatabase<typeof schema>,
) {}
async findAll(): Promise<State[]> {
return await this.drizzle.select().from(states);
}
async findOne(id: number): Promise<State> {
const state = await this.drizzle
.select()
.from(states)
.where(eq(states.id, id));
if (state.length === 0) {
throw new HttpException('State not found', HttpStatus.NOT_FOUND);
}
return state[0];
}
async create(createStateDto: CreateStateDto): Promise<State> {
const [state] = await this.drizzle
.insert(states)
.values({
name: createStateDto.name,
})
.returning();
return state;
}
async update(id: number, updateStateDto: UpdateStateDto): Promise<State> {
// Check if state exists
await this.findOne(id);
await this.drizzle
.update(states)
.set({
name: updateStateDto.name,
})
.where(eq(states.id, id));
return this.findOne(id);
}
async remove(id: number): Promise<{ message: string }> {
// Check if state exists
await this.findOne(id);
await this.drizzle.delete(states).where(eq(states.id, id));
return { message: 'State deleted successfully' };
}
}