Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions backend/src/migrations/1723119327053-ApplicationLabel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

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

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "_application-label" ("id" SERIAL NOT NULL, "deleted_on" TIMESTAMP WITH TIME ZONE, "created_on" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_on" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "name" text NOT NULL, CONSTRAINT "PK_c0aaf1127ad3beeaf0d3ad70096" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`CREATE INDEX "IDX_e4a4e4b1582c4e665cff9be33e" ON "_application-label" ("created_on") `,
);
await queryRunner.query(
`ALTER TABLE "application" ADD "application_label_id" integer`,
);
await queryRunner.query(
`ALTER TABLE "application" ADD CONSTRAINT "FK_318029631a770782ba1c66721fd" FOREIGN KEY ("application_label_id") REFERENCES "_application-label"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "application" DROP CONSTRAINT "FK_318029631a770782ba1c66721fd"`,
);
await queryRunner.query(
`ALTER TABLE "application" DROP COLUMN "application_label_id"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_e4a4e4b1582c4e665cff9be33e"`,
);
await queryRunner.query(`DROP TABLE "_application-label"`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const ORGANIZATION_ALL_APPS_COLUMNS = [
'ongApp.status as "ongStatus"',
'ongApp.created_on as "createdOn"',
'application.type as type',
'applicationLabel.name as "applicationLabel"',
];

export const APPLICATIONS_FILES_DIR = 'applications';
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,6 @@ export class ApplicationController {
);
}

@Roles(Role.SUPER_ADMIN)
Comment thread
radulescuandrew marked this conversation as resolved.
@ApiParam({ name: 'id', type: String })
@Patch(':id/activate')
activate(@Param('id') id: number) {
return this.appService.update(id, {
status: ApplicationStatus.ACTIVE,
});
}

@Roles(Role.SUPER_ADMIN)
@ApiParam({ name: 'id', type: String })
@Patch(':id/deactivate')
deactivate(@Param('id') id: number) {
return this.appService.update(id, {
status: ApplicationStatus.DISABLED,
});
}

@Roles(Role.SUPER_ADMIN)
@ApiParam({ name: 'id', type: String })
@ApiQuery({ type: () => ApplicationAccessFilterDto })
Expand Down
4 changes: 4 additions & 0 deletions backend/src/modules/application/dto/create-application.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { REGEX } from 'src/common/constants/patterns.constant';
import { ApplicationPullingType } from '../enums/application-pulling-type.enum';
import { ApplicationTypeEnum } from '../enums/ApplicationType.enum';
import { ApplicationLabel } from 'src/shared/entities/application-labels.entity';

export class CreateApplicationDto {
@IsString()
Expand Down Expand Up @@ -56,4 +57,7 @@ export class CreateApplicationDto {
@IsOptional()
@Length(2, 100, { each: true })
steps?: string[];

@IsOptional()
applicationLabel: Partial<ApplicationLabel>;
Comment thread
radulescuandrew marked this conversation as resolved.
}
17 changes: 16 additions & 1 deletion backend/src/modules/application/entities/application.entity.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { BaseEntity } from 'src/common/base/base-entity.class';
import { Column, Entity, OneToMany } from 'typeorm';
import {
Column,
Entity,
JoinColumn,
JoinTable,
ManyToOne,
OneToMany,
} from 'typeorm';
import { ApplicationPullingType } from '../enums/application-pulling-type.enum';
import { ApplicationStatus } from '../enums/application-status.enum';
import { ApplicationTypeEnum } from '../enums/ApplicationType.enum';
import { OngApplication } from './ong-application.entity';
import { ApplicationLabel } from 'src/shared/entities/application-labels.entity';

@Entity()
export class Application extends BaseEntity {
Expand Down Expand Up @@ -60,4 +68,11 @@ export class Application extends BaseEntity {

@OneToMany(() => OngApplication, (ongApp) => ongApp.application)
ongApplications: OngApplication[];

@Column({ type: 'integer', name: 'application_label_id', nullable: true })
applicationLabelId: number;

@ManyToOne((type) => ApplicationLabel)
@JoinColumn({ name: 'application_label_id' })
applicationLabel: ApplicationLabel;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ApplicationLabel } from 'src/shared/entities/application-labels.entity';
import { ApplicationPullingType } from '../enums/application-pulling-type.enum';
import { ApplicationStatus } from '../enums/application-status.enum';
import { ApplicationTypeEnum } from '../enums/ApplicationType.enum';
Expand All @@ -23,4 +24,5 @@ export interface IOngApplicationDetails extends IOngApplication {
videoLink: string;
userStatus: UserOngApplicationStatus;
pullingType: ApplicationPullingType;
applicationLabel: ApplicationLabel;
}
45 changes: 44 additions & 1 deletion backend/src/modules/application/services/application.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { ApplicationTableViewRepository } from '../repositories/application-tabl
import { ApplicationRepository } from '../repositories/application.repository';
import { OngApplicationRepository } from '../repositories/ong-application.repository';
import { UserOngApplicationRepository } from '../repositories/user-ong-application.repository';
import { ApplicationLabel } from 'src/shared/entities/application-labels.entity';
import { NomenclaturesService } from 'src/shared/services';

@Injectable()
export class ApplicationService {
Expand All @@ -49,6 +51,7 @@ export class ApplicationService {
private readonly ongApplicationRepository: OngApplicationRepository,
private readonly userOngApplicationRepository: UserOngApplicationRepository,
private readonly applicationOngViewRepository: ApplicationOngViewRepository,
private readonly nomenclatureService: NomenclaturesService,
) {}

public async create(
Expand Down Expand Up @@ -250,6 +253,7 @@ export class ApplicationService {
'application.video_link as "videoLink"',
'application.pulling_type as "pullingType"',
'application.status as "applicationStatus"',
'applicationLabel',
])
.leftJoin(
'ong_application',
Expand All @@ -262,6 +266,11 @@ export class ApplicationService {
'userOngApp',
'userOngApp.ong_application_id = ongApp.id',
)
.leftJoin(
'_application-label',
'applicationLabel',
'applicationLabel.id = application.application_label_id',
)
.where('application.id = :applicationId', { applicationId });

// for employee add further filtersin by user id
Expand Down Expand Up @@ -292,8 +301,19 @@ export class ApplicationService {
);
}

const applicationLabel = {
id: applicationWithDetails.applicationLabel_id,
name: applicationWithDetails.applicationLabel_name,
};

delete applicationWithDetails.applicationLabel_id;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nu putem face queryul direct cu id si name ca aliasuri ca sa nu mai facem delete-uri?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Este getRawOne, n-am cum sa le scot direct in object.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, am inteles ca vrei sa le pui intr-un obiect direct.

Deci chiar daca facem

