Merge branch 'development' of ssh://git.eigen.co.id:2222/eigen/pos-be into development
continuous-integration/drone/tag Build is passing Details

pull/60/head^2 devel_20.1.17
shancheas 2024-08-08 15:47:53 +07:00
commit efe5661a57
13 changed files with 257 additions and 8 deletions

View File

@ -15,6 +15,26 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
abstract get entityTarget(): any;
setData(ids: string[], status: STATUS): void {
/**
* // TODO: Handle case confirm multiple tabs;
* Pola ids yang dikirim dirubah menjadi data_id___updated_at
* Untuk mendapatkan value id nya saja dan menghindari breaking change
* karena sudah digunakan sebelumnya lakukan split dari data ids yang dikirim
* Example:
* this.dataIds = ids.map((i)=> {
* return i.split('___')[0]
* })
*
* Simpan data ids yang mempunyai update_at kedalam valiable baru
* Example:
* this.dataIdsWithDate = ids.map((i)=> {
* return {
* id: i.split('___')[0],
* updated_at: i.split('___')[1]
* }
* })
*/
this.dataIds = ids;
this.dataStatus = status;
}
@ -32,8 +52,21 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
let totalSuccess = 0;
const messages = [];
/**
* // TODO: Handle case confirm multiple tabs;
* Lopping data diambil dari dataIdsWithDate
* exp: for (const item of this.dataIdsWithDate)
*/
for (const id of this.dataIds) {
try {
/**
* // TODO: Handle case confirm multiple tabs;
* buat variable:
* const id = item.id
* const updated_at = item.updated_at
*/
const entity = await this.dataService.getOneByOptions({
where: {
id: id,
@ -64,6 +97,14 @@ export abstract class BaseBatchUpdateStatusManager<Entity> extends BaseManager {
this.tableName,
).execute();
/**
* // TODO: Handle case confirm multiple tabs;
* lakukan update data dengan where condition id dan updated_at
* EXPECTATION => status akan berubah jika updated_at yang dikirim dari FE sama dengen yang di database
* IF => updated_at beda tidak perlu melakukan update status dan tidak perlu memanggil eventBus tetapi tetap dihitung sebagai aksi yang berhasil
* IF => FE tidak menambahkan updated_at makan lakukan update dan publishEvent
*/
const result = await this.dataService.update(
this.queryRunner,
this.entityTarget,

View File

@ -14,6 +14,22 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
abstract get entityTarget(): any;
setData(id: string, status: STATUS): void {
/**
* // TODO: Handle case confirm multiple tabs;
* Pola id yang dikirim dirubah menjadi data_id___updated_at
* Untuk mendapatkan value id nya saja dan menghindari breaking change
* karena sudah digunakan sebelumnya lakukan split dari data ids yang dikirim
* Example:
* this.dataId = id.split('___')[0]
*
* Simpan data id yang mempunyai update_at kedalam valiable baru
* Example:
* this.dataIdsWithDate = {
* id: id.split('___')[0],
* updated_at: id.split('___')[1]
* }
*/
this.dataId = id;
this.dataStatus = status;
}
@ -43,6 +59,16 @@ export abstract class BaseUpdateStatusManager<Entity> extends BaseManager {
this.tableName,
).execute();
/**
* // TODO: Handle case confirm multiple tabs;
* IF => updated_at sama dengen data yang di database
* THEN =>
* - Lakukan update data dengan where condition id dan updated_at
* - EXPECTATION = > status akan berubah jika updated_at yang dikirim dari FE sama dengen yang di database
* IF => updated_at beda maka retun curent data tanpa harus malakukan update status dan publish event
* IF => FE tidak menambahkan updated_at makan lakukan update dan publishEvent
*/
this.result = await this.dataService.update(
this.queryRunner,
this.entityTarget,

View File

@ -43,6 +43,13 @@ import { TransactionModel } from 'src/modules/transaction/transaction/data/model
import { TransactionTaxModel } from 'src/modules/transaction/transaction/data/models/transaction-tax.model';
import { TransactionItemModel } from 'src/modules/transaction/transaction/data/models/transaction-item.model';
import { VipCodeCreatedHandler } from './domain/managers/vip-code.handler';
import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model';
import {
SeasonTypeDeletedHandler,
SeasonTypeUpdatedHandler,
} from './domain/managers/season-type.handler';
import { SeasonPeriodDataService } from 'src/modules/season-related/season-period/data/services/season-period-data.service';
import { SeasonPeriodModel } from 'src/modules/season-related/season-period/data/models/season-period.model';
@Module({
imports: [
@ -50,6 +57,8 @@ import { VipCodeCreatedHandler } from './domain/managers/vip-code.handler';
TypeOrmModule.forFeature(
[
ItemModel,
ItemRateModel,
SeasonPeriodModel,
UserModel,
TransactionModel,
TransactionTaxModel,
@ -80,6 +89,10 @@ import { VipCodeCreatedHandler } from './domain/managers/vip-code.handler';
UserUpdatedHandler,
UserPrivilegeUpdateHandler,
SeasonTypeDeletedHandler,
SeasonTypeUpdatedHandler,
SeasonPeriodDataService,
TransactionDataService,
UserDataService,
ItemDataService,

View File

@ -0,0 +1,52 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CouchService } from '../../data/services/couch.service';
import { SeasonTypeDeletedEvent } from 'src/modules/season-related/season-type/domain/entities/event/season-type-deleted.event';
import { SeasonTypeChangeStatusEvent } from 'src/modules/season-related/season-type/domain/entities/event/season-type-change-status.event';
import { SeasonTypeUpdatedEvent } from 'src/modules/season-related/season-type/domain/entities/event/season-type-updated.event';
import { SeasonPeriodDataService } from 'src/modules/season-related/season-period/data/services/season-period-data.service';
@EventsHandler(SeasonTypeDeletedEvent)
export class SeasonTypeDeletedHandler
implements IEventHandler<SeasonTypeDeletedEvent>
{
constructor(private couchService: CouchService) {}
async handle(event: SeasonTypeDeletedEvent) {
console.log('deleted session type');
}
}
@EventsHandler(SeasonTypeChangeStatusEvent, SeasonTypeUpdatedEvent)
export class SeasonTypeUpdatedHandler
implements IEventHandler<SeasonTypeChangeStatusEvent>
{
constructor(
private couchService: CouchService,
private seasonPeriodService: SeasonPeriodDataService,
) {}
async handle(event: SeasonTypeChangeStatusEvent) {
const data = event.data.data;
const typeID = data.id;
const periods = await this.seasonPeriodService.getManyByOptions({
where: {
season_type_id: typeID,
},
relations: ['season_type'],
});
for (const period of periods) {
const dataID = period.id;
const couchData = await this.couchService.getDoc(dataID, 'season_period');
if (couchData) {
await this.couchService.updateDoc(
{
_id: dataID,
...period,
},
'season_period',
);
}
}
}
}

View File

@ -5,13 +5,30 @@ import { InjectRepository } from '@nestjs/typeorm';
import { ItemModel } from '../models/item.model';
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
import { Repository } from 'typeorm';
import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model';
@Injectable()
export class ItemDataService extends BaseDataService<ItemEntity> {
constructor(
@InjectRepository(ItemModel, CONNECTION_NAME.DEFAULT)
private repo: Repository<ItemModel>,
@InjectRepository(ItemRateModel, CONNECTION_NAME.DEFAULT)
private repoItemRate: Repository<ItemRateModel>,
) {
super(repo);
}
async updateItemRatePrice(
oldPrice: number,
newPrice: number,
itemId: string,
): Promise<void> {
console.log({ oldPrice, newPrice, itemId });
this.repoItemRate.update(
{ item_id: itemId, price: oldPrice },
{ price: newPrice },
);
}
}

View File

@ -11,15 +11,26 @@ import {
@Injectable()
export class UpdateItemManager extends BaseUpdateManager<ItemEntity> {
protected oldBasePrice: number;
async validateProcess(): Promise<void> {
return;
}
async beforeProcess(): Promise<void> {
this.oldBasePrice = this.oldData.base_price;
return;
}
async afterProcess(): Promise<void> {
const newBasePrice = this.result.base_price;
const itemId = this.result.id;
await this.dataService.updateItemRatePrice(
this.oldBasePrice,
newBasePrice,
itemId,
);
return;
}

View File

@ -7,7 +7,11 @@ import {
import { SeasonTypeModel } from '../../../data/models/season-type.model';
import { SeasonTypeDeletedEvent } from '../../entities/event/season-type-deleted.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { Injectable } from '@nestjs/common';
import {
HttpStatus,
Injectable,
UnprocessableEntityException,
} from '@nestjs/common';
@Injectable()
export class BatchDeleteSeasonTypeManager extends BaseBatchDeleteManager<SeasonTypeEntity> {
@ -16,6 +20,19 @@ export class BatchDeleteSeasonTypeManager extends BaseBatchDeleteManager<SeasonT
}
async validateData(data: SeasonTypeEntity): Promise<void> {
const relationData = await this.dataServiceFirstOpt.getOneByOptions({
where: {
season_type_id: data.id,
},
});
if (relationData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagagl! data sudah berelasi dengen season period.`,
error: 'Unprocessable Entity',
});
}
return;
}

View File

@ -7,11 +7,28 @@ import {
import { SeasonTypeModel } from '../../../data/models/season-type.model';
import { SeasonTypeChangeStatusEvent } from '../../entities/event/season-type-change-status.event';
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
import { Injectable } from '@nestjs/common';
import {
HttpStatus,
Injectable,
UnprocessableEntityException,
} from '@nestjs/common';
@Injectable()
export class BatchInactiveSeasonTypeManager extends BaseBatchUpdateStatusManager<SeasonTypeEntity> {
validateData(data: SeasonTypeEntity): Promise<void> {
async validateData(data: SeasonTypeEntity): Promise<void> {
const relationData = await this.dataServiceFirstOpt.getOneByOptions({
where: {
season_type_id: data.id,
},
});
if (relationData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagagl! data sudah berelasi dengen season period.`,
error: 'Unprocessable Entity',
});
}
return;
}

View File

@ -1,4 +1,8 @@
import { Injectable } from '@nestjs/common';
import {
HttpStatus,
Injectable,
UnprocessableEntityException,
} from '@nestjs/common';
import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager';
import { SeasonTypeEntity } from '../../entities/season-type.entity';
import {
@ -15,6 +19,19 @@ export class DeleteSeasonTypeManager extends BaseDeleteManager<SeasonTypeEntity>
}
async validateProcess(): Promise<void> {
const relationData = await this.dataServiceFirstOpt.getOneByOptions({
where: {
season_type_id: this.dataId,
},
});
if (relationData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagagl! data sudah berelasi dengen season period.`,
error: 'Unprocessable Entity',
});
}
return;
}

View File

@ -1,4 +1,8 @@
import { Injectable } from '@nestjs/common';
import {
HttpStatus,
Injectable,
UnprocessableEntityException,
} from '@nestjs/common';
import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager';
import { SeasonTypeEntity } from '../../entities/season-type.entity';
import {
@ -15,6 +19,20 @@ export class InactiveSeasonTypeManager extends BaseUpdateStatusManager<SeasonTyp
}
async validateProcess(): Promise<void> {
const relationData = await this.dataServiceFirstOpt.getOneByOptions({
where: {
season_type_id: this.dataId,
},
});
if (relationData) {
throw new UnprocessableEntityException({
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
message: `Gagagl! data sudah berelasi dengen season period.`,
error: 'Unprocessable Entity',
});
}
return;
}

View File

@ -15,6 +15,7 @@ import { BatchInactiveSeasonTypeManager } from './managers/batch-inactive-season
import { BatchActiveSeasonTypeManager } from './managers/batch-active-season-type.manager';
import { BatchDeleteSeasonTypeManager } from './managers/batch-delete-season-type.manager';
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
import { SeasonPeriodDataService } from 'src/modules/season-related/season-period/data/services/season-period-data.service';
@Injectable()
export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<SeasonTypeEntity> {
@ -30,6 +31,7 @@ export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<
private batchConfirmManager: BatchConfirmSeasonTypeManager,
private batchInactiveManager: BatchInactiveSeasonTypeManager,
private serviceData: SeasonTypeDataService,
private servicePeriodData: SeasonPeriodDataService,
) {
super();
}
@ -50,7 +52,11 @@ export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<
async delete(dataId): Promise<string> {
this.deleteManager.setData(dataId);
this.deleteManager.setService(this.serviceData, TABLE_NAME.SEASON_TYPE);
this.deleteManager.setService(
this.serviceData,
TABLE_NAME.SEASON_TYPE,
this.servicePeriodData,
);
await this.deleteManager.execute();
return this.deleteManager.getResult();
}
@ -60,6 +66,7 @@ export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<
this.batchDeleteManager.setService(
this.serviceData,
TABLE_NAME.SEASON_TYPE,
this.servicePeriodData,
);
await this.batchDeleteManager.execute();
return this.batchDeleteManager.getResult();
@ -101,7 +108,11 @@ export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<
async inactive(dataId): Promise<string> {
this.inactiveManager.setData(dataId, STATUS.INACTIVE);
this.inactiveManager.setService(this.serviceData, TABLE_NAME.SEASON_TYPE);
this.inactiveManager.setService(
this.serviceData,
TABLE_NAME.SEASON_TYPE,
this.servicePeriodData,
);
await this.inactiveManager.execute();
return this.inactiveManager.getResult();
}
@ -111,6 +122,7 @@ export class SeasonTypeDataOrchestrator extends BaseDataTransactionOrchestrator<
this.batchInactiveManager.setService(
this.serviceData,
TABLE_NAME.SEASON_TYPE,
this.servicePeriodData,
);
await this.batchInactiveManager.execute();
return this.batchInactiveManager.getResult();

View File

@ -22,11 +22,16 @@ import { BatchActiveSeasonTypeManager } from './domain/usecases/managers/batch-a
import { BatchConfirmSeasonTypeManager } from './domain/usecases/managers/batch-confirm-season-type.manager';
import { BatchInactiveSeasonTypeManager } from './domain/usecases/managers/batch-inactive-season-type.manager';
import { SeasonTypeModel } from './data/models/season-type.model';
import { SeasonPeriodDataService } from '../season-period/data/services/season-period-data.service';
import { SeasonPeriodModel } from '../season-period/data/models/season-period.model';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forFeature([SeasonTypeModel], CONNECTION_NAME.DEFAULT),
TypeOrmModule.forFeature(
[SeasonTypeModel, SeasonPeriodModel],
CONNECTION_NAME.DEFAULT,
),
CqrsModule,
],
controllers: [SeasonTypeDataController, SeasonTypeReadController],
@ -49,6 +54,7 @@ import { SeasonTypeModel } from './data/models/season-type.model';
SeasonTypeDataOrchestrator,
SeasonTypeReadOrchestrator,
SeasonPeriodDataService,
],
})
export class SeasonTypeModule {}

View File

@ -26,6 +26,7 @@ export class IndexTransactionManager extends BaseIndexManager<TransactionEntity>
);
Object.assign(item, {
refund_type: activeRefund?.type ?? null,
refund_code: activeRefund?.code ?? null,
refund_date: activeRefund?.refund_date ?? null,
});
@ -86,6 +87,7 @@ export class IndexTransactionManager extends BaseIndexManager<TransactionEntity>
`refunds.code`,
`refunds.refund_date`,
`refunds.request_date`,
`refunds.type`,
];
}