feat: update guard time schedule

pull/169/head
Firman Ramdhani 2025-07-07 17:21:38 +07:00
parent c345674643
commit 999ba1ff9b
8 changed files with 63 additions and 47 deletions

View File

@ -54,6 +54,7 @@
"mathjs": "^13.0.2", "mathjs": "^13.0.2",
"midtrans-client": "^1.3.1", "midtrans-client": "^1.3.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"moment-timezone": "^0.6.0",
"nano": "^10.1.3", "nano": "^10.1.3",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.14",
"pdfmake": "^0.2.10", "pdfmake": "^0.2.10",

View File

@ -7,7 +7,6 @@ import { DataSchedulingReadService } from './data/services/data-scheduling-read.
import { DataSchedulingReadController } from './infrastructure/data-scheduling-read.controller'; import { DataSchedulingReadController } from './infrastructure/data-scheduling-read.controller';
import { DataSchedulingReadOrchestrator } from './domain/usecases/data-scheduling-read.orchestrator'; import { DataSchedulingReadOrchestrator } from './domain/usecases/data-scheduling-read.orchestrator';
import { import {
DataSchedulingActiveController,
DataSchedulingDataController, DataSchedulingDataController,
DataSchedulingDefaultController, DataSchedulingDefaultController,
DataSchedulingSetupController, DataSchedulingSetupController,
@ -29,6 +28,11 @@ import { BatchInactiveDataSchedulingManager } from './domain/usecases/managers/b
import { DataSchedulingModel } from './data/models/data-scheduling.model'; import { DataSchedulingModel } from './data/models/data-scheduling.model';
import { DataSchedulingDefaultModel } from './data/models/data-scheduling-default.model'; import { DataSchedulingDefaultModel } from './data/models/data-scheduling-default.model';
import { DataSchedulingManager } from './domain/usecases/managers/data-scheduling-default.manager'; import { DataSchedulingManager } from './domain/usecases/managers/data-scheduling-default.manager';
import { SetupSchedulingGuard } from './infrastructure/guards/setup-scheduling.guard';
import { JwtModule } from '@nestjs/jwt';
import { JWT_EXPIRED } from 'src/core/sessions/constants';
import { JWT_SECRET } from 'src/core/sessions/constants';
@Module({ @Module({
imports: [ imports: [
@ -37,16 +41,20 @@ import { DataSchedulingManager } from './domain/usecases/managers/data-schedulin
[DataSchedulingModel, DataSchedulingDefaultModel], [DataSchedulingModel, DataSchedulingDefaultModel],
CONNECTION_NAME.DEFAULT, CONNECTION_NAME.DEFAULT,
), ),
JwtModule.register({
secret: JWT_SECRET,
signOptions: { expiresIn: JWT_EXPIRED },
}),
CqrsModule, CqrsModule,
], ],
controllers: [ controllers: [
DataSchedulingDataController, DataSchedulingDataController,
DataSchedulingReadController, DataSchedulingReadController,
DataSchedulingDefaultController, DataSchedulingDefaultController,
DataSchedulingActiveController,
DataSchedulingSetupController, DataSchedulingSetupController,
], ],
providers: [ providers: [
SetupSchedulingGuard,
IndexDataSchedulingManager, IndexDataSchedulingManager,
DetailDataSchedulingManager, DetailDataSchedulingManager,
CreateDataSchedulingManager, CreateDataSchedulingManager,

View File

@ -13,6 +13,9 @@ import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { SelectQueryBuilder } from 'typeorm'; import { SelectQueryBuilder } from 'typeorm';
import { DataSchedulingModel } from '../../../data/models/data-scheduling.model'; import { DataSchedulingModel } from '../../../data/models/data-scheduling.model';
import { decryptionTotal } from '../../../infrastructure/helpers'; import { decryptionTotal } from '../../../infrastructure/helpers';
import * as momentTz from 'moment-timezone';
import { EventBus } from '@nestjs/cqrs';
import { DataSchedulingChangeStatusEvent } from '../../entities/event/data-scheduling-change-status.event';
@Injectable() @Injectable()
export class DataSchedulingManager { export class DataSchedulingManager {
@ -20,6 +23,8 @@ export class DataSchedulingManager {
protected userProvider: UserProvider; protected userProvider: UserProvider;
constructor( constructor(
private eventBus: EventBus,
@InjectRepository(DataSchedulingDefaultModel) @InjectRepository(DataSchedulingDefaultModel)
private repository: Repository<DataSchedulingDefaultModel>, private repository: Repository<DataSchedulingDefaultModel>,
@ -72,7 +77,11 @@ export class DataSchedulingManager {
return this.queryBuilder().getOne(); return this.queryBuilder().getOne();
} }
async getActiveData(date) { async getActiveData() {
const timeZoneWIB = 'Asia/Jakarta';
const nowInWIB = momentTz().tz(timeZoneWIB).format('YYYY-MM-DD');
const date = nowInWIB;
const qb = this.repoSchedule.createQueryBuilder(TABLE_NAME.DATA_SCHEDULING); const qb = this.repoSchedule.createQueryBuilder(TABLE_NAME.DATA_SCHEDULING);
const findData: DataSchedulingEntity = await qb const findData: DataSchedulingEntity = await qb
@ -86,6 +95,15 @@ export class DataSchedulingManager {
return { value: defaultData?.default_value }; return { value: defaultData?.default_value };
} }
return { value: decryptionTotal(findData.indexing_key as string) }; return { value: decryptionTotal(findData.indexing_key as string), date };
}
async setupActiveScheduling() {
const activeSchedule = await this.getActiveData();
await this.eventBus.publish(
new DataSchedulingChangeStatusEvent({ data: activeSchedule } as any),
);
return { message: 'Berhasil setup transaction scheduling.' };
} }
} }

View File

@ -7,12 +7,10 @@ import {
Patch, Patch,
Post, Post,
Put, Put,
Query,
UseGuards, UseGuards,
} from '@nestjs/common'; } from '@nestjs/common';
import { DataSchedulingDataOrchestrator } from '../domain/usecases/data-scheduling-data.orchestrator'; import { DataSchedulingDataOrchestrator } from '../domain/usecases/data-scheduling-data.orchestrator';
import { import {
SetupDataSchedulingDto,
CreateDataSchedulingDto, CreateDataSchedulingDto,
EditDataSchedulingDto, EditDataSchedulingDto,
EditDataSchedulingDefaultDto, EditDataSchedulingDefaultDto,
@ -20,7 +18,6 @@ import {
import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { import {
DataSchedulingActiveEntity,
DataSchedulingDefaultEntity, DataSchedulingDefaultEntity,
DataSchedulingEntity, DataSchedulingEntity,
} from '../domain/entities/data-scheduling.entity'; } from '../domain/entities/data-scheduling.entity';
@ -29,7 +26,6 @@ import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto'
import { ExcludePrivilege, Public } from 'src/core/guards'; import { ExcludePrivilege, Public } from 'src/core/guards';
import { SetupSchedulingGuard } from './guards/setup-scheduling.guard'; import { SetupSchedulingGuard } from './guards/setup-scheduling.guard';
import { DataSchedulingManager } from '../domain/usecases/managers/data-scheduling-default.manager'; import { DataSchedulingManager } from '../domain/usecases/managers/data-scheduling-default.manager';
import { FilterActiveDataSchedulingDto } from './dto/filter-data-scheduling.dto';
@ApiTags(`${MODULE_NAME.DATA_SCHEDULING.split('-').join(' ')} - data`) @ApiTags(`${MODULE_NAME.DATA_SCHEDULING.split('-').join(' ')} - data`)
@Controller(`v1/${MODULE_NAME.DATA_SCHEDULING}`) @Controller(`v1/${MODULE_NAME.DATA_SCHEDULING}`)
@ -115,43 +111,19 @@ export class DataSchedulingDefaultController {
} }
} }
@ApiTags(
`${MODULE_NAME.DATA_SCHEDULING_ACTIVE.split('-').join(' ')} active - Data`,
)
@Controller(`v1/${MODULE_NAME.DATA_SCHEDULING_ACTIVE}`)
@Public(false)
@ApiBearerAuth('JWT')
export class DataSchedulingActiveController {
constructor(private manager: DataSchedulingManager) {}
@Get()
async get(
@Query() params: FilterActiveDataSchedulingDto,
): Promise<DataSchedulingActiveEntity> {
return await this.manager.getActiveData(params?.date);
}
}
@ApiTags( @ApiTags(
`${MODULE_NAME.DATA_SCHEDULING_SETUP.split('-').join(' ')} setup - Data`, `${MODULE_NAME.DATA_SCHEDULING_SETUP.split('-').join(' ')} setup - Data`,
) )
@Controller(`v1/${MODULE_NAME.DATA_SCHEDULING_SETUP}`) @Controller(`v1/${MODULE_NAME.DATA_SCHEDULING_SETUP}`)
@Public(true) @Public(true)
@ApiBearerAuth('JWT')
export class DataSchedulingSetupController { export class DataSchedulingSetupController {
constructor(private manager: DataSchedulingManager) {}
@Post() @Post()
@ExcludePrivilege() @ExcludePrivilege()
@UseGuards(SetupSchedulingGuard) @UseGuards(SetupSchedulingGuard)
async setup( async setup(): Promise<{ message: string }> {
@Body() data: SetupDataSchedulingDto, return this.manager.setupActiveScheduling();
): Promise<DataSchedulingEntity> {
console.log('payload scheduling setup', { data });
// TODO: Implement logic for "Send to Black Hole" configuration.
// 1. Retrieve the relevant scheduling configuration based on the date provided in the request body.
// 2. If a specific scheduling configuration is found, apply its values to the main 'configuration' table.
// These values will then be used for the "Send to Black Hole" logic.
// 3. If no specific scheduling configuration is found for the given date, update the 'configuration' table
// with values from the 'data scheduling default' settings instead.
return;
} }
} }

View File

@ -83,10 +83,6 @@ export class EditDataSchedulingDefaultDto
} }
export class SetupDataSchedulingDto { export class SetupDataSchedulingDto {
@ApiProperty({ // @ApiProperty({ type: 'string', required: true, example: '2025-01-01' })
type: Date, // date: Date;
required: true,
example: '2024-01-01',
})
schedule_date: Date;
} }

View File

@ -17,7 +17,7 @@ export class FilterDataSchedulingDto
} }
export class FilterActiveDataSchedulingDto { export class FilterActiveDataSchedulingDto {
@ApiProperty({ type: 'string', required: true }) // @ApiProperty({ type: 'string', required: true })
@ValidateIf((body) => body.schedule_date_from) // @ValidateIf((body) => body.schedule_date_from)
date: Date; // date: Date;
} }

View File

@ -4,11 +4,15 @@ import {
Injectable, Injectable,
UnprocessableEntityException, UnprocessableEntityException,
} from '@nestjs/common'; } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable() @Injectable()
export class SetupSchedulingGuard implements CanActivate { export class SetupSchedulingGuard implements CanActivate {
constructor(private readonly jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> { async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest(); const request = context.switchToHttp().getRequest();
const jwtAuth = request.headers['authorization'];
const setupAuth = request.headers['x-setup-authorization']; const setupAuth = request.headers['x-setup-authorization'];
if (setupAuth) { if (setupAuth) {
@ -19,6 +23,16 @@ export class SetupSchedulingGuard implements CanActivate {
} catch (err) { } catch (err) {
throw new UnprocessableEntityException('Invalid authentication.'); throw new UnprocessableEntityException('Invalid authentication.');
} }
} else if (jwtAuth && jwtAuth.startsWith('Bearer ')) {
const token = jwtAuth.split(' ')[1];
try {
const payload = await this.jwtService.verifyAsync(token);
if (payload) return true;
else new UnprocessableEntityException('Setup Authorization Not Found.');
return true;
} catch (err) {
throw new UnprocessableEntityException('Invalid JWT token');
}
} }
throw new UnprocessableEntityException('Invalid authentication'); throw new UnprocessableEntityException('Invalid authentication');

View File

@ -5607,7 +5607,14 @@ module-details-from-path@^1.0.3:
resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==
moment@^2.30.1: moment-timezone@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.6.0.tgz#c5a6519171f31a64739ea75d33f5c136c08ff608"
integrity sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==
dependencies:
moment "^2.29.4"
moment@^2.29.4, moment@^2.30.1:
version "2.30.1" version "2.30.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==