feat(SPG-372) REST API Read Item Rate

pull/2/head
Aswin Ashar Abdullah 2024-06-20 05:14:06 +07:00
parent 86f81f3027
commit a3d67ff5be
19 changed files with 394 additions and 55 deletions

View File

@ -1,3 +1,8 @@
import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity';
export interface FilterItemRateEntity extends BaseFilterEntity {}
export interface FilterItemRateEntity extends BaseFilterEntity {
item_ids: string[];
season_period_ids: string[];
start_date: Date;
end_date: Date;
}

View File

@ -6,6 +6,8 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interfa
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
import { DetailItemRateManager } from './managers/detail-item-rate.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { ItemReadService } from 'src/modules/item-related/item/data/services/item-read.service';
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
@Injectable()
export class ItemRateReadOrchestrator extends BaseReadOrchestrator<ItemRateEntity> {
@ -13,13 +15,25 @@ export class ItemRateReadOrchestrator extends BaseReadOrchestrator<ItemRateEntit
private indexManager: IndexItemRateManager,
private detailManager: DetailItemRateManager,
private serviceData: ItemRateReadService,
private itemServiceRead: ItemReadService,
) {
super();
}
// untuk sementara function ini tidak terpakai
async index(params): Promise<PaginationResponse<ItemRateEntity>> {
// this.indexManager.setFilterParam(params);
// this.indexManager.setService(this.itemServiceRead, TABLE_NAME.ITEM_RATE);
// await this.indexManager.execute();
// return this.indexManager.getResult();
return
}
async indexItem(params): Promise<PaginationResponse<ItemEntity>> {
params.ia_all = true;
this.indexManager.setFilterParam(params);
this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM_RATE);
this.indexManager.setService(this.itemServiceRead, TABLE_NAME.ITEM);
await this.indexManager.execute();
return this.indexManager.getResult();
}

View File

