fix(SPG-549) BE - Validasi tgl periode unique based on level
parent
067025312e
commit
cc7a345fff
|
@ -0,0 +1,14 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddColumnPrioritySeasonPeriod1719227554657 implements MigrationInterface {
|
||||||
|
name = 'AddColumnPrioritySeasonPeriod1719227554657'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "season_periods" ADD "priority" integer NOT NULL DEFAULT '3'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "season_periods" DROP COLUMN "priority"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,8 +9,7 @@ import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/it
|
||||||
@Entity(TABLE_NAME.SEASON_PERIOD)
|
@Entity(TABLE_NAME.SEASON_PERIOD)
|
||||||
export class SeasonPeriodModel
|
export class SeasonPeriodModel
|
||||||
extends BaseStatusModel<SeasonPeriodEntity>
|
extends BaseStatusModel<SeasonPeriodEntity>
|
||||||
implements SeasonPeriodEntity
|
implements SeasonPeriodEntity {
|
||||||
{
|
|
||||||
@Column('date', { name: 'start_date', nullable: true })
|
@Column('date', { name: 'start_date', nullable: true })
|
||||||
start_date: Date;
|
start_date: Date;
|
||||||
|
|
||||||
|
@ -23,6 +22,9 @@ export class SeasonPeriodModel
|
||||||
@Column('varchar', { name: 'holiday_name', nullable: true })
|
@Column('varchar', { name: 'holiday_name', nullable: true })
|
||||||
holiday_name: string;
|
holiday_name: string;
|
||||||
|
|
||||||
|
@Column('int', { name: 'priority', default: 3 })
|
||||||
|
priority: number;
|
||||||
|
|
||||||
@Column('varchar', { name: 'season_type_id', nullable: true })
|
@Column('varchar', { name: 'season_type_id', nullable: true })
|
||||||
season_type_id: string;
|
season_type_id: string;
|
||||||
@ManyToOne(() => SeasonTypeModel, (model) => model.season_periods, {
|
@ManyToOne(() => SeasonTypeModel, (model) => model.season_periods, {
|
||||||
|
|
|
@ -6,4 +6,5 @@ export interface SeasonPeriodEntity extends BaseStatusEntity {
|
||||||
end_date: Date;
|
end_date: Date;
|
||||||
days: EnumDays[];
|
days: EnumDays[];
|
||||||
holiday_name: string;
|
holiday_name: string;
|
||||||
|
priority?: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { SeasonPeriodModel } from '../../../data/models/season-period.model';
|
||||||
export class SeasonPeriodHolidayHandler
|
export class SeasonPeriodHolidayHandler
|
||||||
implements IEventHandler<SeasonPeriodCreatedEvent>
|
implements IEventHandler<SeasonPeriodCreatedEvent>
|
||||||
{
|
{
|
||||||
constructor(private dataService: SeasonPeriodDataService) {}
|
constructor(private dataService: SeasonPeriodDataService) { }
|
||||||
|
|
||||||
async handle(event: SeasonPeriodCreatedEvent) {
|
async handle(event: SeasonPeriodCreatedEvent) {
|
||||||
const queryRunner = this.dataService
|
const queryRunner = this.dataService
|
||||||
|
@ -29,6 +29,7 @@ export class SeasonPeriodHolidayHandler
|
||||||
holidayDate.updated_at = event.data.data.updated_at;
|
holidayDate.updated_at = event.data.data.updated_at;
|
||||||
holidayDate.season_type = event.data.data.season_type;
|
holidayDate.season_type = event.data.data.season_type;
|
||||||
holidayDate.item_rates = event.data.data.item_rates;
|
holidayDate.item_rates = event.data.data.item_rates;
|
||||||
|
holidayDate.priority = 1;
|
||||||
|
|
||||||
holidayDates.push(holidayDate);
|
holidayDates.push(holidayDate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { HttpStatus, Injectable, UnprocessableEntityException } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
EventTopics,
|
EventTopics,
|
||||||
columnUniques,
|
columnUniques,
|
||||||
|
@ -8,10 +8,16 @@ import { SeasonPeriodEntity } from '../../entities/season-period.entity';
|
||||||
import { SeasonPeriodModel } from '../../../data/models/season-period.model';
|
import { SeasonPeriodModel } from '../../../data/models/season-period.model';
|
||||||
import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager';
|
import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager';
|
||||||
import { SeasonPeriodCreatedEvent } from '../../entities/event/season-period-created.event';
|
import { SeasonPeriodCreatedEvent } from '../../entities/event/season-period-created.event';
|
||||||
|
import { ValidateSeasonPeriodHelper } from './helpers/validate.helper';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateSeasonPeriodManager extends BaseCreateManager<SeasonPeriodEntity> {
|
export class CreateSeasonPeriodManager extends BaseCreateManager<SeasonPeriodEntity> {
|
||||||
async beforeProcess(): Promise<void> {
|
async beforeProcess(): Promise<void> {
|
||||||
|
const priority = await ValidateSeasonPeriodHelper(this.dataService, this.data);
|
||||||
|
|
||||||
|
Object.assign(this.data, {
|
||||||
|
priority: priority
|
||||||
|
})
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { HttpStatus, UnprocessableEntityException } from "@nestjs/common";
|
||||||
|
|
||||||
|
// function ini bergungsi untuk validasi season period yang sama
|
||||||
|
export async function ValidateSeasonPeriodHelper(dataService, data) {
|
||||||
|
/*
|
||||||
|
singkatnya, ada 3 level priority season period
|
||||||
|
level 1 hari libur atau specific date ( mempunyai holiday_name atau start_date sama dengan end_date )
|
||||||
|
level 2 specific day (array daysnya tidak kosong contoh [Senin, Selasa])
|
||||||
|
level 3 range date ( array daynya kosong, bukan holiday )
|
||||||
|
|
||||||
|
priority 1,2,3 bisa saling tumpang tindih, dan diperhatikan tingkatnya ( semakin besar angkanya , maka semakin kecil priority )
|
||||||
|
|
||||||
|
tapi priority tidak dapat ditindih oleh season period dengan tingkat priority yang sama pada range tanggal yang sama
|
||||||
|
contohnya :
|
||||||
|
1. Season period holiday start_date 2024-08-28, end_date 2024-08-28 tidak dapat ditindih oleh season period holiday lainnya pada range tanggal yang sama
|
||||||
|
2. Season period start_date: 2024-08-15, end_date 2024-08-28, dan days [Senin, Selasa] tidak dapat ditindih oleh Season period 2024-07-08, 2024-08-20 days [Sabtu, Senin]
|
||||||
|
=> akan tetap dapat ditindih oleh season period 2024-08-15, 2024-08-28, days [Rabu, Kamis] (karena beberapa day)
|
||||||
|
3. Season period range 2024-08-15 hingga 2024-08-28, days [] tidak dapat ditindih oleh Season period 2024-07-08, 2024-08-20 days []
|
||||||
|
=> akan tetapi dapat ditindih oleh season period 2024-08-15, 2024-08-28 days [Sabtu, Senin] (karena ini naik prio menjadi priority 2)
|
||||||
|
*/
|
||||||
|
const query = dataService.getRepository().createQueryBuilder('data')
|
||||||
|
let priority: number = 3;
|
||||||
|
// libur / specific date
|
||||||
|
if (data.holidays?.length > 0 || data.start_date == data.end_date || data.holiday_name) priority = 1
|
||||||
|
// specific day
|
||||||
|
else if (data.days?.length > 0) priority = 2
|
||||||
|
|
||||||
|
if (data.id) {
|
||||||
|
query.andWhere('data.id != :dataId', { dataId: data.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
const datas = await query
|
||||||
|
.andWhere('data.priority = :priority', { priority: priority })
|
||||||
|
.andWhere('data.start_date BETWEEN :inputStartDate AND :inputEndDate', { inputStartDate: data.start_date, inputEndDate: data.end_date })
|
||||||
|
.andWhere('data.end_date BETWEEN :inputStartDate AND :inputEndDate', { inputStartDate: data.start_date, inputEndDate: data.end_date }).getCount();
|
||||||
|
|
||||||
|
if (datas > 0) {
|
||||||
|
throw new UnprocessableEntityException({
|
||||||
|
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||||
|
message: `Failed! there is another season period in same range date`,
|
||||||
|
error: 'Unprocessable Entity',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return priority;
|
||||||
|
}
|
|
@ -8,10 +8,16 @@ import {
|
||||||
columnUniques,
|
columnUniques,
|
||||||
validateRelations,
|
validateRelations,
|
||||||
} from 'src/core/strings/constants/interface.constants';
|
} from 'src/core/strings/constants/interface.constants';
|
||||||
|
import { ValidateSeasonPeriodHelper } from './helpers/validate.helper';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UpdateSeasonPeriodManager extends BaseUpdateManager<SeasonPeriodEntity> {
|
export class UpdateSeasonPeriodManager extends BaseUpdateManager<SeasonPeriodEntity> {
|
||||||
async validateProcess(): Promise<void> {
|
async validateProcess(): Promise<void> {
|
||||||
|
const priority = await ValidateSeasonPeriodHelper(this.dataService, this.data);
|
||||||
|
|
||||||
|
Object.assign(this.data, {
|
||||||
|
priority: priority
|
||||||
|
})
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue