Skip to content

Commit

Permalink
feat: [Contracts] Add rejection on volunteer get one contract
Browse files Browse the repository at this point in the history
  • Loading branch information
radulescuandrew committed Oct 1, 2024
1 parent da540ed commit e92fd31
Show file tree
Hide file tree
Showing 14 changed files with 418 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { GetManyContractsByVolunteerDto } from './dto/get-many-contracts-by-volu
import { DocumentContractListViewItemPresenter } from 'src/api/documents/presenters/document-contract-list-view-item.presenter';
import { PaginatedPresenter } from 'src/infrastructure/presenters/generic-paginated.presenter';
import { GetOneDocumentContractForVolunteerUsecase } from 'src/usecases/documents/new_contracts/get-one-document-contract-for-volunteer.usecase';
import { DocumentContractItemMobilePresenter } from './presenters/document-contract-item-mobile.presenter';

// @UseGuards(MobileJwtAuthGuard, ContractVolunteerGuard)
@UseGuards(MobileJwtAuthGuard)
Expand Down Expand Up @@ -53,15 +54,15 @@ export class MobileDocumentsContractController {
@ExtractUser() { id }: IRegularUserModel,
@Param('contractId', UuidValidationPipe) contractId: string,
@Query('organizationId', UuidValidationPipe) organizationId: string,
): Promise<DocumentContractListViewItemPresenter> {
): Promise<DocumentContractItemMobilePresenter> {
const contract =
await this.getOneDocumentContractForVolunteerUsecase.execute({
documentContractId: contractId,
userId: id,
organizationId,
});

return new DocumentContractListViewItemPresenter(contract);
return new DocumentContractItemMobilePresenter(contract);
}

@ApiParam({ name: 'contractId', type: 'string' })
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { DocumentContractComputedStatuses } from 'src/modules/documents/enums/contract-status.enum';
import { IDocumentContractItemModel } from 'src/modules/documents/models/document-contract-item-view.model';