@ -1,14 +1,14 @@
import { Injectable } from '@nestjs/common';
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
import { ItemRateEntity } from '../../entities/item-rate.entity';
import { SelectQueryBuilder } from 'typeorm';
import {
Param,
RelationParam,
} from 'src/core/modules/domain/entities/base-filter.entity';
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
@Injectable()
export class IndexItemRateManager extends BaseIndexManager<ItemRateEntity> {
export class IndexItemRateManager extends BaseIndexManager<ItemEntity> {
async prepareData(): Promise<void> {
return;
}
@ -18,6 +18,30 @@ export class IndexItemRateManager extends BaseIndexManager<ItemRateEntity> {
}
async afterProcess(): Promise<void> {
this.result.data?.map(item => {
let prices = []
for (let d = new Date(this.filterParam.start_date); d <= new Date(this.filterParam.end_date); d.setDate(d.getDate() + 1)) {
console.log(d, 'tanggal')
const rate = item['item_rates']?.find(
rate => d >= new Date(rate.season_period.start_date) && d <= new Date(rate.season_period.end_date),
);
prices.push({
date: new Date(d),
price: rate?.price ?? item.base_price,
season_type: rate?.season_period?.season_type ?? null,
holiday_name: rate?.season_period?.holiday_name ?? null,
});
}
delete item['item_rates'];
Object.assign(item, {
dates: prices
})
})
return;
}
@ -27,7 +51,13 @@ export class IndexItemRateManager extends BaseIndexManager<ItemRateEntity> {
joinRelations: [],
// relation join and select (relasi yang ingin ditampilkan),
selectRelations: [],
selectRelations: [
'bundling_items',
'tenant',
'item_rates',
'item_rates.season_period',
'season_period.season_type'
],
// relation yang hanya ingin dihitung (akan return number)
countRelations: [],
@ -35,21 +65,39 @@ export class IndexItemRateManager extends BaseIndexManager<ItemRateEntity> {
}
get selects(): string[] {
return [];
}
get specificFilter(): Param[] {
return [
{
cols: `${this.tableName}.name`,
data: this.filterParam.names,
},
`${ this.tableName }.id`,
`${ this.tableName }.created_at`,
`${ this.tableName }.name`,
`${ this.tableName }.base_price`,
'tenant.id',
'tenant.name',
'bundling_items.id',
'bundling_items.name',
'item_rates.id',
'item_rates.price',
'season_period.id',
'season_period.holiday_name',
'season_period.start_date',
'season_period.end_date',
'season_type.id',
'season_type.name',
];
}
get specificFilter(): Param[] {
return [];
}
setQueryFilter(
queryBuilder: SelectQueryBuilder<ItemRateEntity>,
): SelectQueryBuilder<ItemRateEntity> {
queryBuilder: SelectQueryBuilder<ItemEntity>,
): SelectQueryBuilder<ItemEntity> {
return queryBuilder;
}
}

View File

@ -1,6 +1,36 @@
import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto';
import { FilterItemRateEntity } from '../../domain/entities/filter-item-rate.entity';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class FilterItemRateDto
extends BaseFilterDto
implements FilterItemRateEntity {}
implements FilterItemRateEntity {
@ApiProperty({
required: true,
type: Date,
example: '2024-04-01'
})
start_date: Date;
@ApiProperty({
required: true,
type: Date,
example: '2024-04-30'
})
end_date: Date;
@ApiProperty({ type: ['string'], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
item_ids: string[];
@ApiProperty({ type: ['string'], required: false })
@Transform((body) => {
return Array.isArray(body.value) ? body.value : [body.value];
})
season_period_ids: string[];
}

View File

@ -4,7 +4,6 @@ import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
import { IsObject } from 'class-validator';
import { ItemDto } from 'src/modules/item-related/item/infrastructure/dto/item.dto';
export class ItemRateDto extends BaseCoreDto implements ItemRateEntity {
@Exclude()

View File

@ -0,0 +1,18 @@
import { BaseCoreDto } from 'src/core/modules/infrastructure/dto/base-core.dto';
import { ItemRateEntity } from '../../domain/entities/item-rate.entity';
import { ApiProperty } from '@nestjs/swagger';
import { Exclude } from 'class-transformer';
export class UpdateItemRateDto extends BaseCoreDto implements ItemRateEntity {
@Exclude()
item_id: string;
@Exclude()
season_period_id: string;
@ApiProperty({
type: Number,
required: true,
})
price: number;
}

View File

@ -15,16 +15,20 @@ import { Public } from 'src/core/guards';
export class ItemRateDataController {
constructor(private orchestrator: ItemRateDataOrchestrator) { }
@Post()
async create(@Body() data: ItemRateDto): Promise<ItemRateEntity> {
return await this.orchestrator.create(data);
}
// untuk sementara, tidak dapat create
// @Post()
// async create(@Body() data: ItemRateDto): Promise<ItemRateEntity> {
// return await this.orchestrator.create(data);
// }
@Put('/batch-delete')
async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
return await this.orchestrator.batchDelete(body.ids);
}
// untuk sementara, tidak dapat delete
// @Put('/batch-delete')
// async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
// return await this.orchestrator.batchDelete(body.ids);
// }
// update endpoint digunakan untuk update single price
// pada halaman detail item -> list item rates (dapat update single row)
@Put(':id')
async update(
@Param('id') dataId: string,
@ -33,8 +37,8 @@ export class ItemRateDataController {
return await this.orchestrator.update(dataId, data);
}
@Delete(':id')
async delete(@Param('id') dataId: string): Promise<String> {
return await this.orchestrator.delete(dataId);
}
// @Delete(':id')
// async delete(@Param('id') dataId: string): Promise<String> {
// return await this.orchestrator.delete(dataId);
// }
}

View File

@ -7,6 +7,7 @@ import { ItemRateReadOrchestrator } from '../domain/usecases/item-rate-read.orch
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { Public } from 'src/core/guards';
import { ItemEntity } from '../../item/domain/entities/item.entity';
@ApiTags(`${ MODULE_NAME.ITEM_RATE.split('-').join(' ') } - read`)
@Controller(MODULE_NAME.ITEM_RATE)
@ -19,12 +20,12 @@ export class ItemRateReadController {
@Pagination()
async index(
@Query() params: FilterItemRateDto,
): Promise<PaginationResponse<ItemRateEntity>> {
return await this.orchestrator.index(params);
): Promise<PaginationResponse<ItemEntity>> {
return await this.orchestrator.indexItem(params);
}
@Get(':id')
async detail(@Param('id') id: string): Promise<ItemRateEntity> {
return await this.orchestrator.detail(id);
}
// @Get(':id')
// async detail(@Param('id') id: string): Promise<ItemRateEntity> {
// return await this.orchestrator.detail(id);
// }
}

View File

@ -6,13 +6,19 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interfa
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
import { DetailItemManager } from './managers/detail-item.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { ItemRateReadService } from 'src/modules/item-related/item-rate/data/services/item-rate-read.service';
import { FilterItemRateDto } from 'src/modules/item-related/item-rate/infrastructure/dto/filter-item-rate.dto';
import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entities/item-rate.entity';
import { IndexItemRatesManager } from './managers/index-item-rates.manager';
@Injectable()
export class ItemReadOrchestrator extends BaseReadOrchestrator<ItemEntity> {
constructor(
private indexManager: IndexItemManager,
private detailManager: DetailItemManager,
private indexRateManager: IndexItemRatesManager,
private serviceData: ItemReadService,
private serviceItemData: ItemRateReadService,
) {
super();
}
@ -30,4 +36,16 @@ export class ItemReadOrchestrator extends BaseReadOrchestrator<ItemEntity> {
await this.detailManager.execute();
return this.detailManager.getResult();
}
async indexRate(id): Promise<PaginationResponse<ItemRateEntity>> {
const params = new FilterItemRateDto();
params.item_ids = [id];
console.log(params, 'param')
this.indexRateManager.setFilterParam(params);
this.indexRateManager.setService(this.serviceItemData, TABLE_NAME.ITEM);
await this.indexRateManager.execute();
return this.indexRateManager.getResult();
}
}

View File

@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
import { SelectQueryBuilder } from 'typeorm';
import {
Param,
RelationParam,
} from 'src/core/modules/domain/entities/base-filter.entity';
import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entities/item-rate.entity';
@Injectable()
export class IndexItemRatesManager extends BaseIndexManager<ItemRateEntity> {
async prepareData(): Promise<void> {
this.filterParam.order_by = `${ this.tableName }.id`
return;
}
async beforeProcess(): Promise<void> {
return;
}
async afterProcess(): Promise<void> {
return;
}
get relations(): RelationParam {
return {
// relation only join (for query purpose)
joinRelations: [],
// relation join and select (relasi yang ingin ditampilkan),
selectRelations: ['season_period', 'season_period.season_type'],
// relation yang hanya ingin dihitung (akan return number)
countRelations: [],
};
}
get selects(): string[] {
return [
`${ this.tableName }.id`,
`${ this.tableName }.price`,
`season_period.id`,
`season_period.created_at`,
`season_period.creator_name`,
`season_period.editor_name`,
`season_period.updated_at`,
`season_period.status`,
`season_period.start_date`,
`season_period.end_date`,
`season_period.days`,
`season_period.holiday_name`,
'season_type.id',
'season_type.name',
];
}
get specificFilter(): Param[] {
return [];
}
setQueryFilter(
queryBuilder: SelectQueryBuilder<ItemRateEntity>,
): SelectQueryBuilder<ItemRateEntity> {
if (this.filterParam.item_ids) {
queryBuilder.andWhere(`${ this.tableName }.item_id In (:...itemIds)`, {
itemIds: this.filterParam.item_ids
})
}
return queryBuilder;
}
}

View File

@ -7,6 +7,7 @@ import { ItemReadOrchestrator } from '../domain/usecases/item-read.orchestrator'
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { Public } from 'src/core/guards';
import { ItemRateEntity } from '../../item-rate/domain/entities/item-rate.entity';
@ApiTags(`${ MODULE_NAME.ITEM.split('-').join(' ') } - read`)
@Controller(MODULE_NAME.ITEM)
@ -27,4 +28,13 @@ export class ItemReadController {
async detail(@Param('id') id: string): Promise<ItemEntity> {
return await this.orchestrator.detail(id);
}
@Get(':id/rates')
@Pagination()
async indexRate(
@Param('id') id: string
): Promise<PaginationResponse<ItemRateEntity>> {
console.log(id, 'id')
return await this.orchestrator.indexRate(id);
}
}

View File

@ -22,17 +22,21 @@ import { BatchActiveItemManager } from './domain/usecases/managers/batch-active-
import { BatchConfirmItemManager } from './domain/usecases/managers/batch-confirm-item.manager';
import { BatchInactiveItemManager } from './domain/usecases/managers/batch-inactive-item.manager';
import { ItemModel } from './data/models/item.model';
import { ItemRateModel } from '../item-rate/data/models/item-rate.model';
import { ItemRateReadService } from '../item-rate/data/services/item-rate-read.service';
import { IndexItemRatesManager } from './domain/usecases/managers/index-item-rates.manager';
@Global()
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forFeature([ItemModel], CONNECTION_NAME.DEFAULT),
TypeOrmModule.forFeature([ItemModel, ItemRateModel], CONNECTION_NAME.DEFAULT),
CqrsModule,
],
controllers: [ItemDataController, ItemReadController],
providers: [
IndexItemManager,
IndexItemRatesManager,
DetailItemManager,
CreateItemManager,
DeleteItemManager,
@ -47,12 +51,14 @@ import { ItemModel } from './data/models/item.model';
ItemDataService,
ItemReadService,
ItemRateReadService,
ItemDataOrchestrator,
ItemReadOrchestrator,
],
exports: [
IndexItemManager,
IndexItemRatesManager,
DetailItemManager,
CreateItemManager,
DeleteItemManager,
@ -65,6 +71,7 @@ import { ItemModel } from './data/models/item.model';
BatchConfirmItemManager,
BatchInactiveItemManager,
ItemRateReadService,
ItemDataService,
ItemReadService,

View File

@ -0,0 +1,82 @@
import { Injectable } from '@nestjs/common';
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
import { SelectQueryBuilder } from 'typeorm';
import {
Param,
RelationParam,
} from 'src/core/modules/domain/entities/base-filter.entity';
import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entities/item-rate.entity';
@Injectable()
export class IndexSeasonPeriodeItemManager extends BaseIndexManager<ItemRateEntity> {
async prepareData(): Promise<void> {
this.filterParam.order_by = `${ this.tableName }.id`
return;
}
async beforeProcess(): Promise<void> {
return;
}
async afterProcess(): Promise<void> {
return;
}
get relations(): RelationParam {
return {
// relation only join (for query purpose)
joinRelations: [],
// relation join and select (relasi yang ingin ditampilkan),
selectRelations: ['item', 'item.item_category', 'item.bundling_items'],
// relation yang hanya ingin dihitung (akan return number)
countRelations: [],
};
}
get selects(): string[] {
return [
`${ this.tableName }.id`,
`${ this.tableName }.price`,
`item.id`,
`item.created_at`,
`item.status`,
`item.item_type`,
`item.name`,
`item.hpp`,
`item.limit_type`,
`item.limit_value`,
`item.base_price`,
`item_category.id`,
`item_category.name`,
'bundling_items.id',
'bundling_items.name',
];
}
get specificFilter(): Param[] {
return [
{
cols: `${ this.tableName }.name`,
data: this.filterParam.names,
},
];
}
setQueryFilter(
queryBuilder: SelectQueryBuilder<ItemRateEntity>,
): SelectQueryBuilder<ItemRateEntity> {
if (this.filterParam.season_period_ids) {
queryBuilder.andWhere(`${ this.tableName }.season_period_id In (:...periodIds)`, {
periodIds: this.filterParam.season_period_ids
})
}
return queryBuilder;
}
}

View File

@ -6,13 +6,19 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interfa
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
import { DetailSeasonPeriodManager } from './managers/detail-season-period.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { IndexSeasonPeriodeItemManager } from './managers/index-season-period-item.manager';
import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entities/item-rate.entity';
import { FilterItemRateDto } from 'src/modules/item-related/item-rate/infrastructure/dto/filter-item-rate.dto';
import { ItemRateReadService } from 'src/modules/item-related/item-rate/data/services/item-rate-read.service';
@Injectable()
export class SeasonPeriodReadOrchestrator extends BaseReadOrchestrator<SeasonPeriodEntity> {
constructor(
private indexManager: IndexSeasonPeriodManager,
private detailManager: DetailSeasonPeriodManager,
private indexItemManager: IndexSeasonPeriodeItemManager,
private serviceData: SeasonPeriodReadService,
private itemServiceRead: ItemRateReadService,
) {
super();
}
@ -30,4 +36,14 @@ export class SeasonPeriodReadOrchestrator extends BaseReadOrchestrator<SeasonPer
await this.detailManager.execute();
return this.detailManager.getResult();
}
async indexItem(id): Promise<PaginationResponse<ItemRateEntity>> {
const params = new FilterItemRateDto();
params.season_period_ids = [id];
this.indexItemManager.setFilterParam(params);
this.indexItemManager.setService(this.itemServiceRead, TABLE_NAME.SEASON_PERIOD);
await this.indexItemManager.execute();
return this.indexItemManager.getResult();
}
}

View File

@ -74,6 +74,7 @@ export class SeasonPeriodDataController {
return await this.orchestrator.update(dataId, data);
}
// pemisahan update data dengan update items dikarenakan payload (based on tampilan) berbeda
@Put(':id/items')
async updateItems(
@Param('id') dataId: string,

View File

@ -7,6 +7,7 @@ import { SeasonPeriodReadOrchestrator } from '../domain/usecases/season-period-r
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { MODULE_NAME } from 'src/core/strings/constants/module.constants';
import { Public } from 'src/core/guards';
import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entities/item-rate.entity';
@ApiTags(`${ MODULE_NAME.SEASON_PERIOD.split('-').join(' ') } - read`)
@Controller(MODULE_NAME.SEASON_PERIOD)
@ -27,4 +28,10 @@ export class SeasonPeriodReadController {
async detail(@Param('id') id: string): Promise<SeasonPeriodEntity> {
return await this.orchestrator.detail(id);
}
@Get(':id/items')
@Pagination()
async indexItem(@Param('id') id: string): Promise<PaginationResponse<ItemRateEntity>> {
return await this.orchestrator.indexItem(id);
}
}

View File

@ -23,11 +23,14 @@ import { BatchConfirmSeasonPeriodManager } from './domain/usecases/managers/batc
import { BatchInactiveSeasonPeriodManager } from './domain/usecases/managers/batch-inactive-season-period.manager';
import { SeasonPeriodModel } from './data/models/season-period.model';
import { SeasonPeriodHolidayHandler } from './domain/usecases/handlers/season-period-created.handler';
import { IndexSeasonPeriodeItemManager } from './domain/usecases/managers/index-season-period-item.manager';
import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model';
import { ItemRateReadService } from 'src/modules/item-related/item-rate/data/services/item-rate-read.service';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forFeature([SeasonPeriodModel], CONNECTION_NAME.DEFAULT),
TypeOrmModule.forFeature([SeasonPeriodModel, ItemRateModel], CONNECTION_NAME.DEFAULT),
CqrsModule,
],
controllers: [SeasonPeriodDataController, SeasonPeriodReadController],
@ -35,6 +38,7 @@ import { SeasonPeriodHolidayHandler } from './domain/usecases/handlers/season-pe
SeasonPeriodHolidayHandler,
IndexSeasonPeriodManager,
IndexSeasonPeriodeItemManager,
DetailSeasonPeriodManager,
CreateSeasonPeriodManager,
DeleteSeasonPeriodManager,
@ -49,6 +53,7 @@ import { SeasonPeriodHolidayHandler } from './domain/usecases/handlers/season-pe
SeasonPeriodDataService,
SeasonPeriodReadService,
ItemRateReadService,
SeasonPeriodDataOrchestrator,
SeasonPeriodReadOrchestrator,