Created
August 22, 2024 23:44
-
-
Save codersidprogrammer/bc674dd0a6b7c9da6c914f23125335a6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import { Injectable } from '@nestjs/common'; | |
import { EventEmitter2 } from '@nestjs/event-emitter'; | |
import { | |
$Enums, | |
StopReason, | |
Teams, | |
TransactionActiveJob, | |
TransactionStopJob, | |
} from '@prisma/client'; | |
import { plainToClass } from 'class-transformer'; | |
import { | |
addHours, | |
addMinutes, | |
differenceInMilliseconds, | |
differenceInMinutes, | |
} from 'date-fns'; | |
import { | |
catchError, | |
filter, | |
from, | |
lastValueFrom, | |
mergeMap, | |
of, | |
switchMap, | |
tap, | |
throwError, | |
zip, | |
} from 'rxjs'; | |
import { SoeDto } from 'src/core/api/services/soe/soe.dto'; | |
import { BaseService } from 'src/core/base.service'; | |
import { EVENT_LOG_ACTIVITY } from 'src/core/constants/app.constant'; | |
import { AppLogsDto } from 'src/core/dtos/app.log.dto'; | |
import { EventNotificationDto } from 'src/core/dtos/event.notification.dto'; | |
import EntityNotFoundError from 'src/core/errors/entity-notfound.error'; | |
import ServiceError from 'src/core/errors/service.error'; | |
import { PrismaService } from 'src/core/services/prisma.service'; | |
import { | |
SAP_TRANSACTION_FINSH, | |
SAP_TRANSACTION_START, | |
SAP_TRANSACTION_STOP, | |
TRANSACTION_START, | |
TRANSACTION_START_NONROUTINE, | |
TRANSACTION_STOP, | |
} from '../queue/constants/queue.contant'; | |
import { QueueService } from '../queue/queue.service'; | |
import { StopreasonService } from '../stopreason/stopreason.service'; | |
import { TeamsService } from '../teams/teams.service'; | |
import { UsersService } from '../users/users.service'; | |
import { BaseTransactionDto } from './dto/base-trx.dto'; | |
import { FinishTransactionDto } from './dto/finish-trx.dto'; | |
import { StartNonRoutineTransactionDto } from './dto/start-nonroutine-trx.dto'; | |
import { StartTransactionDto } from './dto/start-trx.dto'; | |
import { StopTransactionDto } from './dto/stop-trx.dto'; | |
import { ActiveQueueDataInterface } from './interfaces/active-queue.data.interface'; | |
import { StopNonroutineTransactionDto } from './dto/stop-nonroutine-trx.dto'; | |
import { StopTaskSAPDTO } from '../transaction-sap/dtos/stop-task-sap.dto'; | |
@Injectable() | |
export class TransactionService extends BaseService { | |
constructor( | |
private readonly event: EventEmitter2, | |
private readonly prisma: PrismaService, | |
private readonly teamService: TeamsService, | |
private readonly userService: UsersService, | |
private readonly queueService: QueueService, | |
private readonly stopReasonService: StopreasonService, | |
) { | |
super(TransactionService.name); | |
} | |
async startOrderNonRoutine(dto: StartNonRoutineTransactionDto) { | |
const _now = new Date(); | |
const start$ = this.userService.getUserDetails(dto.personalNumber).pipe( | |
mergeMap((value) => | |
from( | |
this.createActiveJobRecord( | |
{ | |
personalNumber: dto.personalNumber, | |
orderNumber: dto.orderNumber, | |
orderName: dto.orderName, | |
orderOperation: 'NRXO', | |
orderType: dto.orderType, | |
orderZone: dto.orderZone, | |
workPlanDuration: dto.workPlanDuration, | |
aircraftType: dto.aircraftRegistration, | |
aircraftRegistration: dto.aircraftType, | |
operationName: 'NON-ROUTINE', | |
}, | |
value, | |
_now, | |
), | |
).pipe( | |
tap(() => | |
this.logger.log( | |
`[start:${dto.personalNumber}] create XOPS job record`, | |
), | |
), | |
), | |
), | |
tap(() => | |
this.logger.log(`[start:${dto.personalNumber}] create job alarm queue`), | |
), | |
mergeMap((value) => { | |
// 1. Get some minutes from start | |
const _plannedEndTime = addMinutes(_now, dto.workPlanDuration * 60); | |
// 2. Find different in millisecond | |
const _differentInMillis = differenceInMilliseconds( | |
_plannedEndTime, | |
_now, | |
); | |
return from( | |
this.queueService.addQueue(TRANSACTION_START_NONROUTINE, value, { | |
delay: _differentInMillis * 2, | |
}), | |
).pipe( | |
catchError((err) => { | |
throw new ServiceError(err, [value]); | |
}), | |
); | |
}), | |
tap((value) => | |
this.logger.log( | |
`[start:${dto.personalNumber}] saving job queue ID ${value.id}`, | |
), | |
), | |
mergeMap((value) => | |
from( | |
this.createActiveQueueRecord( | |
{ | |
personalNumber: value.data.personalNumber, | |
personalUnit: value.data.personalUnit, | |
queueActiveId: Number(value.id), | |
queueType: $Enums.JobQueueType.STOP, | |
orderNumber: value.data.orderNumber, | |
orderOperation: value.data.orderOperation, | |
}, | |
$Enums.JobQueueType.START, | |
), | |
).pipe(mergeMap((v) => of({ ...v, uniqueId: value.data.uniqueId }))), | |
), | |
); | |
return await lastValueFrom(start$); | |
} | |
async stopOrderNonRoutine(dto: StopNonroutineTransactionDto) { | |
const _now = new Date(); | |
const stop$ = from(this.deleteActiveJobRecord(dto.activeJobUuid)).pipe( | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] stoping job alarm queue`), | |
), | |
mergeMap(() => | |
from( | |
this.findActiveJobQueue( | |
dto.personalNumber, | |
dto.orderNumber, | |
dto.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
).pipe( | |
tap((value) => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:queue] active job found ${value.uniqueId}`, | |
), | |
), | |
tap((value) => | |
this.logger.warn( | |
`[start:${dto.personalNumber}:queue] deleting active queue ID ${value.queueActiveId}`, | |
), | |
), | |
mergeMap((value) => | |
from( | |
this.queueService.removeQueue(String(value.queueActiveId)), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}:queue] deleted`), | |
), | |
tap(() => | |
this.logger.warn( | |
`[stop:${dto.personalNumber}:queue] deleting on XOPS table`, | |
), | |
), | |
mergeMap(() => | |
from( | |
this.deleteActiveJobQueue( | |
value.personalNumber, | |
value.orderNumber, | |
value.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
), | |
), | |
), | |
), | |
), | |
), | |
tap(() => | |
this.logger.warn( | |
`[stop:${dto.personalNumber}] set record as stop personal from job`, | |
), | |
), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] getting personal info`), | |
), | |
mergeMap(() => this.userService.getUserDetails(dto.personalNumber)), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] getting stop reason`), | |
), | |
mergeMap((value) => { | |
const stopReason$ = from( | |
this.stopReasonService.readFirstByCondition({ | |
reason: 'Final', | |
status: $Enums.PublicStatus.PUBLIC, | |
}), | |
); | |
return zip(of(value), stopReason$); | |
}), | |
mergeMap((value) => { | |
const soe = value[0]; | |
const stopReason = value[1]; | |
return from( | |
this.createStopJobRecord( | |
dto, | |
soe, | |
_now, | |
stopReason, | |
dto.isStopBySystem || false, | |
), | |
).pipe( | |
tap(() => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:stopjobqueue] registering queue stop job`, | |
), | |
), | |
mergeMap((value) => { | |
return from( | |
this.queueService.addQueue(TRANSACTION_STOP, value, { | |
delay: stopReason.duration * 60 * 1000, | |
}), | |
); | |
}), | |
tap(() => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:stopjobqueue] saving queue stop job`, | |
), | |
), | |
tap(() => | |
from( | |
this.userService.update( | |
{ | |
userJobStatus: $Enums.UserJobStatus.STOP, | |
}, | |
dto.personalNumber, | |
), | |
), | |
), | |
mergeMap((value) => | |
this.createActiveQueueRecord( | |
{ | |
personalNumber: value.data.personalNumber, | |
personalUnit: value.data.personalUnit, | |
queueActiveId: Number(value.id), | |
queueType: $Enums.JobQueueType.STOP, | |
orderNumber: value.data.lastOrderNumber, | |
orderOperation: value.data.lastOperationNumber, | |
}, | |
$Enums.JobQueueType.STOP, | |
), | |
), | |
); | |
}), | |
); | |
return await lastValueFrom(stop$); | |
} | |
/** | |
* Starting job order. | |
* 1. Get personal info | |
* 2. Create job record on XOPS | |
* 3. Create alarm on XOPS | |
* 4. Set job start on SAP | |
* | |
* @param dto | |
* @returns | |
*/ | |
async startOrder(dto: StartTransactionDto, team?: Teams) { | |
const _now = new Date(); | |
// 1. Get personal info | |
const checking$ = from( | |
this.findAndDeletePersonalOnStopJob(dto.personalNumber), | |
); | |
const start$ = from( | |
this.userService.update( | |
{ | |
userJobStatus: $Enums.UserJobStatus.ONJOB, | |
}, | |
dto.personalNumber, | |
), | |
).pipe( | |
tap(() => | |
this.logger.log(`[start:${dto.personalNumber}] getting personal info`), | |
), | |
catchError((err) => { | |
return throwError(() => new EntityNotFoundError(err, [err])); | |
}), | |
mergeMap(() => this.userService.getUserDetails(dto.personalNumber)), | |
// 2. Create new record active transaction on XOPS | |
mergeMap((value) => | |
from(this.createActiveJobRecord(dto, value, _now, team)).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
tap(() => | |
this.logger.log( | |
`[start:${dto.personalNumber}] create XOPS job record`, | |
), | |
), | |
), | |
), | |
// 3. Creating alarm on XOPS | |
tap(() => | |
this.logger.log(`[start:${dto.personalNumber}] create job alarm queue`), | |
), | |
mergeMap((value) => { | |
// 1. Get some minutes from start | |
const _plannedEndTime = addMinutes(_now, dto.workPlanDuration * 60); | |
// 2. Find different in millisecond | |
const _differentInMillis = differenceInMilliseconds( | |
_plannedEndTime, | |
_now, | |
); | |
// 3. Bug Fixed: treshold delay should not more than 20 hours | |
const diffMillisTreshold = 20 * 60 * 60 * 1000; // hour * minute * second * millisec | |
return from( | |
this.queueService.addQueue(TRANSACTION_START, value, { | |
delay: diffMillisTreshold, | |
}), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
); | |
}), | |
// 3.1. Create active Queue job record | |
tap((value) => | |
this.logger.log( | |
`[start:${dto.personalNumber}] saving job queue ID ${value.id}`, | |
), | |
), | |
mergeMap((value) => | |
from( | |
this.createActiveQueueRecord( | |
{ | |
personalNumber: value.data.personalNumber, | |
personalUnit: value.data.personalUnit, | |
queueActiveId: Number(value.id), | |
queueType: $Enums.JobQueueType.STOP, | |
orderNumber: value.data.orderNumber, | |
orderOperation: value.data.orderOperation, | |
}, | |
$Enums.JobQueueType.START, | |
), | |
).pipe( | |
tap((v) => | |
this.event.emit( | |
'notification.transaction', | |
plainToClass(EventNotificationDto, { | |
title: 'Job started', | |
module: TransactionService.name.toLowerCase(), | |
sender: '100000', | |
recepient: v.personalNumber, | |
description: `You started on ${value.data.orderNumber}`, | |
isRead: 'unread', | |
}), | |
), | |
), | |
tap((v) => | |
this.event.emit( | |
EVENT_LOG_ACTIVITY, | |
plainToClass(AppLogsDto, { | |
logTitle: 'Jobs', | |
personalNumber: v.personalNumber, | |
detail: `You started on ${value.data.orderNumber}`, | |
}), | |
), | |
), | |
mergeMap((v) => of({ ...v, uniqueId: value.data.uniqueId })), | |
), | |
), | |
// 4. Queue SAP Transaction | |
mergeMap((value) => | |
from( | |
this.queueService.addQueue( | |
SAP_TRANSACTION_START, | |
{ | |
personalNumber: dto.personalNumber, | |
operationNumber: dto.orderOperation, | |
orderNumber: dto.orderNumber, | |
startDate: _now, | |
confirmationText: 'XOPS', | |
countOfWorker: 1, | |
sapStopReason: '', | |
}, | |
{ delay: 5000, attempts: 5 }, | |
), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
switchMap(() => of(value)), | |
), | |
), | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
); | |
return lastValueFrom( | |
checking$.pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
switchMap(() => start$), | |
), | |
); | |
} | |
/** | |
* Stopping job order. | |
* 1. Set job stop on SAP | |
* 2. Delete active transaction by UUID | |
* 3. Removing alarm | |
* 4. Set personal as stop from job in transaction | |
* | |
* @param dto | |
* @returns | |
*/ | |
async stopOrder(dto: StopTransactionDto) { | |
const _now = new Date(); | |
const stop$ = from( | |
// get active transaction first | |
this.prisma.transactionActiveJob.findUnique({ | |
where: { | |
uniqueId: dto.activeJobUuid, | |
}, | |
}), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
switchMap((value) => { | |
const stopReason$ = from( | |
this.stopReasonService.readFirstByCondition({ | |
uniqueId: dto.stopUuid, | |
status: dto.stopReasonStatus || $Enums.PublicStatus.PUBLIC, | |
}), | |
); | |
return zip(of(value), stopReason$); | |
}), | |
switchMap((value) => { | |
return from( | |
// Stop the transaction from SAP using queue | |
this.queueService.addQueue<StopTaskSAPDTO>( | |
SAP_TRANSACTION_STOP, | |
{ | |
personalNumber: dto.personalNumber, | |
operationNumber: dto.orderOperation, | |
orderNumber: dto.orderNumber, | |
startDate: addHours(value[0].startTime, 7), | |
confirmationText: 'XOPS', | |
countOfWorker: 1, | |
workInMinutes: differenceInMinutes(_now, value[0].startTime), | |
sapStopReason: value[1].sapCategory, | |
}, | |
{ delay: 1000, attempts: 5 }, | |
), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
); | |
}), | |
mergeMap(() => from(this.deleteActiveJobRecord(dto.activeJobUuid))), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] stoping job alarm queue`), | |
), | |
mergeMap(() => | |
from( | |
this.findActiveJobQueue( | |
dto.personalNumber, | |
dto.orderNumber, | |
dto.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
).pipe( | |
tap((value) => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:queue] active job found ${value.uniqueId}`, | |
), | |
), | |
tap((value) => | |
this.logger.warn( | |
`[start:${dto.personalNumber}:queue] deleting active queue ID ${value.queueActiveId}`, | |
), | |
), | |
mergeMap((value) => | |
from( | |
this.queueService.removeQueue(String(value.queueActiveId)), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}:queue] deleted`), | |
), | |
tap(() => | |
this.logger.warn( | |
`[stop:${dto.personalNumber}:queue] deleting on XOPS table`, | |
), | |
), | |
mergeMap(() => | |
from( | |
this.deleteActiveJobQueue( | |
value.personalNumber, | |
value.orderNumber, | |
value.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
), | |
), | |
), | |
), | |
), | |
), | |
tap(() => | |
this.logger.warn( | |
`[stop:${dto.personalNumber}] set record as stop personal from job`, | |
), | |
), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] getting personal info`), | |
), | |
mergeMap(() => this.userService.getUserDetails(dto.personalNumber)), | |
tap(() => | |
this.logger.log(`[stop:${dto.personalNumber}] getting stop reason`), | |
), | |
mergeMap((value) => { | |
const stopReason$ = from( | |
this.stopReasonService.readFirstByCondition({ | |
uniqueId: dto.stopUuid, | |
status: dto.stopReasonStatus || $Enums.PublicStatus.PUBLIC, | |
}), | |
); | |
return zip(of(value), stopReason$); | |
}), | |
mergeMap((value) => { | |
const soe = value[0]; | |
const stopReason = value[1]; | |
return from( | |
this.createStopJobRecord( | |
dto, | |
soe, | |
_now, | |
stopReason, | |
dto.isStopBySystem || false, | |
), | |
).pipe( | |
tap(() => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:stopjobqueue] registering queue stop job`, | |
), | |
), | |
mergeMap((value) => { | |
return from( | |
this.queueService.addQueue(TRANSACTION_STOP, value, { | |
delay: stopReason.duration * 60 * 1000, | |
}), | |
); | |
}), | |
tap(() => | |
this.logger.log( | |
`[stop:${dto.personalNumber}:stopjobqueue] saving queue stop job`, | |
), | |
), | |
tap(() => | |
from( | |
this.userService.update( | |
{ | |
userJobStatus: $Enums.UserJobStatus.STOP, | |
}, | |
dto.personalNumber, | |
), | |
), | |
), | |
tap((v) => | |
this.event.emit( | |
'notification.transaction', | |
plainToClass(EventNotificationDto, { | |
title: 'Job stopped', | |
module: TransactionService.name.toLowerCase(), | |
sender: '100000', | |
recepient: v.data.personalNumber, | |
description: `You stopped on ${v.data.lastOrderNumber}`, | |
isRead: 'unread', | |
}), | |
), | |
), | |
tap((v) => | |
this.event.emit( | |
EVENT_LOG_ACTIVITY, | |
plainToClass(AppLogsDto, { | |
logTitle: 'Jobs', | |
personalNumber: v.data.personalNumber, | |
detail: `You stopped on ${v.data.lastOrderNumber}`, | |
}), | |
), | |
), | |
mergeMap((value) => | |
this.createActiveQueueRecord( | |
{ | |
personalNumber: value.data.personalNumber, | |
personalUnit: value.data.personalUnit, | |
queueActiveId: Number(value.id), | |
queueType: $Enums.JobQueueType.STOP, | |
orderNumber: value.data.lastOrderNumber, | |
orderOperation: value.data.lastOperationNumber, | |
}, | |
$Enums.JobQueueType.STOP, | |
), | |
), | |
); | |
}), | |
); | |
return lastValueFrom(stop$); | |
} | |
/** | |
* Finishing job order. | |
* 1. Check if it was stopped by leader | |
* 2. Do logic on stopOrder for each member (SAP Included) | |
* 3. Do logic on finishOrder for leader (SAP Included) | |
* | |
* @param dto | |
* @returns | |
*/ | |
async finishOrderAsTeam(dto: FinishTransactionDto) { | |
const activeJobAsTeam$ = from( | |
await this.findActiveJobRecordByTeams(dto.teamId), | |
); | |
const checkOwner$ = from( | |
this.teamService.readFirstByIdAndOwner(dto.teamId, dto.personalNumber), | |
).pipe( | |
catchError((err) => { | |
return throwError( | |
() => new EntityNotFoundError('It was not your team maid', [err]), | |
); | |
}), | |
// Get stop reason first | |
switchMap((value) => { | |
const stopReason$ = from( | |
this.stopReasonService.readFirstByCondition({ | |
reason: 'Final', | |
status: $Enums.PublicStatus.PUBLIC, | |
}), | |
).pipe(); | |
return zip(of(value), stopReason$); | |
}), | |
// Stop first for all member | |
switchMap(([teamInfo, stopReason]) => | |
activeJobAsTeam$.pipe( | |
filter((value) => value.personalNumber !== teamInfo.leader), | |
mergeMap((value) => | |
from( | |
this.stopOrder({ | |
activeJobUuid: value.uniqueId, | |
personalNumber: value.personalNumber, | |
stopUuid: stopReason.uniqueId, | |
orderName: dto.orderName, | |
orderNumber: dto.orderNumber, | |
orderOperation: dto.orderOperation, | |
isStopBySystem: dto.isStopBySystem || false, | |
}), | |
), | |
), | |
), | |
), | |
// Then finish by leader | |
switchMap(() => { | |
return from(this.finishOrder(dto)); | |
}), | |
); | |
return lastValueFrom(checkOwner$); | |
} | |
/** | |
* Finishing job order. | |
* 1. Set job stop on SAP | |
* 2. Delete active transaction by UUID | |
* 3. Removing alarm | |
* 4. Set personal as stop from job in transaction | |
* | |
* @param dto | |
* @returns | |
*/ | |
async finishOrder(dto: FinishTransactionDto) { | |
const _now = new Date(); | |
// Stop the transaction from SAP using queue | |
const stop$ = from( | |
// get active transaction first | |
this.prisma.transactionActiveJob.findUnique({ | |
where: { | |
uniqueId: dto.activeJobUuid, | |
}, | |
}), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
switchMap((value) => | |
from( | |
this.queueService.addQueue( | |
SAP_TRANSACTION_FINSH, | |
{ | |
personalNumber: dto.personalNumber, | |
operationNumber: dto.orderOperation, | |
orderNumber: dto.orderNumber, | |
startDate: addHours(value.startTime, 7), | |
confirmationText: 'XOPS', | |
countOfWorker: 1, | |
workInMinutes: differenceInMinutes(_now, value.startTime), | |
}, | |
{ delay: 1000, attempts: 5 }, | |
), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
), | |
), | |
mergeMap(() => from(this.deleteActiveJobRecord(dto.activeJobUuid))), | |
tap(() => | |
this.logger.log( | |
`[finish:${dto.personalNumber}] stoping job alarm queue`, | |
), | |
), | |
mergeMap(() => | |
from( | |
this.findActiveJobQueue( | |
dto.personalNumber, | |
dto.orderNumber, | |
dto.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
).pipe( | |
tap((value) => | |
this.logger.log( | |
`[finish:${dto.personalNumber}:queue] active job found ${value.uniqueId}`, | |
), | |
), | |
tap((value) => | |
this.logger.warn( | |
`[finish:${dto.personalNumber}:queue] deleting active queue ID ${value.queueActiveId}`, | |
), | |
), | |
mergeMap((value) => | |
from( | |
this.queueService.removeQueue(String(value.queueActiveId)), | |
).pipe( | |
catchError((err) => { | |
return throwError(() => err); | |
}), | |
tap(() => | |
this.logger.log(`[finish:${dto.personalNumber}:queue] deleted`), | |
), | |
tap(() => | |
this.logger.warn( | |
`[finish:${dto.personalNumber}:queue] deleting on XOPS table`, | |
), | |
), | |
mergeMap(() => | |
from( | |
this.deleteActiveJobQueue( | |
value.personalNumber, | |
value.orderNumber, | |
value.orderOperation, | |
$Enums.JobQueueType.START, | |
), | |
), | |
), | |
), | |
), | |
), | |
), | |
tap(() => | |
this.logger.warn( | |
`[finish:${dto.personalNumber}] set record as stop personal from job`, | |
), | |
), | |
tap(() => | |
this.logger.log(`[finish:${dto.personalNumber}] getting personal info`), | |
), | |
mergeMap(() => this.userService.getUserDetails(dto.personalNumber)), | |
tap(() => | |
this.logger.log(`[finish:${dto.personalNumber}] getting stop reason`), | |
), | |
mergeMap((value) => { | |
const stopReason$ = from( | |
this.stopReasonService.readFirstByCondition({ | |
reason: 'Final', | |
status: $Enums.PublicStatus.PUBLIC, | |
}), | |
); | |
return zip(of(value), stopReason$); | |
}), | |
mergeMap((value) => { | |
const soe = value[0]; | |
const stopReason = value[1]; | |
return from( | |
this.createStopJobRecord( | |
dto, | |
soe, | |
_now, | |
stopReason, | |
dto.isStopBySystem || false, | |
), | |
).pipe( | |
tap(() => | |
this.logger.log( | |
`[finish:${dto.personalNumber}:stopjobqueue] registering queue stop job`, | |
), | |
), | |
mergeMap((value) => { | |
return from( | |
this.queueService.addQueue(TRANSACTION_STOP, value, { | |
delay: stopReason.duration * 60 * 1000, | |
}), | |
); | |
}), | |
tap(() => | |
this.logger.log( | |
`[finish:${dto.personalNumber}:stopjobqueue] saving queue stop job`, | |
), | |
), | |
tap(() => | |
from( | |
this.userService.update( | |
{ | |
userJobStatus: $Enums.UserJobStatus.STOP, | |
}, | |
dto.personalNumber, | |
), | |
), | |
), | |
tap((v) => | |
this.event.emit( | |
'notification.transaction', | |
plainToClass(EventNotificationDto, { | |
title: 'Job stopped', | |
module: TransactionService.name.toLowerCase(), | |
sender: '100000', | |
recepient: v.data.personalNumber, | |
description: `You stopped on ${v.data.lastOrderNumber}`, | |
isRead: 'unread', | |
}), | |
), | |
), | |
tap((v) => | |
this.event.emit( | |
EVENT_LOG_ACTIVITY, | |
plainToClass(AppLogsDto, { | |
logTitle: 'Jobs', | |
personalNumber: v.data.personalNumber, | |
detail: `You stopped on ${v.data.lastOrderNumber}`, | |
}), | |
), | |
), | |
mergeMap((value) => | |
this.createActiveQueueRecord( | |
{ | |
personalNumber: value.data.personalNumber, | |
personalUnit: value.data.personalUnit, | |
queueActiveId: Number(value.id), | |
queueType: $Enums.JobQueueType.STOP, | |
orderNumber: value.data.lastOrderNumber, | |
orderOperation: value.data.lastOperationNumber, | |
}, | |
$Enums.JobQueueType.STOP, | |
), | |
), | |
); | |
}), | |
); | |
return lastValueFrom(stop$); | |
} | |
/** | |
* Creating active job record on XOPS | |
* | |
* @param order | |
* @param personal | |
* @param _now | |
* @returns | |
*/ | |
async createActiveJobRecord( | |
order: StartTransactionDto, | |
personal: SoeDto, | |
_now: Date, | |
team?: Teams, | |
): Promise<TransactionActiveJob> { | |
return await this.prisma.transactionActiveJob.create({ | |
data: { | |
personalNumber: personal.personalNumber, | |
personalName: personal.personalName, | |
personalUnit: personal.personalUnit, | |
orderNumber: order.orderNumber, | |
orderOperation: order.orderOperation, | |
orderOperationName: order.operationName, | |
orderName: order.orderName || '', | |
orderType: order.orderType || '', | |
orderZone: order.orderZone || '', | |
objectType: order.aircraftType || '', // aircraft type | |
objectProperties: order.aircraftRegistration || '', // aircraft properties | |
startTime: _now, | |
plannedEndTime: addMinutes(_now, order.workPlanDuration * 60), | |
teams: team || {}, // TODO: Change based on DTO | |
}, | |
}); | |
} | |
/** | |
* Deleting active job record in XOPS by UUID | |
* | |
* @param activeUuid | |
* @returns | |
*/ | |
async deleteActiveJobRecord(activeUuid: string) { | |
return await this.prisma.transactionActiveJob.delete({ | |
where: { | |
uniqueId: activeUuid, | |
}, | |
}); | |
} | |
/** | |
* Finding active job record by personal number | |
* | |
* @param personalNumber | |
* @returns | |
*/ | |
async findActiveJobRecord( | |
personalNumber: string, | |
): Promise<TransactionActiveJob[]> { | |
return await this.prisma.transactionActiveJob.findMany({ | |
where: { | |
personalNumber: personalNumber, | |
}, | |
}); | |
} | |
/** | |
* Finding all active job record by unit | |
* | |
* @param unit | |
* @returns | |
*/ | |
async findActiveJobRecordByUnit( | |
unit: string, | |
): Promise<TransactionActiveJob[]> { | |
return await this.prisma.transactionActiveJob.findMany({ | |
where: { | |
personalUnit: unit, | |
}, | |
}); | |
} | |
/** | |
* Finding all active job record by teams uniqueId | |
* | |
* @param teamsId | |
* @returns | |
*/ | |
async findActiveJobRecordByTeams( | |
teamsId: string, | |
): Promise<TransactionActiveJob[]> { | |
const result = await this.prisma.transactionActiveJob.findMany({ | |
where: { | |
teams: { | |
path: ['uniqueId'], | |
equals: teamsId, | |
}, | |
}, | |
}); | |
this.handleEmptyCheck(result, `No team found for ID: ${teamsId}`); | |
return result; | |
} | |
/** | |
* Finding all active stopping job record by unit | |
* | |
* @param unit | |
* @returns | |
*/ | |
async findStopJobRecordByUnit(unit: string): Promise<TransactionStopJob[]> { | |
return await this.prisma.transactionStopJob.findMany({ | |
where: { | |
personalUnit: unit, | |
}, | |
}); | |
} | |
/** | |
* Creating stop job personal record in XOPS | |
* | |
* @param order | |
* @param personal | |
* @param _now | |
* @param stopReason | |
* @param isBySystem | |
* @returns | |
*/ | |
async createStopJobRecord( | |
order: BaseTransactionDto, | |
personal: SoeDto, | |
_now: Date, | |
stopReason: StopReason, | |
isBySystem: boolean, | |
) { | |
return await this.prisma.transactionStopJob.create({ | |
data: { | |
personalNumber: personal.personalNumber, | |
lastTrxStartId: order.activeJobUuid, | |
personalName: personal.personalName, | |
personalUnit: personal.personalUnit, | |
lastOrderNumber: order.orderNumber, | |
lastOperationNumber: order.orderOperation, | |
stopTime: _now, | |
stopReason: stopReason.reason, | |
stopCategory: stopReason.category, | |
plannedEndTime: addMinutes(_now, stopReason.duration), | |
isBySystem: isBySystem, | |
}, | |
}); | |
} | |
/** | |
* Get and check if personal still on active stop job queue | |
* If yes, delete them including all queue | |
* | |
* @param personalNumber | |
* @returns | |
*/ | |
async findAndDeletePersonalOnStopJob(personalNumber: string) { | |
this.logger.warn(`Checking for stopping state for ${personalNumber}`); | |
const _check = await this.prisma.transactionStopJob.findFirst({ | |
where: { | |
personalNumber: personalNumber, | |
}, | |
}); | |
if (_check !== null) { | |
this.logger.log(`${personalNumber} on stop state`); | |
this.logger.warn(`${personalNumber} removing from stop state`); | |
await this.prisma.$transaction(async (trx) => { | |
this.logger.warn(`${personalNumber} removing using db trx`); | |
// 1. Deleting stop state | |
await trx.transactionStopJob.deleteMany({ | |
where: { | |
personalNumber: personalNumber, | |
}, | |
}); | |
const _activeStop = await trx.transactionActiveQueue.findMany({ | |
where: { | |
personalNumber: personalNumber, | |
queueType: $Enums.JobQueueType.STOP, | |
}, | |
}); | |
_activeStop.forEach(async (element) => { | |
await this.queueService.removeQueue(String(element.queueActiveId)); | |
}); | |
// 2. Deleting active queue | |
await trx.transactionActiveQueue.deleteMany({ | |
where: { | |
personalNumber: personalNumber, | |
queueType: $Enums.JobQueueType.STOP, | |
}, | |
}); | |
return true; | |
}); | |
} | |
this.logger.log(`${personalNumber} is not on stop state`); | |
return false; | |
} | |
/** | |
* Each transaction (Start/Stop) should have a queue | |
* This method would make one and save it on XOPS Database | |
* | |
* @param data | |
* @param queueType | |
* @returns | |
*/ | |
async createActiveQueueRecord( | |
data: ActiveQueueDataInterface, | |
queueType: $Enums.JobQueueType, | |
) { | |
return await this.prisma.transactionActiveQueue.create({ | |
data: { | |
personalNumber: data.personalNumber, | |
personalUnit: data.personalUnit, | |
queueActiveId: data.queueActiveId, | |
queueType: queueType, | |
orderNumber: data.orderNumber, | |
orderOperation: data.orderOperation, | |
}, | |
}); | |
} | |
/** | |
* Find active queue by personal number | |
* | |
* @param personalNumber | |
* @param orderNumber | |
* @param operationNumber | |
* @param queueType | |
* @returns | |
*/ | |
async findActiveJobQueue( | |
personalNumber: string, | |
orderNumber: string, | |
operationNumber: string, | |
queueType: $Enums.JobQueueType, | |
) { | |
return await this.prisma.transactionActiveQueue.findFirst({ | |
where: { | |
personalNumber: personalNumber, | |
orderNumber: orderNumber, | |
orderOperation: operationNumber, | |
queueType: queueType, | |
}, | |
}); | |
} | |
async deleteActiveJobQueue( | |
personalNumber: string, | |
orderNumber: string, | |
operationNumber: string, | |
queueType: $Enums.JobQueueType, | |
) { | |
return await this.prisma.transactionActiveQueue.deleteMany({ | |
where: { | |
personalNumber: personalNumber, | |
orderNumber: orderNumber, | |
orderOperation: operationNumber, | |
queueType: queueType, | |
}, | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment