251123:2300 Update T1
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository, DataSource } from 'typeorm';
|
||||
import { Repository, DataSource, Not } from 'typeorm'; // เพิ่ม Not
|
||||
|
||||
import { Circulation } from './entities/circulation.entity';
|
||||
import { CirculationRouting } from './entities/circulation-routing.entity';
|
||||
import { User } from '../user/entities/user.entity';
|
||||
import { CreateCirculationDto } from './dto/create-circulation.dto'; // ต้องสร้าง DTO นี้
|
||||
import { CreateCirculationDto } from './dto/create-circulation.dto';
|
||||
import { UpdateCirculationRoutingDto } from './dto/update-circulation-routing.dto'; // Import ใหม่
|
||||
import { SearchCirculationDto } from './dto/search-circulation.dto'; // Import ใหม่
|
||||
|
||||
@Injectable()
|
||||
export class CirculationService {
|
||||
@@ -18,13 +25,16 @@ export class CirculationService {
|
||||
) {}
|
||||
|
||||
async create(createDto: CreateCirculationDto, user: User) {
|
||||
if (!user.primaryOrganizationId) {
|
||||
throw new BadRequestException('User must belong to an organization');
|
||||
}
|
||||
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
// 1. Create Master Circulation
|
||||
// TODO: Generate Circulation No. logic here (Simple format)
|
||||
// Generate No. (Mock Logic) -> ควรใช้ NumberingService จริงในอนาคต
|
||||
const circulationNo = `CIR-${Date.now()}`;
|
||||
|
||||
const circulation = queryRunner.manager.create(Circulation, {
|
||||
@@ -37,13 +47,12 @@ export class CirculationService {
|
||||
});
|
||||
const savedCirculation = await queryRunner.manager.save(circulation);
|
||||
|
||||
// 2. Create Routings (Assignees)
|
||||
if (createDto.assigneeIds && createDto.assigneeIds.length > 0) {
|
||||
const routings = createDto.assigneeIds.map((userId, index) =>
|
||||
queryRunner.manager.create(CirculationRouting, {
|
||||
circulationId: savedCirculation.id,
|
||||
stepNumber: index + 1,
|
||||
organizationId: user.primaryOrganizationId, // Internal routing
|
||||
organizationId: user.primaryOrganizationId,
|
||||
assignedTo: userId,
|
||||
status: 'PENDING',
|
||||
}),
|
||||
@@ -61,23 +70,84 @@ export class CirculationService {
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(searchDto: SearchCirculationDto, user: User) {
|
||||
const { search, status, page = 1, limit = 20 } = searchDto;
|
||||
const query = this.circulationRepo
|
||||
.createQueryBuilder('c')
|
||||
.leftJoinAndSelect('c.creator', 'creator')
|
||||
.where('c.organizationId = :orgId', {
|
||||
orgId: user.primaryOrganizationId,
|
||||
});
|
||||
|
||||
if (status) {
|
||||
query.andWhere('c.statusCode = :status', { status });
|
||||
}
|
||||
|
||||
if (search) {
|
||||
query.andWhere(
|
||||
'(c.circulationNo LIKE :search OR c.subject LIKE :search)',
|
||||
{ search: `%${search}%` },
|
||||
);
|
||||
}
|
||||
|
||||
query
|
||||
.orderBy('c.createdAt', 'DESC')
|
||||
.skip((page - 1) * limit)
|
||||
.take(limit);
|
||||
|
||||
const [data, total] = await query.getManyAndCount();
|
||||
return { data, meta: { total, page, limit } };
|
||||
}
|
||||
|
||||
async findOne(id: number) {
|
||||
const circulation = await this.circulationRepo.findOne({
|
||||
where: { id },
|
||||
relations: ['routings', 'routings.assignee', 'correspondence'],
|
||||
relations: ['routings', 'routings.assignee', 'correspondence', 'creator'],
|
||||
order: { routings: { stepNumber: 'ASC' } },
|
||||
});
|
||||
if (!circulation) throw new NotFoundException('Circulation not found');
|
||||
return circulation;
|
||||
}
|
||||
|
||||
// Method update status (Complete task)
|
||||
// ✅ Logic อัปเดตสถานะและปิดงาน
|
||||
async updateRoutingStatus(
|
||||
routingId: number,
|
||||
status: string,
|
||||
comments: string,
|
||||
dto: UpdateCirculationRoutingDto,
|
||||
user: User,
|
||||
) {
|
||||
// Logic to update routing status
|
||||
// and Check if all routings are completed -> Close Circulation
|
||||
const routing = await this.routingRepo.findOne({
|
||||
where: { id: routingId },
|
||||
relations: ['circulation'],
|
||||
});
|
||||
|
||||
if (!routing) throw new NotFoundException('Routing task not found');
|
||||
|
||||
// Check Permission: คนทำต้องเป็นเจ้าของ Task
|
||||
if (routing.assignedTo !== user.user_id) {
|
||||
throw new ForbiddenException('You are not assigned to this task');
|
||||
}
|
||||
|
||||
// Update Routing
|
||||
routing.status = dto.status;
|
||||
routing.comments = dto.comments;
|
||||
routing.completedAt = new Date();
|
||||
await this.routingRepo.save(routing);
|
||||
|
||||
// Check: ถ้าทุกคนทำเสร็จแล้ว ให้ปิดใบเวียน (Master)
|
||||
const pendingCount = await this.routingRepo.count({
|
||||
where: {
|
||||
circulationId: routing.circulationId,
|
||||
status: 'PENDING', // หรือ status ที่ยังไม่เสร็จ
|
||||
},
|
||||
});
|
||||
|
||||
if (pendingCount === 0) {
|
||||
await this.circulationRepo.update(routing.circulationId, {
|
||||
statusCode: 'COMPLETED',
|
||||
closedAt: new Date(),
|
||||
});
|
||||
}
|
||||
|
||||
return routing;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user