        'applicationLabel.id as "applicationLabelId"',
        'applicationLabel.name as "applicationLabelName"',

Tot trebuie sa le stergi apoi din applicationWithDetails cele 2 props.

@dragos1195 Totusi, mai lipseste applicationLabel din interfata IOngApplicationDetails

delete applicationWithDetails.applicationLabel_name;
delete applicationWithDetails.applicationLabel_created_on;
delete applicationWithDetails.applicationLabel_updated_on;

return {
...applicationWithDetails,
applicationLabel,
logo,
};
}
Expand Down Expand Up @@ -346,7 +366,17 @@ export class ApplicationService {
};
}

return this.applicationRepository.update({ id }, applicationPayload);
let applicationLabel = null;
if (applicationPayload.applicationLabel) {
applicationLabel = await this.saveAndGetApplicationLabel(
applicationPayload.applicationLabel,
);
}

return this.applicationRepository.update(
{ id },
{ ...applicationPayload, applicationLabel },
);
} catch (error) {
this.logger.error({
error: { error },
Expand Down Expand Up @@ -502,4 +532,17 @@ export class ApplicationService {

return applicationCount;
}

private async saveAndGetApplicationLabel(
label: Partial<ApplicationLabel>,
): Promise<ApplicationLabel> {
if (label.id) {
return label as ApplicationLabel;
}

const newLabel =
await this.nomenclatureService.createApplicationLabel(label);

return newLabel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,19 @@ export class OngApplicationService {
: OngApplicationStatus.ACTIVE,
});

if(application.type === ApplicationTypeEnum.STANDALONE) {
if (application.type === ApplicationTypeEnum.STANDALONE) {
// 8. trigger emails for admin and super-admin
this.eventEmitter.emit(
EVENTS.REQUEST_APPLICATION_ACCESS,
new ApplicationRequestEvent(organizationId, application.name),
);
}


return ongApp;
} catch (error) {
Sentry.captureException(error, {
extra: {organizationId, applicationId},
})
extra: { organizationId, applicationId },
});
this.logger.error({ error: { error }, ...ONG_APPLICATION_ERRORS.CREATE });
const err = error?.response;
throw new BadRequestException({
Expand Down Expand Up @@ -174,6 +173,11 @@ export class OngApplicationService {
const applicationsQuery = this.applicationRepository
.getQueryBuilder()
.select(ORGANIZATION_ALL_APPS_COLUMNS)
.leftJoin(
'_application-label',
'applicationLabel',
'applicationLabel.id = application.application_label_id',
)
.leftJoin(
'ong_application',
'ongApp',
Expand Down
19 changes: 18 additions & 1 deletion backend/src/shared/controllers/nomenclatures.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,69 +13,86 @@ import { NomenclaturesService } from '../services';
import { CacheInterceptor } from '@nestjs/cache-manager';

@Public()
@UseInterceptors(ClassSerializerInterceptor, CacheInterceptor)
@UseInterceptors(ClassSerializerInterceptor)
@Controller('nomenclatures')
export class NomenclaturesController {
constructor(private nomenclaturesService: NomenclaturesService) {}

@Get('cities')
@UseInterceptors(CacheInterceptor)
getCities(@Query() citySearchDto: CitySearchDto) {
return this.nomenclaturesService.getCitiesSearch(citySearchDto);
}

@Get('counties')
@UseInterceptors(CacheInterceptor)
getCounties() {
return this.nomenclaturesService.getCounties({});
}

@Get('domains')
@UseInterceptors(CacheInterceptor)
getDomains() {
return this.nomenclaturesService.getDomains({});
}

@Get('regions')
@UseInterceptors(CacheInterceptor)
getRegions() {
return this.nomenclaturesService.getRegions({});
}

@Get('federations')
@UseInterceptors(CacheInterceptor)
getFederations() {
return this.nomenclaturesService.getFederations({});
}

@Get('coalitions')
@UseInterceptors(CacheInterceptor)
getCoalitions() {
return this.nomenclaturesService.getCoalitions({});
}

@Get('faculties')
@UseInterceptors(CacheInterceptor)
getFaculties(@Query() { search }: FacultySearchDto) {
const options = search ? { where: { name: ILike(`%${search}%`) } } : {};
return this.nomenclaturesService.getFaculties(options);
}

@Get('skills')
@UseInterceptors(CacheInterceptor)
getSkills() {
return this.nomenclaturesService.getSkills({});
}

@Get('practice-domains')
@UseInterceptors(CacheInterceptor)
getPracticeDomains() {
return this.nomenclaturesService.getPracticeDomains({});
}

@Get('service-domains')
@UseInterceptors(CacheInterceptor)
getServiceDomains() {
return this.nomenclaturesService.getServiceDomains({});
}

@Get('beneficiaries')
@UseInterceptors(CacheInterceptor)
getBeneficiaries() {
return this.nomenclaturesService.getBeneficiaries({});
}

@Get('issuers')
@UseInterceptors(CacheInterceptor)
getIssuers() {
return this.nomenclaturesService.getIssuers({});
}

@Get('application-labels')
getApplicationLabels() {
return this.nomenclaturesService.getApplicationLabels({});
}
}
8 changes: 8 additions & 0 deletions backend/src/shared/entities/application-labels.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { BaseEntity } from 'src/common/base/base-entity.class';
import { Column, Entity } from 'typeorm';

@Entity({ name: '_application-label' })
export class ApplicationLabel extends BaseEntity {
@Column({ type: 'text', name: 'name' })
name: string;
}
13 changes: 13 additions & 0 deletions backend/src/shared/services/nomenclatures.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Federation } from '../entities/federation.entity';
import { PracticeDomain } from 'src/modules/practice-program/entities/practice_domain.entity';
import { ServiceDomain } from 'src/modules/civic-center-service/entities/service-domain.entity';
import { Beneficiary } from 'src/modules/civic-center-service/entities/beneficiary.entity';
import { ApplicationLabel } from '../entities/application-labels.entity';

@Injectable()
export class NomenclaturesService {
Expand Down Expand Up @@ -45,6 +46,8 @@ export class NomenclaturesService {
private readonly beneficiaryRepository: Repository<Beneficiary>,
@InjectRepository(Issuer)
private readonly issuersRepository: Repository<Issuer>,
@InjectRepository(ApplicationLabel)
private readonly applicationLabelRepository: Repository<ApplicationLabel>,
) {}

public getCity(conditions: FindOneOptions<City>) {
Expand Down Expand Up @@ -169,4 +172,14 @@ export class NomenclaturesService {
public getIssuers(conditions: FindManyOptions<Issuer>) {
return this.issuersRepository.find(conditions);
}

public getApplicationLabels(conditions: FindManyOptions<ApplicationLabel>) {
return this.applicationLabelRepository.find(conditions);
}

public createApplicationLabel(
applicationLabel: Partial<ApplicationLabel>,
): Promise<ApplicationLabel> {
return this.applicationLabelRepository.save(applicationLabel);
}
}
2 changes: 2 additions & 0 deletions backend/src/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { FileManagerService } from './services/file-manager.service';
import { PracticeDomain } from 'src/modules/practice-program/entities/practice_domain.entity';
import { ServiceDomain } from 'src/modules/civic-center-service/entities/service-domain.entity';
import { Beneficiary } from 'src/modules/civic-center-service/entities/beneficiary.entity';
import { ApplicationLabel } from './entities/application-labels.entity';

@Global()
@Module({
Expand All @@ -37,6 +38,7 @@ import { Beneficiary } from 'src/modules/civic-center-service/entities/beneficia
ServiceDomain,
Beneficiary,
Issuer,
ApplicationLabel,
]),
HttpModule,
],
Expand Down
Loading