update first - 84
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
import { IsDateString, IsInt, IsNotEmpty, IsPositive, IsString, Max, Min } from 'class-validator';
|
||||
export class CreateKeyResultDto {
|
||||
objectiveId;
|
||||
title;
|
||||
startValue;
|
||||
targetValue;
|
||||
progress;
|
||||
deadline;
|
||||
}
|
||||
__decorate([
|
||||
IsInt(),
|
||||
IsPositive(),
|
||||
__metadata("design:type", Number)
|
||||
], CreateKeyResultDto.prototype, "objectiveId", void 0);
|
||||
__decorate([
|
||||
IsString(),
|
||||
IsNotEmpty(),
|
||||
__metadata("design:type", String)
|
||||
], CreateKeyResultDto.prototype, "title", void 0);
|
||||
__decorate([
|
||||
IsInt(),
|
||||
__metadata("design:type", Number)
|
||||
], CreateKeyResultDto.prototype, "startValue", void 0);
|
||||
__decorate([
|
||||
IsInt(),
|
||||
IsPositive(),
|
||||
__metadata("design:type", Number)
|
||||
], CreateKeyResultDto.prototype, "targetValue", void 0);
|
||||
__decorate([
|
||||
IsInt(),
|
||||
Min(0),
|
||||
Max(100),
|
||||
__metadata("design:type", Number)
|
||||
], CreateKeyResultDto.prototype, "progress", void 0);
|
||||
__decorate([
|
||||
IsDateString(),
|
||||
__metadata("design:type", String)
|
||||
], CreateKeyResultDto.prototype, "deadline", void 0);
|
||||
@@ -0,0 +1,25 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
import { IsInt, IsOptional, IsString, Max, Min } from 'class-validator';
|
||||
export class UpdateProgressDto {
|
||||
progress;
|
||||
comment;
|
||||
}
|
||||
__decorate([
|
||||
IsInt(),
|
||||
Min(0),
|
||||
Max(100),
|
||||
__metadata("design:type", Number)
|
||||
], UpdateProgressDto.prototype, "progress", void 0);
|
||||
__decorate([
|
||||
IsString(),
|
||||
IsOptional(),
|
||||
__metadata("design:type", String)
|
||||
], UpdateProgressDto.prototype, "comment", void 0);
|
||||
@@ -0,0 +1,67 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
import { Body, Controller, Get, Inject, Param, ParseIntPipe, Patch, Post, UseGuards, ValidationPipe } from '@nestjs/common';
|
||||
import { ok } from '../common/api-response.js';
|
||||
import { CurrentUser } from '../common/current-user.decorator.js';
|
||||
import { JwtAuthGuard } from '../common/jwt-auth.guard.js';
|
||||
import { RolesGuard } from '../common/roles.guard.js';
|
||||
import { CreateKeyResultDto } from './dto/create-key-result.dto.js';
|
||||
import { UpdateProgressDto } from './dto/update-progress.dto.js';
|
||||
import { KeyResultsService } from './key-results.service.js';
|
||||
let KeyResultsController = class KeyResultsController {
|
||||
keyResultsService;
|
||||
constructor(keyResultsService) {
|
||||
this.keyResultsService = keyResultsService;
|
||||
}
|
||||
async get(id, user) {
|
||||
return ok(await this.keyResultsService.getById(id, user));
|
||||
}
|
||||
async create(dto, user) {
|
||||
return ok(await this.keyResultsService.create(dto, user));
|
||||
}
|
||||
async updateProgress(id, dto, user) {
|
||||
return ok(await this.keyResultsService.updateProgress(id, dto, user));
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
Get(':id'),
|
||||
__param(0, Param('id', ParseIntPipe)),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], KeyResultsController.prototype, "get", null);
|
||||
__decorate([
|
||||
Post(),
|
||||
__param(0, Body(new ValidationPipe({ expectedType: CreateKeyResultDto, whitelist: true, forbidNonWhitelisted: true, transform: true }))),
|
||||
__param(1, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [CreateKeyResultDto, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], KeyResultsController.prototype, "create", null);
|
||||
__decorate([
|
||||
Patch(':id/progress'),
|
||||
__param(0, Param('id', ParseIntPipe)),
|
||||
__param(1, Body(new ValidationPipe({ expectedType: UpdateProgressDto, whitelist: true, forbidNonWhitelisted: true, transform: true }))),
|
||||
__param(2, CurrentUser()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, UpdateProgressDto, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], KeyResultsController.prototype, "updateProgress", null);
|
||||
KeyResultsController = __decorate([
|
||||
Controller('key-results'),
|
||||
UseGuards(JwtAuthGuard, RolesGuard),
|
||||
__param(0, Inject(KeyResultsService)),
|
||||
__metadata("design:paramtypes", [KeyResultsService])
|
||||
], KeyResultsController);
|
||||
export { KeyResultsController };
|
||||
@@ -0,0 +1,20 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from '../prisma/prisma.module.js';
|
||||
import { KeyResultsController } from './key-results.controller.js';
|
||||
import { KeyResultsService } from './key-results.service.js';
|
||||
let KeyResultsModule = class KeyResultsModule {
|
||||
};
|
||||
KeyResultsModule = __decorate([
|
||||
Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [KeyResultsController],
|
||||
providers: [KeyResultsService],
|
||||
})
|
||||
], KeyResultsModule);
|
||||
export { KeyResultsModule };
|
||||
@@ -0,0 +1,104 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
import { ForbiddenException, Inject, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service.js';
|
||||
const keyResultInclude = {
|
||||
objective: {
|
||||
include: {
|
||||
owner: { select: { id: true, name: true, username: true, email: true, role: true } },
|
||||
},
|
||||
},
|
||||
};
|
||||
let KeyResultsService = class KeyResultsService {
|
||||
prisma;
|
||||
constructor(prisma) {
|
||||
this.prisma = prisma;
|
||||
}
|
||||
async getById(id, user) {
|
||||
const keyResult = await this.prisma.keyResult.findUnique({ where: { id }, include: keyResultInclude });
|
||||
if (keyResult === null) {
|
||||
throw new NotFoundException('Key result not found');
|
||||
}
|
||||
this.assertCanRead(keyResult.objective.ownerId, user);
|
||||
return keyResult;
|
||||
}
|
||||
async create(dto, user) {
|
||||
const objective = await this.prisma.objective.findUnique({ where: { id: dto.objectiveId } });
|
||||
if (objective === null) {
|
||||
throw new NotFoundException('Objective not found');
|
||||
}
|
||||
this.assertCanWrite(objective.ownerId, user);
|
||||
const keyResult = await this.prisma.keyResult.create({
|
||||
data: {
|
||||
objectiveId: dto.objectiveId,
|
||||
title: dto.title,
|
||||
progress: dto.progress,
|
||||
startValue: dto.startValue,
|
||||
targetValue: dto.targetValue,
|
||||
deadline: new Date(dto.deadline),
|
||||
},
|
||||
include: keyResultInclude,
|
||||
});
|
||||
await this.recalculateObjectiveStatus(dto.objectiveId);
|
||||
return keyResult;
|
||||
}
|
||||
async updateProgress(id, dto, user) {
|
||||
const existing = await this.prisma.keyResult.findUnique({ where: { id }, include: keyResultInclude });
|
||||
if (existing === null) {
|
||||
throw new NotFoundException('Key result not found');
|
||||
}
|
||||
this.assertCanWrite(existing.objective.ownerId, user);
|
||||
const updated = await this.prisma.$transaction(async (tx) => {
|
||||
const keyResult = await tx.keyResult.update({
|
||||
where: { id },
|
||||
data: { progress: dto.progress },
|
||||
include: keyResultInclude,
|
||||
});
|
||||
await tx.progressUpdate.create({
|
||||
data: {
|
||||
keyResultId: id,
|
||||
progress: dto.progress,
|
||||
comment: dto.comment,
|
||||
createdById: user.sub,
|
||||
},
|
||||
});
|
||||
return keyResult;
|
||||
});
|
||||
await this.recalculateObjectiveStatus(existing.objectiveId);
|
||||
return updated;
|
||||
}
|
||||
assertCanRead(ownerId, user) {
|
||||
if (user.role === 'EMPLOYEE' && ownerId !== user.sub) {
|
||||
throw new ForbiddenException('Key result belongs to another owner');
|
||||
}
|
||||
}
|
||||
assertCanWrite(ownerId, user) {
|
||||
if (user.role === 'EMPLOYEE' && ownerId !== user.sub) {
|
||||
throw new ForbiddenException('Only the owner can update this key result');
|
||||
}
|
||||
}
|
||||
async recalculateObjectiveStatus(objectiveId) {
|
||||
const keyResults = await this.prisma.keyResult.findMany({ where: { objectiveId } });
|
||||
const average = keyResults.length === 0
|
||||
? 0
|
||||
: Math.round(keyResults.reduce((total, keyResult) => total + keyResult.progress, 0) / keyResults.length);
|
||||
const status = average === 0 ? 'NOT_STARTED' : average >= 100 ? 'COMPLETED' : 'IN_PROGRESS';
|
||||
await this.prisma.objective.update({ where: { id: objectiveId }, data: { status } });
|
||||
}
|
||||
};
|
||||
KeyResultsService = __decorate([
|
||||
Injectable(),
|
||||
__param(0, Inject(PrismaService)),
|
||||
__metadata("design:paramtypes", [PrismaService])
|
||||
], KeyResultsService);
|
||||
export { KeyResultsService };
|
||||
Reference in New Issue
Block a user