Add attendance and visit management features with database schema updates
- Introduced new `attendances` and `visits` tables to manage employee attendance and customer visits, including relevant fields for check-in and check-out details. - Updated `company_settings` to include a `check_in_radius_meters` column for attendance validation. - Implemented foreign key constraints to ensure data integrity between `attendances`, `visits`, `employees`, `branches`, and other related entities. - Created new services and controllers for handling attendance and visit operations, including check-in, check-out, and bulk actions. - Enhanced DTOs for attendance and visit data transfer, including validation for input data. - Added unit and integration tests to validate the new functionalities and ensure proper handling of attendance and visit records. - Created migration scripts to apply the necessary database schema changes for the new features.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
HttpCode,
|
||||
Param,
|
||||
ParseUUIDPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ApiBearerAuth,
|
||||
ApiCreatedResponse,
|
||||
ApiForbiddenResponse,
|
||||
ApiNoContentResponse,
|
||||
ApiNotFoundResponse,
|
||||
ApiOkResponse,
|
||||
ApiOperation,
|
||||
ApiTags,
|
||||
ApiUnauthorizedResponse,
|
||||
} from '@nestjs/swagger';
|
||||
import { CurrentUser } from '../../../common/decorators/current-user.decorator';
|
||||
import { RequirePrivilege } from '../../../common/decorators/require-privilege.decorator';
|
||||
import { BEARER_AUTH_NAME } from '../../../common/swagger/setup-swagger';
|
||||
import { FIELD_ATTENDANCE_PRIVILEGE_KEY } from '../shared/field-purpose';
|
||||
import {
|
||||
AttendanceCheckInDto,
|
||||
AttendanceCheckOutDto,
|
||||
AttendanceDto,
|
||||
BulkIdsDto,
|
||||
BulkStatusDto,
|
||||
UpdateAttendanceStatusDto,
|
||||
} from './dto/attendance.dto';
|
||||
import { AttendancesService } from './attendances.service';
|
||||
|
||||
@ApiTags('attendances')
|
||||
@ApiBearerAuth(BEARER_AUTH_NAME)
|
||||
@Controller('attendances')
|
||||
export class AttendancesWriteController {
|
||||
constructor(private readonly attendancesService: AttendancesService) {}
|
||||
|
||||
@Post('check-in')
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'create')
|
||||
@ApiOperation({ summary: 'Check in at a branch' })
|
||||
@ApiCreatedResponse({ type: AttendanceDto })
|
||||
@ApiUnauthorizedResponse()
|
||||
@ApiForbiddenResponse()
|
||||
checkIn(
|
||||
@Body() dto: AttendanceCheckInDto,
|
||||
@CurrentUser('id') userId: string,
|
||||
): Promise<AttendanceDto> {
|
||||
return this.attendancesService.checkIn(dto, userId);
|
||||
}
|
||||
|
||||
@Post('bulk-delete')
|
||||
@HttpCode(200)
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'delete')
|
||||
@ApiOperation({ summary: 'Bulk delete attendances' })
|
||||
@ApiOkResponse({ schema: { properties: { deleted: { type: 'number' } } } })
|
||||
bulkDelete(@Body() dto: BulkIdsDto): Promise<{ deleted: number }> {
|
||||
return this.attendancesService.bulkDelete(dto.ids);
|
||||
}
|
||||
|
||||
@Post('bulk-status')
|
||||
@HttpCode(200)
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'update')
|
||||
@ApiOperation({ summary: 'Bulk update attendance status' })
|
||||
@ApiOkResponse({ schema: { properties: { updated: { type: 'number' } } } })
|
||||
bulkStatus(
|
||||
@Body() dto: BulkStatusDto,
|
||||
@CurrentUser('id') userId: string,
|
||||
): Promise<{ updated: number }> {
|
||||
return this.attendancesService.bulkUpdateStatus(
|
||||
dto.ids,
|
||||
dto.status,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
@Post(':id/check-out')
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'update')
|
||||
@ApiOperation({ summary: 'Check out from a branch shift' })
|
||||
@ApiOkResponse({ type: AttendanceDto })
|
||||
@ApiNotFoundResponse()
|
||||
@ApiUnauthorizedResponse()
|
||||
@ApiForbiddenResponse()
|
||||
checkOut(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: AttendanceCheckOutDto,
|
||||
@CurrentUser('id') userId: string,
|
||||
): Promise<AttendanceDto> {
|
||||
return this.attendancesService.checkOut(id, dto, userId);
|
||||
}
|
||||
|
||||
@Patch(':id/status')
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'update')
|
||||
@ApiOperation({ summary: 'Update attendance status' })
|
||||
@ApiOkResponse({ type: AttendanceDto })
|
||||
updateStatus(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: UpdateAttendanceStatusDto,
|
||||
@CurrentUser('id') userId: string,
|
||||
): Promise<AttendanceDto> {
|
||||
return this.attendancesService.updateStatus(id, dto.status, userId);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@HttpCode(204)
|
||||
@RequirePrivilege(FIELD_ATTENDANCE_PRIVILEGE_KEY, 'delete')
|
||||
@ApiOperation({ summary: 'Delete attendance' })
|
||||
@ApiNoContentResponse()
|
||||
@ApiNotFoundResponse()
|
||||
delete(@Param('id', ParseUUIDPipe) id: string): Promise<void> {
|
||||
return this.attendancesService.delete(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user