fix(change-position) perbaikan change position module
parent
12359f3685
commit
37b12c960f
|
@ -21,6 +21,15 @@ export abstract class BaseDataService<Entity> {
|
|||
return await queryRunner.manager.save(newEntity);
|
||||
}
|
||||
|
||||
async createMany(
|
||||
queryRunner: QueryRunner,
|
||||
entityTarget: EntityTarget<Entity>,
|
||||
entity: Entity[],
|
||||
): Promise<Entity[]> {
|
||||
const newEntity = queryRunner.manager.create(entityTarget, entity);
|
||||
return await queryRunner.manager.save(newEntity);
|
||||
}
|
||||
|
||||
async createBatch(
|
||||
queryRunner: QueryRunner,
|
||||
entityTarget: EntityTarget<Entity>,
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
import { BaseManager } from '../base.manager';
|
||||
import {
|
||||
EventTopics,
|
||||
columnUniques,
|
||||
validateRelations,
|
||||
} from 'src/core/strings/constants/interface.constants';
|
||||
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
|
||||
import { SelectQueryBuilder } from 'typeorm';
|
||||
|
||||
export abstract class BaseChangePosition<Entity> extends BaseManager {
|
||||
protected result: Entity;
|
||||
protected duplicateColumn: string[];
|
||||
protected startData: Entity;
|
||||
protected endData: Entity;
|
||||
protected columnSort: string;
|
||||
|
||||
protected firstDataId: number;
|
||||
protected lastSort: number;
|
||||
protected sortTo: number;
|
||||
|
||||
abstract get entityTarget(): any;
|
||||
|
||||
setData(entity: Entity, columnSort: string): void {
|
||||
this.data = entity;
|
||||
this.columnSort = columnSort;
|
||||
}
|
||||
|
||||
async beforeProcess(): Promise<void> {
|
||||
if (!this.data?.end || this.data.start == this.data?.end) {
|
||||
throw new UnprocessableEntityException({
|
||||
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
message: 'Please drag to another position',
|
||||
error: 'Unprocessable Entity',
|
||||
});
|
||||
}
|
||||
|
||||
this.startData = await this.dataService.getOneByOptions({
|
||||
where: {
|
||||
id: this.data.start,
|
||||
},
|
||||
});
|
||||
|
||||
if (!this.startData) {
|
||||
throw new UnprocessableEntityException({
|
||||
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
message: `Entity with id : ${this.data.start} not found`,
|
||||
error: 'Unprocessable Entity',
|
||||
});
|
||||
}
|
||||
|
||||
this.endData = await this.dataService.getOneByOptions({
|
||||
where: {
|
||||
id: this.data.end,
|
||||
},
|
||||
});
|
||||
|
||||
if (!this.endData) {
|
||||
throw new UnprocessableEntityException({
|
||||
statusCode: HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
message: `Entity with id : ${this.data.end} not found`,
|
||||
error: 'Unprocessable Entity',
|
||||
});
|
||||
}
|
||||
|
||||
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
|
||||
// drag from up
|
||||
this.firstDataId = this.startData[this.columnSort];
|
||||
this.lastSort = this.endData[this.columnSort];
|
||||
this.sortTo = this.lastSort;
|
||||
} else if (
|
||||
this.endData[this.columnSort] < this.startData[this.columnSort]
|
||||
) {
|
||||
// drag from bottom
|
||||
this.firstDataId = this.endData[this.columnSort];
|
||||
this.lastSort = this.startData[this.columnSort];
|
||||
this.sortTo = this.firstDataId;
|
||||
}
|
||||
}
|
||||
|
||||
async prepareData(): Promise<void> {
|
||||
Object.assign(this.data, {
|
||||
creator_id: this.user.id,
|
||||
creator_name: this.user.name,
|
||||
created_at: new Date().getTime(),
|
||||
updated_at: new Date().getTime(),
|
||||
});
|
||||
}
|
||||
|
||||
async validateProcess(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
async process(): Promise<void> {
|
||||
let dataArrange: Entity[];
|
||||
|
||||
const queryBuilder = this.dataService
|
||||
.getRepository()
|
||||
.createQueryBuilder(this.tableName)
|
||||
.where(`${this.tableName}.${this.columnSort} between :data1 and :data2`, {
|
||||
data1: this.firstDataId,
|
||||
data2: this.lastSort,
|
||||
});
|
||||
|
||||
const datas = await queryBuilder
|
||||
.orderBy(`${this.tableName}.${this.columnSort}`, 'ASC')
|
||||
.getManyAndCount();
|
||||
|
||||
if (datas[0].length) {
|
||||
let dataFirst = datas[0][0][this.columnSort];
|
||||
const data = datas[0];
|
||||
const length = datas[1];
|
||||
|
||||
if (this.endData[this.columnSort] > this.startData[this.columnSort]) {
|
||||
// drag from above
|
||||
const dataDragged = data[0];
|
||||
const arraySlice = data.slice(1, length);
|
||||
dataArrange = arraySlice.concat([dataDragged]);
|
||||
} else if (
|
||||
this.endData[this.columnSort] < this.startData[this.columnSort]
|
||||
) {
|
||||
// drag from bottom
|
||||
const dataDragged = data[length - 1];
|
||||
const arraySlice = data.slice(0, length - 1);
|
||||
|
||||
dataArrange = [dataDragged].concat(arraySlice);
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
dataArrange[i][this.columnSort] = dataFirst;
|
||||
dataFirst++;
|
||||
}
|
||||
|
||||
await this.dataService.createMany(
|
||||
this.queryRunner,
|
||||
this.entityTarget,
|
||||
dataArrange,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
get validateRelations(): validateRelations[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
get eventTopics(): EventTopics[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
getResult(): string {
|
||||
return `Success! Data ${this.startData['name']} successfully moved to ${this.sortTo}`;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export class ChangePositionDto {
|
||||
start: string;
|
||||
end: string;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UpdateSortColumn1721284172572 implements MigrationInterface {
|
||||
name = 'UpdateSortColumn1721284172572';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "term_conditions" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "faqs" ADD "sort_order" integer NOT NULL DEFAULT '0'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "faqs" DROP COLUMN "sort_order"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "term_conditions" DROP COLUMN "sort_order"`,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UpdateMidtransColumnTransaction1721284234428
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'UpdateMidtransColumnTransaction1721284234428';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_url"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "transactions" DROP COLUMN "payment_midtrans_token"`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "transactions" ADD "payment_midtrans_token" character varying`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "transactions" ADD "payment_midtrans_url" character varying`,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,9 @@ import { BaseStatusModel } from 'src/core/modules/data/model/base-status.model';
|
|||
|
||||
@Entity(TABLE_NAME.FAQ)
|
||||
export class FaqModel extends BaseStatusModel<FaqEntity> implements FaqEntity {
|
||||
@Column('int', { name: 'sort_order', default: 0 })
|
||||
sort_order: number;
|
||||
|
||||
@Column('varchar', { name: 'title', nullable: true })
|
||||
title: string;
|
||||
|
||||
|
|
|
@ -14,4 +14,16 @@ export class FaqDataService extends BaseDataService<FaqEntity> {
|
|||
) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
async getSortColumn(): Promise<number> {
|
||||
const query = this.repo.createQueryBuilder('data');
|
||||
|
||||
const sortColumn = await query
|
||||
.select('data.sort_order')
|
||||
.orderBy('data.sort_order', 'DESC')
|
||||
.getOne();
|
||||
|
||||
const lastColumn = sortColumn?.sort_order ?? 0;
|
||||
return lastColumn + 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity';
|
||||
|
||||
export interface FaqEntity extends BaseStatusEntity {
|
||||
sort_order: number;
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { BatchInactiveFaqManager } from './managers/batch-inactive-faq.manager';
|
|||
import { BatchActiveFaqManager } from './managers/batch-active-faq.manager';
|
||||
import { BatchDeleteFaqManager } from './managers/batch-delete-faq.manager';
|
||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||
import { ChangePositionFaqManager } from './managers/change-position-faq.manager';
|
||||
|
||||
@Injectable()
|
||||
export class FaqDataOrchestrator extends BaseDataTransactionOrchestrator<FaqEntity> {
|
||||
|
@ -29,11 +30,19 @@ export class FaqDataOrchestrator extends BaseDataTransactionOrchestrator<FaqEnti
|
|||
private batchActiveManager: BatchActiveFaqManager,
|
||||
private batchConfirmManager: BatchConfirmFaqManager,
|
||||
private batchInactiveManager: BatchInactiveFaqManager,
|
||||
private changePositionManager: ChangePositionFaqManager,
|
||||
private serviceData: FaqDataService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async changePostion(data): Promise<string> {
|
||||
this.changePositionManager.setData(data, 'sort_order');
|
||||
this.changePositionManager.setService(this.serviceData, TABLE_NAME.FAQ);
|
||||
await this.changePositionManager.execute();
|
||||
return this.changePositionManager.getResult();
|
||||
}
|
||||
|
||||
async create(data): Promise<FaqEntity> {
|
||||
this.createManager.setData(data);
|
||||
this.createManager.setService(this.serviceData, TABLE_NAME.FAQ);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { BaseChangePosition } from 'src/core/modules/domain/usecase/managers/base-change-position.manager';
|
||||
import { FaqEntity } from '../../entities/faq.entity';
|
||||
import { FaqModel } from '../../../data/models/faq.model';
|
||||
|
||||
@Injectable()
|
||||
export class ChangePositionFaqManager extends BaseChangePosition<FaqEntity> {
|
||||
get entityTarget(): any {
|
||||
return FaqModel;
|
||||
}
|
||||
|
||||
async afterProcess(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,11 @@ import { FaqCreatedEvent } from '../../entities/event/faq-created.event';
|
|||
@Injectable()
|
||||
export class CreateFaqManager extends BaseCreateManager<FaqEntity> {
|
||||
async beforeProcess(): Promise<void> {
|
||||
const sortColumn = await this.dataService.getSortColumn();
|
||||
|
||||
Object.assign(this.data, {
|
||||
sort_order: sortColumn,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import { BatchActiveFaqManager } from './domain/usecases/managers/batch-active-f
|
|||
import { BatchConfirmFaqManager } from './domain/usecases/managers/batch-confirm-faq.manager';
|
||||
import { BatchInactiveFaqManager } from './domain/usecases/managers/batch-inactive-faq.manager';
|
||||
import { FaqModel } from './data/models/faq.model';
|
||||
import { ChangePositionFaqManager } from './domain/usecases/managers/change-position-faq.manager';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -43,6 +44,7 @@ import { FaqModel } from './data/models/faq.model';
|
|||
BatchActiveFaqManager,
|
||||
BatchConfirmFaqManager,
|
||||
BatchInactiveFaqManager,
|
||||
ChangePositionFaqManager,
|
||||
|
||||
FaqDataService,
|
||||
FaqReadService,
|
||||
|
|
|
@ -2,8 +2,12 @@ import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.d
|
|||
import { FaqEntity } from '../../domain/entities/faq.entity';
|
||||
import { IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Exclude } from 'class-transformer';
|
||||
|
||||
export class FaqDto extends BaseStatusDto implements FaqEntity {
|
||||
@Exclude()
|
||||
sort_order: number;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
|
@ -15,6 +15,7 @@ import { FaqEntity } from '../domain/entities/faq.entity';
|
|||
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
|
||||
import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto';
|
||||
import { Public } from 'src/core/guards';
|
||||
import { ChangePositionDto } from 'src/core/modules/infrastructure/dto/base-change-position.dto';
|
||||
|
||||
@ApiTags(`${MODULE_NAME.FAQ.split('-').join(' ')} - data`)
|
||||
@Controller(`v1/${MODULE_NAME.FAQ}`)
|
||||
|
@ -28,6 +29,11 @@ export class FaqDataController {
|
|||
return await this.orchestrator.create(data);
|
||||
}
|
||||
|
||||
@Post('/change-position')
|
||||
async dragDrop(@Body() body: ChangePositionDto): Promise<string> {
|
||||
return await this.orchestrator.changePostion(body);
|
||||
}
|
||||
|
||||
@Put('/batch-delete')
|
||||
async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
|
||||
return await this.orchestrator.batchDelete(body.ids);
|
||||
|
|
|
@ -8,6 +8,9 @@ export class TermConditionModel
|
|||
extends BaseStatusModel<TermConditionEntity>
|
||||
implements TermConditionEntity
|
||||
{
|
||||
@Column('int', { name: 'sort_order', default: 0 })
|
||||
sort_order: number;
|
||||
|
||||
@Column('varchar', { name: 'title', nullable: true })
|
||||
title: string;
|
||||
|
||||
|
|
|
@ -14,4 +14,16 @@ export class TermConditionDataService extends BaseDataService<TermConditionEntit
|
|||
) {
|
||||
super(repo);
|
||||
}
|
||||
|
||||
async getSortColumn(): Promise<number> {
|
||||
const query = this.repo.createQueryBuilder('data');
|
||||
|
||||
const sortColumn = await query
|
||||
.select('data.sort_order')
|
||||
.orderBy('data.sort_order', 'DESC')
|
||||
.getOne();
|
||||
|
||||
const lastColumn = sortColumn?.sort_order ?? 0;
|
||||
return lastColumn + 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity';
|
||||
|
||||
export interface TermConditionEntity extends BaseStatusEntity {
|
||||
sort_order: number;
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { BaseChangePosition } from 'src/core/modules/domain/usecase/managers/base-change-position.manager';
|
||||
import { TermConditionEntity } from '../../entities/term-condition.entity';
|
||||
import { TermConditionModel } from '../../../data/models/term-condition.model';
|
||||
|
||||
@Injectable()
|
||||
export class ChangePositionTermConditionManager extends BaseChangePosition<TermConditionEntity> {
|
||||
get entityTarget(): any {
|
||||
return TermConditionModel;
|
||||
}
|
||||
|
||||
async afterProcess(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,11 @@ import { TermConditionCreatedEvent } from '../../entities/event/term-condition-c
|
|||
@Injectable()
|
||||
export class CreateTermConditionManager extends BaseCreateManager<TermConditionEntity> {
|
||||
async beforeProcess(): Promise<void> {
|
||||
const sortColumn = await this.dataService.getSortColumn();
|
||||
|
||||
Object.assign(this.data, {
|
||||
sort_order: sortColumn,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import { BatchInactiveTermConditionManager } from './managers/batch-inactive-ter
|
|||
import { BatchActiveTermConditionManager } from './managers/batch-active-term-condition.manager';
|
||||
import { BatchDeleteTermConditionManager } from './managers/batch-delete-term-condition.manager';
|
||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||
import { ChangePositionTermConditionManager } from './managers/change-position-term-condition.manager';
|
||||
|
||||
@Injectable()
|
||||
export class TermConditionDataOrchestrator extends BaseDataTransactionOrchestrator<TermConditionEntity> {
|
||||
|
@ -29,11 +30,22 @@ export class TermConditionDataOrchestrator extends BaseDataTransactionOrchestrat
|
|||
private batchActiveManager: BatchActiveTermConditionManager,
|
||||
private batchConfirmManager: BatchConfirmTermConditionManager,
|
||||
private batchInactiveManager: BatchInactiveTermConditionManager,
|
||||
private changePositionManager: ChangePositionTermConditionManager,
|
||||
private serviceData: TermConditionDataService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async changePostion(data): Promise<string> {
|
||||
this.changePositionManager.setData(data, 'sort_order');
|
||||
this.changePositionManager.setService(
|
||||
this.serviceData,
|
||||
TABLE_NAME.TERM_CONDITION,
|
||||
);
|
||||
await this.changePositionManager.execute();
|
||||
return this.changePositionManager.getResult();
|
||||
}
|
||||
|
||||
async create(data): Promise<TermConditionEntity> {
|
||||
this.createManager.setData(data);
|
||||
this.createManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION);
|
||||
|
|
|
@ -2,11 +2,15 @@ import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.d
|
|||
import { TermConditionEntity } from '../../domain/entities/term-condition.entity';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { Exclude } from 'class-transformer';
|
||||
|
||||
export class TermConditionDto
|
||||
extends BaseStatusDto
|
||||
implements TermConditionEntity
|
||||
{
|
||||
@Exclude()
|
||||
sort_order: number;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
|
@ -15,6 +15,7 @@ import { TermConditionEntity } from '../domain/entities/term-condition.entity';
|
|||
import { BatchResult } from 'src/core/response/domain/ok-response.interface';
|
||||
import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto';
|
||||
import { Public } from 'src/core/guards';
|
||||
import { ChangePositionDto } from 'src/core/modules/infrastructure/dto/base-change-position.dto';
|
||||
|
||||
@ApiTags(`${MODULE_NAME.TERM_CONDITION.split('-').join(' ')} - data`)
|
||||
@Controller(`v1/${MODULE_NAME.TERM_CONDITION}`)
|
||||
|
@ -28,6 +29,11 @@ export class TermConditionDataController {
|
|||
return await this.orchestrator.create(data);
|
||||
}
|
||||
|
||||
@Post('/change-position')
|
||||
async dragDrop(@Body() body: ChangePositionDto): Promise<string> {
|
||||
return await this.orchestrator.changePostion(body);
|
||||
}
|
||||
|
||||
@Put('/batch-delete')
|
||||
async batchDeleted(@Body() body: BatchIdsDto): Promise<BatchResult> {
|
||||
return await this.orchestrator.batchDelete(body.ids);
|
||||
|
|
|
@ -22,6 +22,7 @@ import { BatchActiveTermConditionManager } from './domain/usecases/managers/batc
|
|||
import { BatchConfirmTermConditionManager } from './domain/usecases/managers/batch-confirm-term-condition.manager';
|
||||
import { BatchInactiveTermConditionManager } from './domain/usecases/managers/batch-inactive-term-condition.manager';
|
||||
import { TermConditionModel } from './data/models/term-condition.model';
|
||||
import { ChangePositionTermConditionManager } from './domain/usecases/managers/change-position-term-condition.manager';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -43,6 +44,7 @@ import { TermConditionModel } from './data/models/term-condition.model';
|
|||
BatchActiveTermConditionManager,
|
||||
BatchConfirmTermConditionManager,
|
||||
BatchInactiveTermConditionManager,
|
||||
ChangePositionTermConditionManager,
|
||||
|
||||
TermConditionDataService,
|
||||
TermConditionReadService,
|
||||
|
|
Loading…
Reference in New Issue