export class DocumentContractItemMobilePresenter {
constructor(item: IDocumentContractItemModel) {
this.documentId = item.documentId;
this.documentNumber = item.documentNumber;
this.documentStartDate = item.documentStartDate;
this.documentEndDate = item.documentEndDate;
this.documentFilePath = item.documentFilePath;
this.status = item.status;
this.volunteerId = item.volunteerId;
this.volunteerName = item.volunteerName;

this.organizationId = item.organizationId;
this.organizationName = item.organizationName;

this.rejectedByName = item.rejectedByName;
this.rejectionDate = item.rejectionDate;
this.rejectionReason = item.rejectionReason;
}

@Expose()
@ApiProperty({
description: 'The uuid of the template',
example: '525dcdf9-4117-443e-a0c3-bf652cdc5c1b',
})
documentId: string;

@Expose()
@ApiProperty({
description: 'The document number',
example: '123456',
})
documentNumber: string;

@Expose()
@ApiProperty({
description: 'The document start date',
example: '2021-01-01',
})
documentStartDate: Date;

@Expose()
@ApiProperty({
description: 'The document end date',
example: '2021-01-01',
})
documentEndDate: Date;

@Expose()
@ApiProperty({
description: 'The document file path',
example: 'https://example.com/document.pdf',
})
documentFilePath: string;

@Expose()
@ApiProperty({
description: 'The document status',
example: 'CREATED',
})
status: DocumentContractComputedStatuses;

@Expose()
@ApiProperty({
description: 'The volunteer id',
example: '525dcdf9-4117-443e-a0c3-bf652cdc5c1b',
})
volunteerId: string;

@Expose()
@ApiProperty({
description: 'The volunteer name',
example: 'John Doe',
})
volunteerName: string;

@Expose()
@ApiProperty({
description: 'The organization id',
example: '525dcdf9-4117-443e-a0c3-bf652cdc5c1b',
})
organizationId: string;

@Expose()
@ApiProperty({
description: 'The organization name',
example: 'John Doe',
})
organizationName: string;

@Expose()
@ApiProperty({
description: 'The rejected by name',
example: 'John Doe',
})
rejectedByName: string;

@Expose()
@ApiProperty({
description: 'The rejection date',
example: '2021-01-01',
})
rejectionDate: Date;

@Expose()
@ApiProperty({
description: 'The rejection reason',
example: 'The personal data is not valid',
})
rejectionReason: string;
}
8 changes: 4 additions & 4 deletions backend/src/api/documents/document-contract.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { ValidateDocumentContractByNgoUsecase } from 'src/usecases/documents/new
import { SignDocumentContractByNgoUsecase } from 'src/usecases/documents/new_contracts/sign-document-contract-by-ngo.usecase';
import { RejectDocumentContractByNgoUsecase } from 'src/usecases/documents/new_contracts/reject-document-contract-by-ngo.usecase';
import { RejectDocumentContractByNgoDTO } from './dto/reject-document-contract.dto';
import { DocumentContractWebItemPresenter } from './presenters/document-contract-web-item.presenter';
import { DocumentContractItemPresenter } from './presenters/document-contract-item.presenter';
import { GetOneDocumentContractForNgoUsecase } from 'src/usecases/documents/new_contracts/get-one-document-contract-for-ngo.usecase';
import { DocumentContractStatisticsPresenter } from './presenters/document-contract-statistics.presenter';
import { GetDocumentContractStatisticsUsecase } from 'src/usecases/documents/new_contracts/get-document-contract-statistics.usecase';
Expand Down Expand Up @@ -100,18 +100,18 @@ export class DocumentContractController {

@Get(':id')
@ApiResponse({
type: DocumentContractWebItemPresenter,
type: DocumentContractItemPresenter,
})
async getDocumentContract(
@Param('id', UuidValidationPipe) id: string,
@ExtractUser() { organizationId }: IAdminUserModel,
): Promise<DocumentContractWebItemPresenter> {
): Promise<DocumentContractItemPresenter> {
const documentContract =
await this.getOneDocumentContractForNgoUsecase.execute({
documentContractId: id,
organizationId,
});
return new DocumentContractWebItemPresenter(documentContract);
return new DocumentContractItemPresenter(documentContract);
}

@Patch(':id/approve')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { DocumentContractComputedStatuses } from 'src/modules/documents/enums/contract-status.enum';
import { IDocumentContractWebItemModel } from 'src/modules/documents/models/document-contract-web-item.model';
import { IDocumentContractItemModel } from 'src/modules/documents/models/document-contract-item-view.model';

export class DocumentContractWebItemPresenter {
constructor(item: IDocumentContractWebItemModel) {
export class DocumentContractItemPresenter {
constructor(item: IDocumentContractItemModel) {
this.documentId = item.documentId;
this.documentNumber = item.documentNumber;
this.documentStartDate = item.documentStartDate;
Expand All @@ -13,7 +13,10 @@ export class DocumentContractWebItemPresenter {
this.status = item.status;
this.volunteerId = item.volunteerId;
this.volunteerName = item.volunteerName;

this.organizationId = item.organizationId;
this.organizationName = item.organizationName;

this.createdByAdminId = item.createdByAdminId;
this.createdByAdminName = item.createdByAdminName;

Expand Down Expand Up @@ -91,6 +94,13 @@ export class DocumentContractWebItemPresenter {
})
organizationId: string;

@Expose()
@ApiProperty({
description: 'The name of the organization',
example: 'Code4Romania',
})
organizationName: string;

@Expose()
@ApiProperty({
description:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddOrganizationNameToContractItem1727777526306
implements MigrationInterface
{
name = 'AddOrganizationNameToContractItem1727777526306';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'DocumentContractListView', 'public'],
);
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'DocumentContractWebItemView', 'public'],
);
await queryRunner.query(`DROP VIEW "DocumentContractListView"`);
await queryRunner.query(`DROP VIEW "DocumentContractWebItemView"`);

await queryRunner.query(`CREATE VIEW "DocumentContractItemView" AS
SELECT
dc.id as "document_id",
dc.document_number,
dc.document_start_date,
dc.document_end_date,
CASE
WHEN dc.status = 'APPROVED' AND
dc.document_start_date <= CURRENT_DATE AND
dc.document_end_date >= CURRENT_DATE
THEN 'ACTIVE'
WHEN dc.status = 'APPROVED' AND
dc.document_start_date > CURRENT_DATE
THEN 'NOT_STARTED'
WHEN dc.status = 'APPROVED' AND
dc.document_end_date < CURRENT_DATE
THEN 'EXPIRED'
ELSE dc.status::text
END AS "status",
dc.file_path as "document_file_path",
dc.document_template_id,
dt."name" as "document_template_name",
dc.volunteer_id,
dc.volunteer_data->>'name' as "volunteer_name",
dc.created_by_admin_id,
"adminUser"."name" as "created_by_admin_name",
dc.rejection_date,
dc.rejection_reason,
dc.rejected_by_id,
"rejectionUser".name as "rejected_by_name",
dc.organization_id,
o.name as "organization_name",
dc.created_on,
dc.updated_on
FROM
document_contract dc
LEFT JOIN volunteer v ON v.id = dc.id
LEFT JOIN document_template dt on dt.id = dc.document_template_id
LEFT JOIN "user" "adminUser" ON dc.created_by_admin_id = "adminUser".id
LEFT JOIN "user" "rejectionUser" ON dc.rejected_by_id = "rejectionUser".id
LEFT JOIN "organization" o ON dc.organization_id = o.id
`);
await queryRunner.query(
`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`,
[
'public',
'VIEW',
'DocumentContractItemView',
'SELECT\n dc.id as "document_id",\n dc.document_number,\n dc.document_start_date,\n dc.document_end_date,\n CASE \n WHEN dc.status = \'APPROVED\' AND \n dc.document_start_date <= CURRENT_DATE AND \n dc.document_end_date >= CURRENT_DATE \n THEN \'ACTIVE\'\n WHEN dc.status = \'APPROVED\' AND \n dc.document_start_date > CURRENT_DATE \n THEN \'NOT_STARTED\'\n WHEN dc.status = \'APPROVED\' AND \n dc.document_end_date < CURRENT_DATE \n THEN \'EXPIRED\'\n ELSE dc.status::text\n END AS "status",\n dc.file_path as "document_file_path",\n dc.document_template_id,\n dt."name" as "document_template_name",\n dc.volunteer_id,\n dc.volunteer_data->>\'name\' as "volunteer_name",\n dc.created_by_admin_id, \n "adminUser"."name" as "created_by_admin_name",\n \n dc.rejection_date,\n dc.rejection_reason,\n dc.rejected_by_id,\n "rejectionUser".name as "rejected_by_name",\n\n dc.organization_id,\n o.name as "organization_name",\n\n dc.created_on, \n dc.updated_on\n FROM\n document_contract dc\n LEFT JOIN volunteer v ON v.id = dc.id\n LEFT JOIN document_template dt on dt.id = dc.document_template_id\n LEFT JOIN "user" "adminUser" ON dc.created_by_admin_id = "adminUser".id\n LEFT JOIN "user" "rejectionUser" ON dc.rejected_by_id = "rejectionUser".id\n LEFT JOIN "organization" o ON dc.organization_id = o.id',
],
);
await queryRunner.query(`CREATE VIEW "DocumentContractListView" AS
SELECT document_contract.id AS document_id,
document_contract.document_number,
CASE
WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_start_date <= CURRENT_DATE AND document_contract.document_end_date >= CURRENT_DATE THEN 'ACTIVE'::text
WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_start_date > CURRENT_DATE THEN 'NOT_STARTED'::text
WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_end_date < CURRENT_DATE THEN 'EXPIRED'::text
ELSE document_contract.status::text
END AS status,
document_contract.document_start_date,
document_contract.document_end_date,
document_contract.file_path AS document_file_path,
organization.id AS organization_id,
organization.name AS organization_name,
volunteer.id AS volunteer_id,
"user".name AS volunteer_name
FROM document_contract
JOIN volunteer ON document_contract.volunteer_id = volunteer.id
JOIN "user" ON "user".id = volunteer.user_id
JOIN organization ON document_contract.organization_id = organization.id;
`);
await queryRunner.query(
`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`,
[
'public',
'VIEW',
'DocumentContractListView',
"SELECT document_contract.id AS document_id,\n document_contract.document_number,\n CASE\n WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_start_date <= CURRENT_DATE AND document_contract.document_end_date >= CURRENT_DATE THEN 'ACTIVE'::text\n WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_start_date > CURRENT_DATE THEN 'NOT_STARTED'::text\n WHEN document_contract.status = 'APPROVED'::document_contract_status_enum AND document_contract.document_end_date < CURRENT_DATE THEN 'EXPIRED'::text\n ELSE document_contract.status::text\n END AS status,\n document_contract.document_start_date,\n document_contract.document_end_date,\n document_contract.file_path AS document_file_path,\n organization.id AS organization_id,\n organization.name AS organization_name,\n volunteer.id AS volunteer_id,\n \"user\".name AS volunteer_name\n FROM document_contract\n JOIN volunteer ON document_contract.volunteer_id = volunteer.id\n JOIN \"user\" ON \"user\".id = volunteer.user_id\n JOIN organization ON document_contract.organization_id = organization.id;",
],
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'DocumentContractListView', 'public'],
);
await queryRunner.query(`DROP VIEW "DocumentContractListView"`);
await queryRunner.query(
`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`,
['VIEW', 'DocumentContractItemView', 'public'],
);
await queryRunner.query(`DROP VIEW "DocumentContractItemView"`);
await queryRunner.query(`CREATE VIEW "DocumentContractListView" AS SELECT
document_contract.id AS document_id,
document_contract.document_number,
CASE
WHEN document_contract.status = 'APPROVED' AND
document_contract.document_start_date <= CURRENT_DATE AND
document_contract.document_end_date >= CURRENT_DATE
THEN 'ACTIVE'
WHEN document_contract.status = 'APPROVED' AND
document_contract.document_start_date > CURRENT_DATE
THEN 'NOT_STARTED'
WHEN document_contract.status = 'APPROVED' AND
document_contract.document_end_date < CURRENT_DATE
THEN 'EXPIRED'
ELSE document_contract.status::text
END AS "status",
document_contract.document_start_date,
document_contract.document_end_date,
document_contract.file_path AS document_file_path,
organization.id AS organization_id,
organization.name AS organization_name,
volunteer.id AS volunteer_id,
"user".name AS volunteer_name
FROM document_contract
JOIN volunteer ON document_contract.volunteer_id = volunteer.id
JOIN "user" ON "user".id = volunteer.user_id
JOIN organization ON document_contract.organization_id = organization.id;`);
await queryRunner.query(
`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`,
[
'public',
'VIEW',
'DocumentContractListView',
"SELECT \n document_contract.id AS document_id,\n document_contract.document_number,\n\n \n CASE \n WHEN document_contract.status = 'APPROVED' AND \n document_contract.document_start_date <= CURRENT_DATE AND \n document_contract.document_end_date >= CURRENT_DATE \n THEN 'ACTIVE'\n WHEN document_contract.status = 'APPROVED' AND \n document_contract.document_start_date > CURRENT_DATE \n THEN 'NOT_STARTED'\n WHEN document_contract.status = 'APPROVED' AND \n document_contract.document_end_date < CURRENT_DATE \n THEN 'EXPIRED'\n ELSE document_contract.status::text\n END AS \"status\",\n\n document_contract.document_start_date,\n document_contract.document_end_date,\n document_contract.file_path AS document_file_path,\n organization.id AS organization_id,\n organization.name AS organization_name,\n volunteer.id AS volunteer_id,\n \"user\".name AS volunteer_name\n FROM document_contract\n JOIN volunteer ON document_contract.volunteer_id = volunteer.id\n JOIN \"user\" ON \"user\".id = volunteer.user_id\n JOIN organization ON document_contract.organization_id = organization.id;",
],
);
}
}
8 changes: 4 additions & 4 deletions backend/src/modules/documents/documents.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import { DocumentTemplateListViewEntity } from './entities/document-template-lis
import { DocumentTemplateListViewRepository } from './repositories/document-template-list-view.repository';
import { DocumentSignatureRepository } from './repositories/document-signature.repository';
import { DocumentSignatureFacade } from './services/document-signature.facade';
import { DocumentContractWebItemView } from './entities/document-contract-web-item.entity';
import { DocumentContractWebItemRepository } from './repositories/document-contract-web-item.repository';
import { DocumentContractItemView } from './entities/document-contract-web-item.entity';
import { DocumentContractItemRepository } from './repositories/document-contract-item-view.repository';
import { CronsService } from './services/crons.service';

@Module({
imports: [
TypeOrmModule.forFeature([
DocumentContractListViewEntity,
DocumentContractWebItemView,
DocumentContractItemView,
DocumentTemplateListViewEntity,
TemplateEntity,
ContractEntity,
Expand All @@ -46,7 +46,7 @@ import { CronsService } from './services/crons.service';
DocumentSignatureRepository,
DocumentContractListViewRepository,
DocumentTemplateListViewRepository,
DocumentContractWebItemRepository,
DocumentContractItemRepository,
// Facades
TemplateFacade,
ContractFacade,
Expand Down
Loading

0 comments on commit e92fd31

Please sign in to comment.