251124:1700 Ready to Phase 7

This commit is contained in:
admin
2025-11-24 17:01:58 +07:00
parent 9360d78ea6
commit 4f45a69ed0
47 changed files with 2047 additions and 433 deletions
@@ -0,0 +1,19 @@
// File: src/modules/master/dto/create-tag.dto.ts
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class CreateTagDto {
@ApiProperty({ example: 'URGENT', description: 'ชื่อ Tag' })
@IsString()
@IsNotEmpty()
tag_name: string;
@ApiProperty({
example: 'เอกสารด่วนต้องดำเนินการทันที',
description: 'คำอธิบาย',
})
@IsString()
@IsOptional()
description?: string;
}
@@ -0,0 +1,26 @@
// File: src/modules/master/dto/search-tag.dto.ts
import { IsString, IsOptional, IsInt, Min } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiPropertyOptional } from '@nestjs/swagger';
export class SearchTagDto {
@ApiPropertyOptional({ description: 'คำค้นหา (ชื่อ Tag หรือ คำอธิบาย)' })
@IsOptional()
@IsString()
search?: string;
@ApiPropertyOptional({ description: 'หมายเลขหน้า (เริ่มต้น 1)', default: 1 })
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number = 1;
@ApiPropertyOptional({ description: 'จำนวนรายการต่อหน้า', default: 20 })
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
limit?: number = 20;
}
@@ -0,0 +1,6 @@
// File: src/modules/master/dto/update-tag.dto.ts
import { PartialType } from '@nestjs/swagger';
import { CreateTagDto } from './create-tag.dto';
export class UpdateTagDto extends PartialType(CreateTagDto) {}
@@ -0,0 +1,27 @@
// File: src/modules/master/entities/tag.entity.ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('tags')
export class Tag {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100, unique: true, comment: 'ชื่อ Tag' })
tag_name: string;
@Column({ type: 'text', nullable: true, comment: 'คำอธิบายแท็ก' })
description: string;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
@@ -0,0 +1,64 @@
// File: src/modules/master/master.controller.ts
import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { MasterService } from './master.service';
import { CreateTagDto } from './dto/create-tag.dto';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RequirePermission } from '../../common/decorators/require-permission.decorator';
@ApiTags('Master Data')
@Controller('master')
@UseGuards(JwtAuthGuard) // บังคับ Login ทุก Endpoint
export class MasterController {
constructor(private readonly masterService: MasterService) {}
@Get('correspondence-types')
@ApiOperation({ summary: 'Get all active correspondence types' })
getCorrespondenceTypes() {
return this.masterService.findAllCorrespondenceTypes();
}
@Get('correspondence-statuses')
@ApiOperation({ summary: 'Get all active correspondence statuses' })
getCorrespondenceStatuses() {
return this.masterService.findAllCorrespondenceStatuses();
}
@Get('rfa-types')
@ApiOperation({ summary: 'Get all active RFA types' })
getRfaTypes() {
return this.masterService.findAllRfaTypes();
}
@Get('rfa-statuses')
@ApiOperation({ summary: 'Get all active RFA status codes' })
getRfaStatuses() {
return this.masterService.findAllRfaStatuses();
}
@Get('rfa-approve-codes')
@ApiOperation({ summary: 'Get all active RFA approve codes' })
getRfaApproveCodes() {
return this.masterService.findAllRfaApproveCodes();
}
@Get('circulation-statuses')
@ApiOperation({ summary: 'Get all active circulation statuses' })
getCirculationStatuses() {
return this.masterService.findAllCirculationStatuses();
}
@Get('tags')
@ApiOperation({ summary: 'Get all tags' })
getTags() {
return this.masterService.findAllTags();
}
@Post('tags')
@RequirePermission('master_data.tag.manage') // ต้องมีสิทธิ์จัดการ Tag
@ApiOperation({ summary: 'Create a new tag (Admin only)' })
createTag(@Body() dto: CreateTagDto) {
return this.masterService.createTag(dto);
}
}
@@ -0,0 +1,33 @@
// File: src/modules/master/master.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MasterService } from './master.service';
import { MasterController } from './master.controller';
// Import Entities
import { Tag } from './entities/tag.entity';
import { CorrespondenceType } from '../correspondence/entities/correspondence-type.entity';
import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity';
import { RfaType } from '../rfa/entities/rfa-type.entity';
import { RfaStatusCode } from '../rfa/entities/rfa-status-code.entity';
import { RfaApproveCode } from '../rfa/entities/rfa-approve-code.entity';
import { CirculationStatusCode } from '../circulation/entities/circulation-status-code.entity';
@Module({
imports: [
TypeOrmModule.forFeature([
Tag,
CorrespondenceType,
CorrespondenceStatus,
RfaType,
RfaStatusCode,
RfaApproveCode,
CirculationStatusCode,
]),
],
controllers: [MasterController],
providers: [MasterService],
exports: [MasterService], // Export เผื่อ Module อื่นต้องใช้
})
export class MasterModule {}
@@ -0,0 +1,97 @@
// File: src/modules/master/master.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
// Import Entities จาก Module อื่นๆ (ตามโครงสร้างที่มีอยู่แล้ว)
import { CorrespondenceType } from '../correspondence/entities/correspondence-type.entity';
import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity';
import { RfaType } from '../rfa/entities/rfa-type.entity';
import { RfaStatusCode } from '../rfa/entities/rfa-status-code.entity';
import { RfaApproveCode } from '../rfa/entities/rfa-approve-code.entity';
import { CirculationStatusCode } from '../circulation/entities/circulation-status-code.entity';
import { Tag } from './entities/tag.entity'; // Entity ของ Module นี้เอง
import { CreateTagDto } from './dto/create-tag.dto';
@Injectable()
export class MasterService {
constructor(
@InjectRepository(CorrespondenceType)
private readonly corrTypeRepo: Repository<CorrespondenceType>,
@InjectRepository(CorrespondenceStatus)
private readonly corrStatusRepo: Repository<CorrespondenceStatus>,
@InjectRepository(RfaType)
private readonly rfaTypeRepo: Repository<RfaType>,
@InjectRepository(RfaStatusCode)
private readonly rfaStatusRepo: Repository<RfaStatusCode>,
@InjectRepository(RfaApproveCode)
private readonly rfaApproveRepo: Repository<RfaApproveCode>,
@InjectRepository(CirculationStatusCode)
private readonly circulationStatusRepo: Repository<CirculationStatusCode>,
@InjectRepository(Tag)
private readonly tagRepo: Repository<Tag>,
) {}
// --- Correspondence ---
findAllCorrespondenceTypes() {
return this.corrTypeRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
findAllCorrespondenceStatuses() {
return this.corrStatusRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
// --- RFA ---
findAllRfaTypes() {
return this.rfaTypeRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
findAllRfaStatuses() {
return this.rfaStatusRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
findAllRfaApproveCodes() {
return this.rfaApproveRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
// --- Circulation ---
findAllCirculationStatuses() {
return this.circulationStatusRepo.find({
where: { is_active: true },
order: { sort_order: 'ASC' },
});
}
// --- Tags ---
findAllTags() {
return this.tagRepo.find({ order: { tag_name: 'ASC' } });
}
async createTag(dto: CreateTagDto) {
const tag = this.tagRepo.create(dto);
return this.tagRepo.save(tag);
}
}