Генерация сообщений для новых задач
This commit is contained in:
parent
8dc886de49
commit
39fe3c7a79
3 changed files with 100 additions and 6 deletions
|
|
@ -5,6 +5,7 @@ import { TimestampEnhancer } from '@app/event-emitter/issue-enhancers/timestamps
|
||||||
import { MainController } from '@app/event-emitter/main/main.controller';
|
import { MainController } from '@app/event-emitter/main/main.controller';
|
||||||
import { Logger, Module, OnModuleInit } from '@nestjs/common';
|
import { Logger, Module, OnModuleInit } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { switchMap } from 'rxjs';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import configuration from './configs/app';
|
import configuration from './configs/app';
|
||||||
|
|
@ -43,6 +44,7 @@ export class AppModule implements OnModuleInit {
|
||||||
private timestampEnhancer: TimestampEnhancer,
|
private timestampEnhancer: TimestampEnhancer,
|
||||||
private customFieldsEnhancer: CustomFieldsEnhancer,
|
private customFieldsEnhancer: CustomFieldsEnhancer,
|
||||||
private currentUserEnhancer: CurrentUserEnhancer,
|
private currentUserEnhancer: CurrentUserEnhancer,
|
||||||
|
private statusChangeNotificationsService: StatusChangeNotificationsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
onModuleInit() {
|
onModuleInit() {
|
||||||
|
|
@ -51,14 +53,56 @@ export class AppModule implements OnModuleInit {
|
||||||
this.customFieldsEnhancer,
|
this.customFieldsEnhancer,
|
||||||
this.currentUserEnhancer,
|
this.currentUserEnhancer,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.personalNotificationsService.$messages.subscribe((message) => {
|
this.personalNotificationsService.$messages.subscribe((message) => {
|
||||||
// eslint-disable-next-line prettier/prettier
|
// eslint-disable-next-line prettier/prettier
|
||||||
this.logger.log(`Get personal message ${JSON.stringify(message.message)} for recipients ${JSON.stringify(message.recipients)}`);
|
this.logger.log(`Get personal message ${JSON.stringify(message.message)} for recipients ${JSON.stringify(message.recipients)}`);
|
||||||
});
|
});
|
||||||
|
this.statusChangeNotificationsService.$changes.subscribe((change) => {
|
||||||
|
this.logger.log(
|
||||||
|
`Get status changes messages for ` +
|
||||||
|
`issue_id = ${change.issue_id}, ` +
|
||||||
|
`messages = ${JSON.stringify(
|
||||||
|
change.messages.map((m) => m.change_message).filter((m) => !!m),
|
||||||
|
)}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
this.redmineIssuesCacheWriterService.subject.subscribe(
|
this.redmineIssuesCacheWriterService.subject.subscribe(
|
||||||
async (saveResult) => {
|
async (saveResult) => {
|
||||||
await this.personalNotificationsService.analize(saveResult);
|
await this.personalNotificationsService.analize(saveResult);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.redmineIssuesCacheWriterService.subject
|
||||||
|
.pipe(
|
||||||
|
switchMap(async (saveResult) => {
|
||||||
|
this.logger.debug(
|
||||||
|
`Save result process started, issue_id = ${saveResult.current.id}`,
|
||||||
|
);
|
||||||
|
return saveResult;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
switchMap(async (saveResult) => {
|
||||||
|
this.logger.debug(`personalNotificationsService.analize started`);
|
||||||
|
await this.personalNotificationsService.analize(saveResult);
|
||||||
|
this.logger.debug('personalNotificationsService.analize successed');
|
||||||
|
return saveResult;
|
||||||
|
}),
|
||||||
|
switchMap(async (saveResult) => {
|
||||||
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
this.logger.debug(`statusChangeNotificationsService.getChanges started`);
|
||||||
|
await this.statusChangeNotificationsService.getChanges(saveResult);
|
||||||
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
this.logger.debug(`statusChangeNotificationsService.getChanges successed`);
|
||||||
|
return saveResult;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.subscribe(async (saveResult) => {
|
||||||
|
this.logger.debug(
|
||||||
|
`Save result process success finished, issue_id = ${saveResult.current.id}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export namespace StatusChangesConfig {
|
||||||
|
|
||||||
export type Item = {
|
export type Item = {
|
||||||
default: boolean;
|
default: boolean;
|
||||||
|
new_issue?: boolean;
|
||||||
from: string;
|
from: string;
|
||||||
to: string;
|
to: string;
|
||||||
messages: Message[];
|
messages: Message[];
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { StatusChangesConfig } from 'src/models/status-changes-config.model';
|
||||||
import { StatusesConfig } from 'src/models/statuses-config.model';
|
import { StatusesConfig } from 'src/models/statuses-config.model';
|
||||||
import Handlebars from 'handlebars';
|
import Handlebars from 'handlebars';
|
||||||
import { ChangeMessage } from 'src/models/change-message.model';
|
import { ChangeMessage } from 'src/models/change-message.model';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StatusChangeNotificationsService {
|
export class StatusChangeNotificationsService {
|
||||||
|
|
@ -17,6 +18,8 @@ export class StatusChangeNotificationsService {
|
||||||
private statuses: StatusesConfig.Config;
|
private statuses: StatusesConfig.Config;
|
||||||
private statusChanges: StatusChangesConfig.Config;
|
private statusChanges: StatusChangesConfig.Config;
|
||||||
|
|
||||||
|
$changes = new Subject<Change>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private usersService: UsersService,
|
private usersService: UsersService,
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
|
|
@ -29,7 +32,10 @@ export class StatusChangeNotificationsService {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`StatusChangeNotificationsService created, ` +
|
`StatusChangeNotificationsService created, ` +
|
||||||
`statuses = ${JSON.stringify(this.statuses.map((s) => s.name))}, ` +
|
`statuses = ${JSON.stringify(this.statuses.map((s) => s.name))}, ` +
|
||||||
`statusChanges.length = ${this.statusChanges.length}`,
|
`statusChanges.length = ${this.statusChanges.length}, ` +
|
||||||
|
`statusChanges = ` +
|
||||||
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
`${JSON.stringify(this.statusChanges.map((c) => `${c.from} -> ${c.to}`))}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,6 +49,11 @@ export class StatusChangeNotificationsService {
|
||||||
|
|
||||||
const issue = saveResponse.current;
|
const issue = saveResponse.current;
|
||||||
|
|
||||||
|
if (!saveResponse.prev) {
|
||||||
|
const newChange = await this.getMessagesForNewIssue(issue);
|
||||||
|
changes.push(newChange);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < saveResponse.journalsDiff.length; i++) {
|
for (let i = 0; i < saveResponse.journalsDiff.length; i++) {
|
||||||
const journal = saveResponse.journalsDiff[i];
|
const journal = saveResponse.journalsDiff[i];
|
||||||
const change = await this.getMessagesForChangeStatus(issue, journal);
|
const change = await this.getMessagesForChangeStatus(issue, journal);
|
||||||
|
|
@ -55,6 +66,9 @@ export class StatusChangeNotificationsService {
|
||||||
`Analize change statuses for issue #${saveResponse.current.id} ` +
|
`Analize change statuses for issue #${saveResponse.current.id} ` +
|
||||||
`(${saveResponse.current.subject}) for journalsDiff.length = ${saveResponse.journalsDiff.length} finished`,
|
`(${saveResponse.current.subject}) for journalsDiff.length = ${saveResponse.journalsDiff.length} finished`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
changes.forEach((c) => this.$changes.next(c));
|
||||||
|
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,8 +85,8 @@ export class StatusChangeNotificationsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getMessagesForChangeStatus(
|
private async getMessagesForChangeStatus(
|
||||||
issue: any,
|
issue: RedmineTypes.Issue & Record<string, any>,
|
||||||
journal: any,
|
journal: RedmineTypes.Journal,
|
||||||
): Promise<Change | null> {
|
): Promise<Change | null> {
|
||||||
const statusChangeDetails = this.getStatusChangeDetails(journal);
|
const statusChangeDetails = this.getStatusChangeDetails(journal);
|
||||||
if (!statusChangeDetails) return null;
|
if (!statusChangeDetails) return null;
|
||||||
|
|
@ -101,8 +115,43 @@ export class StatusChangeNotificationsService {
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getMessagesForNewIssue(
|
||||||
|
issue: RedmineTypes.Issue & Record<string, any>,
|
||||||
|
): Promise<Change> {
|
||||||
|
const changeParams = this.statusChanges.find((p) => p.new_issue);
|
||||||
|
const change: Change = {
|
||||||
|
initiator: await this.usersService.getUser(issue.author.id),
|
||||||
|
dev: await this.usersService.getUser(issue?.dev?.id),
|
||||||
|
qa: await this.usersService.getUser(issue?.qa?.id),
|
||||||
|
cr: await this.usersService.getUser(issue?.cr?.id),
|
||||||
|
current_user: await this.usersService.getUser(issue?.current_user?.id),
|
||||||
|
author: await this.usersService.getUser(issue?.author?.id),
|
||||||
|
old_status: this.findStatusById(issue.status.id),
|
||||||
|
new_status: this.findStatusById(issue.status.id),
|
||||||
|
issue_id: issue.id,
|
||||||
|
issue_url: this.redminePublicUrlConverter.convert(issue.id),
|
||||||
|
issue_tracker: issue.tracker?.name || '',
|
||||||
|
issue_subject: issue.subject || '',
|
||||||
|
created_on: issue.created_on,
|
||||||
|
created_on_timestamp: TimestampConverter.toTimestamp(issue.created_on),
|
||||||
|
journal_note: '',
|
||||||
|
messages: [],
|
||||||
|
};
|
||||||
|
const filledMessages = await Promise.all(
|
||||||
|
changeParams.messages.map(async (messageParams: any) => {
|
||||||
|
return await this.generateMessage(messageParams, change);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
change.messages = filledMessages.filter((m) => Boolean(m));
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
private findStatusById(id: number | string): StatusesConfig.Item | null {
|
private findStatusById(id: number | string): StatusesConfig.Item | null {
|
||||||
if (typeof id === 'string' && !Number.isNaN(id) && Number.isFinite(id)) {
|
if (
|
||||||
|
typeof id === 'string' &&
|
||||||
|
!Number.isNaN(id) &&
|
||||||
|
Number.isFinite(Number(id))
|
||||||
|
) {
|
||||||
id = Number(id);
|
id = Number(id);
|
||||||
}
|
}
|
||||||
return this.statuses.find((s) => s.id === id) || null;
|
return this.statuses.find((s) => s.id === id) || null;
|
||||||
|
|
@ -111,7 +160,7 @@ export class StatusChangeNotificationsService {
|
||||||
private async generateMessages(
|
private async generateMessages(
|
||||||
detail: RedmineTypes.JournalDetail,
|
detail: RedmineTypes.JournalDetail,
|
||||||
change: Change,
|
change: Change,
|
||||||
): Promise<any> {
|
): Promise<ChangeMessage[]> {
|
||||||
const oldStatus = this.findStatusById(detail.old_value);
|
const oldStatus = this.findStatusById(detail.old_value);
|
||||||
const newStatus = this.findStatusById(detail.new_value);
|
const newStatus = this.findStatusById(detail.new_value);
|
||||||
if (!oldStatus || !newStatus) return null;
|
if (!oldStatus || !newStatus) return null;
|
||||||
|
|
@ -122,7 +171,7 @@ export class StatusChangeNotificationsService {
|
||||||
return await this.generateMessage(messageParams, change);
|
return await this.generateMessage(messageParams, change);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return filledMessages.filter((m) => m);
|
return filledMessages.filter((m) => Boolean(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
private findChangeParams(
|
private findChangeParams(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue