-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #188 from fairnesscoop/feat/remove-leaev-request
Remove leave request
- Loading branch information
Showing
14 changed files
with
288 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<script> | ||
import { _ } from 'svelte-i18n'; | ||
import { createEventDispatcher } from 'svelte'; | ||
import TrashIcon from '../icons/TrashIcon.svelte'; | ||
export let confirmMessage = 'common.confirm.remove'; | ||
const dispatch = createEventDispatcher(); | ||
const handleClick = () => { | ||
if (confirm($_(confirmMessage))) { | ||
dispatch('confirm'); | ||
} | ||
} | ||
</script> | ||
|
||
<button | ||
on:click={handleClick} | ||
class="flex items-center justify-between px-2 text-sm font-medium leading-5 text-purple-600 rounded-lg dark:text-gray-400 focus:outline-none focus:shadow-outline-gray" | ||
aria-label={$_('common.form.remove')}> | ||
<TrashIcon className={'w-5 h-5'} /> | ||
</button> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
server/src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommand.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { ICommand } from 'src/Application/ICommand'; | ||
import { User } from 'src/Domain/HumanResource/User/User.entity'; | ||
|
||
export class DeleteLeaveRequestCommand implements ICommand { | ||
constructor( | ||
public readonly id: string, | ||
public readonly owner: User | ||
) {} | ||
} |
94 changes: 94 additions & 0 deletions
94
server/src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommandHandler.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { mock, instance, when, verify, anything, deepEqual } from 'ts-mockito'; | ||
import { DeleteLeaveRequestCommandHandler } from './DeleteLeaveRequestCommandHandler'; | ||
import { DeleteLeaveRequestCommand } from './DeleteLeaveRequestCommand'; | ||
import { User } from 'src/Domain/HumanResource/User/User.entity'; | ||
import { LeaveRequestNotFoundException } from 'src/Domain/HumanResource/Leave/Exception/LeaveRequestNotFoundException'; | ||
import { CanLeaveRequestBeRemoved } from 'src/Domain/HumanResource/Leave/Specification/CanLeaveRequestBeRemoved'; | ||
import { LeaveRequest } from 'src/Domain/HumanResource/Leave/LeaveRequest.entity'; | ||
import { LeaveRequestRepository } from 'src/Infrastructure/HumanResource/Leave/Repository/LeaveRequestRepository'; | ||
import { LeaveRequestCantBeRemovedException } from 'src/Domain/HumanResource/Leave/Exception/LeaveRequestCantBeRemovedException'; | ||
|
||
describe('DeleteLeaveRequestCommandHandler', () => { | ||
let leaveRequestRepository: LeaveRequestRepository; | ||
let canLeaveRequestBeRemoved: CanLeaveRequestBeRemoved; | ||
let handler: DeleteLeaveRequestCommandHandler; | ||
|
||
const user = mock(User); | ||
const leaveRequest = mock(LeaveRequest); | ||
const command = new DeleteLeaveRequestCommand( | ||
'cfdd06eb-cd71-44b9-82c6-46110b30ce05', | ||
instance(user) | ||
); | ||
|
||
beforeEach(() => { | ||
leaveRequestRepository = mock(LeaveRequestRepository); | ||
canLeaveRequestBeRemoved = mock(CanLeaveRequestBeRemoved); | ||
|
||
handler = new DeleteLeaveRequestCommandHandler( | ||
instance(leaveRequestRepository), | ||
instance(canLeaveRequestBeRemoved), | ||
); | ||
}); | ||
|
||
it('testLeaveRequestNotNotFound', async () => { | ||
when( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).thenResolve(null); | ||
|
||
try { | ||
expect(await handler.execute(command)).toBeUndefined(); | ||
} catch (e) { | ||
expect(e).toBeInstanceOf(LeaveRequestNotFoundException); | ||
expect(e.message).toBe('human_resources.leaves.requests.errors.not_found'); | ||
verify( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).once(); | ||
verify( | ||
canLeaveRequestBeRemoved.isSatisfiedBy(anything(), anything()) | ||
).never(); | ||
verify(leaveRequestRepository.remove(anything())).never(); | ||
} | ||
}); | ||
|
||
it('testLeaveRequestCantBeRemoved', async () => { | ||
when( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).thenResolve(instance(leaveRequest)); | ||
when( | ||
canLeaveRequestBeRemoved.isSatisfiedBy(instance(leaveRequest), instance(user)) | ||
).thenReturn(false); | ||
|
||
try { | ||
expect(await handler.execute(command)).toBeUndefined(); | ||
} catch (e) { | ||
expect(e).toBeInstanceOf(LeaveRequestCantBeRemovedException); | ||
expect(e.message).toBe('human_resources.leaves.requests.errors.cant_be_removed'); | ||
verify( | ||
canLeaveRequestBeRemoved.isSatisfiedBy(instance(leaveRequest), instance(user)) | ||
).once(); | ||
verify( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).once(); | ||
verify(leaveRequestRepository.remove(anything())).never(); | ||
} | ||
}); | ||
|
||
it('testLeaveSuccessfullyDeleted', async () => { | ||
when( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).thenResolve(instance(leaveRequest)); | ||
when( | ||
canLeaveRequestBeRemoved.isSatisfiedBy(instance(leaveRequest), instance(user)) | ||
).thenReturn(true); | ||
|
||
expect(await handler.execute(command)).toBeUndefined(); | ||
|
||
verify( | ||
canLeaveRequestBeRemoved.isSatisfiedBy(instance(leaveRequest), instance(user)) | ||
).once(); | ||
verify( | ||
leaveRequestRepository.findOneById('cfdd06eb-cd71-44b9-82c6-46110b30ce05') | ||
).once(); | ||
verify(leaveRequestRepository.remove(instance(leaveRequest))).once(); | ||
}); | ||
}); |
33 changes: 33 additions & 0 deletions
33
server/src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommandHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Inject } from '@nestjs/common'; | ||
import { CommandHandler } from '@nestjs/cqrs'; | ||
import { DeleteLeaveRequestCommand } from './DeleteLeaveRequestCommand'; | ||
import { ILeaveRequestRepository } from 'src/Domain/HumanResource/Leave/Repository/ILeaveRequestRepository'; | ||
import { LeaveRequestNotFoundException } from 'src/Domain/HumanResource/Leave/Exception/LeaveRequestNotFoundException'; | ||
import { CanLeaveRequestBeRemoved } from 'src/Domain/HumanResource/Leave/Specification/CanLeaveRequestBeRemoved'; | ||
import { LeaveRequestCantBeRemovedException } from 'src/Domain/HumanResource/Leave/Exception/LeaveRequestCantBeRemovedException'; | ||
|
||
@CommandHandler(DeleteLeaveRequestCommand) | ||
export class DeleteLeaveRequestCommandHandler { | ||
constructor( | ||
@Inject('ILeaveRequestRepository') | ||
private readonly leaveRequestRepository: ILeaveRequestRepository, | ||
private readonly canLeaveRequestBeRemoved: CanLeaveRequestBeRemoved | ||
) {} | ||
|
||
public async execute(command: DeleteLeaveRequestCommand): Promise<void> { | ||
const { owner, id } = command; | ||
|
||
const leaveRequest = await this.leaveRequestRepository.findOneById(id); | ||
if (!leaveRequest) { | ||
throw new LeaveRequestNotFoundException(); | ||
} | ||
|
||
if ( | ||
false === this.canLeaveRequestBeRemoved.isSatisfiedBy(leaveRequest, owner) | ||
) { | ||
throw new LeaveRequestCantBeRemovedException(); | ||
} | ||
|
||
this.leaveRequestRepository.remove(leaveRequest); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
server/src/Domain/HumanResource/Leave/Exception/LeaveRequestCantBeRemovedException.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export class LeaveRequestCantBeRemovedException extends Error { | ||
constructor() { | ||
super('human_resources.leaves.requests.errors.cant_be_removed'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
server/src/Domain/HumanResource/Leave/Specification/CanLeaveRequestBeRemoved.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { mock, instance, when } from 'ts-mockito'; | ||
import { User } from 'src/Domain/HumanResource/User/User.entity'; | ||
import { LeaveRequest } from '../LeaveRequest.entity'; | ||
import { CanLeaveRequestBeRemoved } from './CanLeaveRequestBeRemoved'; | ||
|
||
describe('CanLeaveRequestBeRemoved', () => { | ||
let canLeaveRequestBeRemoved: CanLeaveRequestBeRemoved; | ||
const user = mock(User); | ||
const leaveRequest = mock(LeaveRequest); | ||
const owner = mock(User); | ||
|
||
beforeEach(() => { | ||
canLeaveRequestBeRemoved = new CanLeaveRequestBeRemoved(); | ||
}); | ||
|
||
it('testLeaveRequestCantBeRemoved', async () => { | ||
when(user.getId()).thenReturn('cfdd06eb-cd71-44b9-82c6-46110b30ce05'); | ||
when(owner.getId()).thenReturn('50e624ef-3609-4053-a437-f74844a2d2de'); | ||
when(leaveRequest.getUser()).thenReturn(instance(user)); | ||
|
||
expect( | ||
await canLeaveRequestBeRemoved.isSatisfiedBy( | ||
instance(leaveRequest), | ||
instance(owner) | ||
) | ||
).toBe(false); | ||
}); | ||
|
||
it('testLeaveRequestCanBeRemoved', async () => { | ||
when(user.getId()).thenReturn('cfdd06eb-cd71-44b9-82c6-46110b30ce05'); | ||
when(owner.getId()).thenReturn('cfdd06eb-cd71-44b9-82c6-46110b30ce05'); | ||
when(leaveRequest.getUser()).thenReturn(instance(user)); | ||
|
||
expect( | ||
await canLeaveRequestBeRemoved.isSatisfiedBy( | ||
instance(leaveRequest), | ||
instance(owner) | ||
) | ||
).toBe(true); | ||
}); | ||
}); |
8 changes: 8 additions & 0 deletions
8
server/src/Domain/HumanResource/Leave/Specification/CanLeaveRequestBeRemoved.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { User } from '../../User/User.entity'; | ||
import { LeaveRequest } from '../LeaveRequest.entity'; | ||
|
||
export class CanLeaveRequestBeRemoved { | ||
public isSatisfiedBy(leaveRequest: LeaveRequest, user: User): boolean { | ||
return leaveRequest.getUser().getId() === user.getId(); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
server/src/Infrastructure/HumanResource/Leave/Action/DeleteLeaveRequestAction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { | ||
Controller, | ||
Inject, | ||
BadRequestException, | ||
UseGuards, | ||
Param, | ||
Delete | ||
} from '@nestjs/common'; | ||
import { AuthGuard } from '@nestjs/passport'; | ||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; | ||
import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO'; | ||
import { Roles } from 'src/Infrastructure/HumanResource/User/Decorator/Roles'; | ||
import { UserRole, User } from 'src/Domain/HumanResource/User/User.entity'; | ||
import { RolesGuard } from 'src/Infrastructure/HumanResource/User/Security/RolesGuard'; | ||
import { LoggedUser } from '../../User/Decorator/LoggedUser'; | ||
import { ICommandBus } from 'src/Application/ICommandBus'; | ||
import { DeleteLeaveRequestCommand } from 'src/Application/HumanResource/Leave/Command/DeleteLeaveRequestCommand'; | ||
|
||
@Controller('leave-requests') | ||
@ApiTags('Human Resource') | ||
@ApiBearerAuth() | ||
@UseGuards(AuthGuard('bearer'), RolesGuard) | ||
export class DeleteLeaveRequestAction { | ||
constructor( | ||
@Inject('ICommandBus') | ||
private readonly commandBus: ICommandBus | ||
) {} | ||
|
||
@Delete(':id') | ||
@Roles(UserRole.COOPERATOR) | ||
@ApiOperation({summary: 'Delete leave request'}) | ||
public async index(@Param() { id }: IdDTO, @LoggedUser() user: User) { | ||
try { | ||
await this.commandBus.execute(new DeleteLeaveRequestCommand(id, user)); | ||
} catch (e) { | ||
throw new BadRequestException(e.message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters