diff --git a/plopfile.js b/plopfile.js index 3fc6cf8..c458132 100644 --- a/plopfile.js +++ b/plopfile.js @@ -29,7 +29,7 @@ module.exports = function (plop) { name: 'location', message: 'Location: ', choices: function () { - return ['item related', 'user related', 'season related', 'transaction']; + return ['item related', 'user related', 'season related', 'transaction', 'web information']; }, }, ], diff --git a/src/app.module.ts b/src/app.module.ts index 8a49cd4..e3cece8 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -47,7 +47,6 @@ import { TransactionModel } from './modules/transaction/transaction/data/models/ import { TransactionItemModel } from './modules/transaction/transaction/data/models/transaction-item.model'; import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model'; import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module'; - import { ReportModule } from './modules/reports/report/report.module'; import { ReportBookmarkModule } from './modules/reports/report-bookmark/report-bookmark.module'; import { ReportExportModule } from './modules/reports/report-export/report-export.module'; @@ -58,6 +57,12 @@ import { MidtransModule } from './modules/configuration/midtrans/midtrans.module import { RefundModule } from './modules/transaction/refund/refund.module'; import { RefundModel } from './modules/transaction/refund/data/models/refund.model'; import { RefundItemModel } from './modules/transaction/refund/data/models/refund-item.model'; +import { GateModule } from './modules/web-information/gate/gate.module'; +import { GateModel } from './modules/web-information/gate/data/models/gate.model'; +import { TermConditionModule } from './modules/web-information/term-condition/term-condition.module'; +import { TermConditionModel } from './modules/web-information/term-condition/data/models/term-condition.model'; +import { FaqModel } from './modules/web-information/faq/data/models/faq.model'; +import { FaqModule } from './modules/web-information/faq/faq.module'; @Module({ imports: [ @@ -76,6 +81,8 @@ import { RefundItemModel } from './modules/transaction/refund/data/models/refund entities: [ ...UserPrivilegeModels, ErrorLogModel, + FaqModel, + GateModel, ItemModel, ItemCategoryModel, ItemRateModel, @@ -87,6 +94,7 @@ import { RefundItemModel } from './modules/transaction/refund/data/models/refund SeasonPeriodModel, SeasonTypeModel, TaxModel, + TermConditionModel, TransactionModel, TransactionItemModel, TransactionTaxModel, @@ -135,6 +143,11 @@ import { RefundItemModel } from './modules/transaction/refund/data/models/refund SeasonTypeModule, SeasonPeriodModule, + // web information + FaqModule, + GateModule, + TermConditionModule, + // report ReportModule, ReportBookmarkModule, diff --git a/src/core/strings/constants/base.constants.ts b/src/core/strings/constants/base.constants.ts index 127b142..0ce2413 100644 --- a/src/core/strings/constants/base.constants.ts +++ b/src/core/strings/constants/base.constants.ts @@ -48,3 +48,5 @@ export const BLANK_USER = { role: null, user_privilege_id: null, }; + +export const EMPTY_UUID = '00000000-0000-0000-0000-000000000000'; diff --git a/src/core/strings/constants/module.constants.ts b/src/core/strings/constants/module.constants.ts index a53b60e..6549a5a 100644 --- a/src/core/strings/constants/module.constants.ts +++ b/src/core/strings/constants/module.constants.ts @@ -1,4 +1,6 @@ export enum MODULE_NAME { + FAQ = 'faqs', + GATE = 'gates', ITEM = 'items', ITEM_CATEGORY = 'item-categories', ITEM_RATE = 'item-rates', @@ -8,6 +10,7 @@ export enum MODULE_NAME { SEASON_TYPE = 'season-types', SEASON_PERIOD = 'season-periods', TAX = 'taxes', + TERM_CONDITION = 'term_conditions', TENANT = 'tenants', TRANSACTION = 'transactions', USER = 'users', diff --git a/src/core/strings/constants/table.constants.ts b/src/core/strings/constants/table.constants.ts index 3d3230d..862d2d5 100644 --- a/src/core/strings/constants/table.constants.ts +++ b/src/core/strings/constants/table.constants.ts @@ -1,8 +1,10 @@ export enum TABLE_NAME { ERROR_LOG = 'log_errors', + FAQ = 'faqs', ITEM = 'items', ITEM_CATEGORY = 'item_categories', ITEM_RATE = 'item_rates', + GATE = 'gates', LOG = 'logs', PAYMENT_METHOD = 'payment_methods', PRICE_FORMULA = 'price_formulas', @@ -11,6 +13,7 @@ export enum TABLE_NAME { SEASON_TYPE = 'season_types', SEASON_PERIOD = 'season_periods', TAX = 'taxes', + TERM_CONDITION = 'term_conditions', TENANT = 'tenants', TRANSACTION = 'transactions', TRANSACTION_ITEM = 'transaction_items', diff --git a/src/database/migrations/1721024987609-gate.ts b/src/database/migrations/1721024987609-gate.ts new file mode 100644 index 0000000..d2d906e --- /dev/null +++ b/src/database/migrations/1721024987609-gate.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class Gate1721024987609 implements MigrationInterface { + name = 'Gate1721024987609'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "public"."gates_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `CREATE TYPE "public"."gates_type_enum" AS ENUM('gate masuk', 'gate keluar')`, + ); + await queryRunner.query( + `CREATE TABLE "gates" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."gates_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."gates_type_enum" NOT NULL DEFAULT 'gate masuk', "code" character varying, "note" text, "item_id" uuid, CONSTRAINT "PK_2dd58a77462dd2c5695ec4a7975" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "gates" ADD CONSTRAINT "FK_29f020cd153bb079722bcbee830" FOREIGN KEY ("item_id") REFERENCES "items"("id") ON DELETE CASCADE ON UPDATE CASCADE`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "gates" DROP CONSTRAINT "FK_29f020cd153bb079722bcbee830"`, + ); + await queryRunner.query(`DROP TABLE "gates"`); + await queryRunner.query(`DROP TYPE "public"."gates_type_enum"`); + await queryRunner.query(`DROP TYPE "public"."gates_status_enum"`); + } +} diff --git a/src/database/migrations/1721029248635-term-condition.ts b/src/database/migrations/1721029248635-term-condition.ts new file mode 100644 index 0000000..2f4ebf4 --- /dev/null +++ b/src/database/migrations/1721029248635-term-condition.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class TermCondition1721029248635 implements MigrationInterface { + name = 'TermCondition1721029248635'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "public"."term_conditions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `CREATE TABLE "term_conditions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."term_conditions_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_fc92769e487820f24ed68337feb" PRIMARY KEY ("id"))`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "term_conditions"`); + await queryRunner.query(`DROP TYPE "public"."term_conditions_status_enum"`); + } +} diff --git a/src/database/migrations/1721029454627-frequently-ask-question.ts b/src/database/migrations/1721029454627-frequently-ask-question.ts new file mode 100644 index 0000000..9fb3173 --- /dev/null +++ b/src/database/migrations/1721029454627-frequently-ask-question.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class FrequentlyAskQuestion1721029454627 implements MigrationInterface { + name = 'FrequentlyAskQuestion1721029454627'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "public"."faqs_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'partial refund', 'pending', 'proses refund', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `CREATE TABLE "faqs" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "creator_id" character varying(36), "creator_name" character varying(125), "editor_id" character varying(36), "editor_name" character varying(125), "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "status" "public"."faqs_status_enum" NOT NULL DEFAULT 'draft', "title" character varying, "description" text, CONSTRAINT "PK_2ddf4f2c910f8e8fa2663a67bf0" PRIMARY KEY ("id"))`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "faqs"`); + await queryRunner.query(`DROP TYPE "public"."faqs_status_enum"`); + } +} diff --git a/src/database/migrations/1721031712642-update-refund.ts b/src/database/migrations/1721031712642-update-refund.ts new file mode 100644 index 0000000..4bbd3c3 --- /dev/null +++ b/src/database/migrations/1721031712642-update-refund.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateRefund1721031712642 implements MigrationInterface { + name = 'UpdateRefund1721031712642' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "refunds" ADD "refund_sub_total" numeric`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "refunds" DROP COLUMN "refund_sub_total"`); + } + +} diff --git a/src/modules/configuration/constant/infrastructure/constant.controller.ts b/src/modules/configuration/constant/infrastructure/constant.controller.ts index 99c6d99..a388236 100644 --- a/src/modules/configuration/constant/infrastructure/constant.controller.ts +++ b/src/modules/configuration/constant/infrastructure/constant.controller.ts @@ -6,6 +6,7 @@ import { ItemType } from 'src/modules/item-related/item-category/constants'; import { LimitType } from 'src/modules/item-related/item/constants'; import { PaymentMethodType } from 'src/modules/transaction/payment-method/constants'; import { RefundType } from 'src/modules/transaction/refund/constants'; +import { GateType } from 'src/modules/web-information/gate/constants'; @ApiTags('configuration - constant') @Controller('v1/constant') @@ -50,4 +51,9 @@ export class ConstantController { async refundType(): Promise { return Object.values(RefundType); } + + @Get('gate-type') + async gateType(): Promise { + return Object.values(GateType); + } } diff --git a/src/modules/item-related/item-rate/domain/usecases/managers/index-item-rate.manager.ts b/src/modules/item-related/item-rate/domain/usecases/managers/index-item-rate.manager.ts index 4f34708..7cc92b8 100644 --- a/src/modules/item-related/item-rate/domain/usecases/managers/index-item-rate.manager.ts +++ b/src/modules/item-related/item-rate/domain/usecases/managers/index-item-rate.manager.ts @@ -6,6 +6,7 @@ import { RelationParam, } from 'src/core/modules/domain/entities/base-filter.entity'; import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity'; +import { STATUS } from 'src/core/strings/constants/base.constants'; @Injectable() export class IndexItemRateManager extends BaseIndexManager { @@ -27,6 +28,7 @@ export class IndexItemRateManager extends BaseIndexManager { ) { const rate = item['item_rates']?.find( (rate) => + rate.season_period?.status == STATUS.ACTIVE && d >= new Date(rate.season_period.start_date) && d <= new Date(rate.season_period.end_date), ); @@ -84,6 +86,7 @@ export class IndexItemRateManager extends BaseIndexManager { 'item_rates.price', 'season_period.id', + 'season_period.status', 'season_period.holiday_name', 'season_period.start_date', 'season_period.end_date', diff --git a/src/modules/item-related/item/data/models/item.model.ts b/src/modules/item-related/item/data/models/item.model.ts index 0b9bf82..73205e4 100644 --- a/src/modules/item-related/item/data/models/item.model.ts +++ b/src/modules/item-related/item/data/models/item.model.ts @@ -15,6 +15,7 @@ import { LimitType } from '../../constants'; import { ItemCategoryModel } from 'src/modules/item-related/item-category/data/models/item-category.model'; import { UserModel } from 'src/modules/user-related/user/data/models/user.model'; import { ItemRateModel } from 'src/modules/item-related/item-rate/data/models/item-rate.model'; +import { GateModel } from 'src/modules/web-information/gate/data/models/gate.model'; @Entity(TABLE_NAME.ITEM) export class ItemModel @@ -108,4 +109,11 @@ export class ItemModel onUpdate: 'CASCADE', }) item_rates: ItemRateModel[]; + + // relasi ke gate + @OneToMany(() => GateModel, (model) => model.item, { + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + gates: GateModel[]; } diff --git a/src/modules/item-related/item/domain/entities/filter-item.entity.ts b/src/modules/item-related/item/domain/entities/filter-item.entity.ts index 1bde43f..19a0b72 100644 --- a/src/modules/item-related/item/domain/entities/filter-item.entity.ts +++ b/src/modules/item-related/item/domain/entities/filter-item.entity.ts @@ -6,4 +6,5 @@ export interface FilterItemEntity extends BaseFilterEntity { limit_types: string[]; tenant_ids: string[]; all_item: boolean; + season_period_ids: string[]; } diff --git a/src/modules/item-related/item/domain/usecases/managers/index-item-rates.manager.ts b/src/modules/item-related/item/domain/usecases/managers/index-item-rates.manager.ts index 3017db9..d51a110 100644 --- a/src/modules/item-related/item/domain/usecases/managers/index-item-rates.manager.ts +++ b/src/modules/item-related/item/domain/usecases/managers/index-item-rates.manager.ts @@ -10,7 +10,7 @@ import { ItemRateEntity } from 'src/modules/item-related/item-rate/domain/entiti @Injectable() export class IndexItemRatesManager extends BaseIndexManager { async prepareData(): Promise { - this.filterParam.order_by = `${this.tableName}.id`; + this.filterParam.order_by = `season_period.id`; return; } @@ -38,9 +38,11 @@ export class IndexItemRatesManager extends BaseIndexManager { get selects(): string[] { return [ `${this.tableName}.id`, + `${this.tableName}.item_id`, `${this.tableName}.price`, `season_period.id`, + `season_period.priority`, `season_period.created_at`, `season_period.creator_name`, `season_period.editor_name`, @@ -68,20 +70,25 @@ export class IndexItemRatesManager extends BaseIndexManager { itemIds: this.filterParam.item_ids, }); } - if (this.filterParam.start_date) { - queryBuilder.andWhere(`season_period.start_date BETWEEN :from AND :to`, { - from: this.filterParam.start_date, - to: this.filterParam.end_date, + + if (this.filterParam.season_period_ids) { + queryBuilder.andWhere(`season_period.id In (:...itemIds)`, { + itemIds: this.filterParam.season_period_ids, }); } - if (this.filterParam.end_date) { - queryBuilder.andWhere(`season_period.end_date BETWEEN :from AND :to`, { - from: this.filterParam.start_date, - to: this.filterParam.end_date, + if (this.filterParam.start_date) { + queryBuilder.andWhere(`season_period.start_date < :inputStartDate`, { + inputStartDate: this.filterParam.end_date, + }); + + queryBuilder.andWhere(`season_period.end_date > :inputEndDate`, { + inputEndDate: this.filterParam.start_date, }); } + queryBuilder.addOrderBy('season_period.priority', 'ASC'); + return queryBuilder; } } diff --git a/src/modules/item-related/item/infrastructure/dto/filter-item.dto.ts b/src/modules/item-related/item/infrastructure/dto/filter-item.dto.ts index 5a0d70f..07b9845 100644 --- a/src/modules/item-related/item/infrastructure/dto/filter-item.dto.ts +++ b/src/modules/item-related/item/infrastructure/dto/filter-item.dto.ts @@ -10,6 +10,12 @@ export class FilterItemDto extends BaseFilterDto implements FilterItemEntity { }) item_categories: string[]; + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + season_period_ids: string[]; + @ApiProperty({ type: ['string'], required: false }) @Transform((body) => { return Array.isArray(body.value) ? body.value : [body.value]; diff --git a/src/modules/season-related/season-period/domain/usecases/managers/create-season-period.manager.ts b/src/modules/season-related/season-period/domain/usecases/managers/create-season-period.manager.ts index 2a53f98..4f10cb0 100644 --- a/src/modules/season-related/season-period/domain/usecases/managers/create-season-period.manager.ts +++ b/src/modules/season-related/season-period/domain/usecases/managers/create-season-period.manager.ts @@ -45,6 +45,7 @@ export class CreateSeasonPeriodManager extends BaseCreateManager { async beforeProcess(): Promise { - // if (this.data.transaction?.status != STATUS.SETTLED) { - // throw new UnprocessableEntityException({ - // statusCode: HttpStatus.UNPROCESSABLE_ENTITY, - // message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, - // error: 'Unprocessable Entity', - // }); - // } + if (this.data.transaction?.status != STATUS.SETTLED) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! only transaction with status ${STATUS.SETTLED} can be refund`, + error: 'Unprocessable Entity', + }); + } return; } diff --git a/src/modules/transaction/refund/infrastructure/dto/refund.dto.ts b/src/modules/transaction/refund/infrastructure/dto/refund.dto.ts index 38164b0..86a3b70 100644 --- a/src/modules/transaction/refund/infrastructure/dto/refund.dto.ts +++ b/src/modules/transaction/refund/infrastructure/dto/refund.dto.ts @@ -15,6 +15,13 @@ export class RefundDto extends BaseStatusDto implements RefundEntity { @IsString() type: RefundType; + @ApiProperty({ + type: Number, + required: false, + example: 1750000, + }) + refund_sub_total: number; + @ApiProperty({ type: Number, example: 1750000, diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts index c8e8ada..301e158 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts @@ -13,6 +13,7 @@ import { UnprocessableEntityException, } from '@nestjs/common'; import { STATUS } from 'src/core/strings/constants/base.constants'; +import { TransactionPaymentType } from '../../../constants'; @Injectable() export class BatchConfirmDataTransactionManager extends BaseBatchUpdateStatusManager { @@ -29,7 +30,10 @@ export class BatchConfirmDataTransactionManager extends BaseBatchUpdateStatusMan Object.assign(data, { status: STATUS.WAITING, - reconciliation_status: STATUS.PENDING, + reconciliation_status: + data.payment_type == TransactionPaymentType.COUNTER + ? null + : STATUS.PENDING, }); return; diff --git a/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts index 46a720f..07361d8 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts @@ -12,6 +12,7 @@ import { import { TransactionModel } from '../../../data/models/transaction.model'; import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; import { STATUS } from 'src/core/strings/constants/base.constants'; +import { TransactionPaymentType } from '../../../constants'; @Injectable() export class ConfirmDataTransactionManager extends BaseUpdateStatusManager { @@ -38,7 +39,10 @@ export class ConfirmDataTransactionManager extends BaseUpdateStatusManager implements FaqEntity { + @Column('varchar', { name: 'title', nullable: true }) + title: string; + + @Column('text', { name: 'description', nullable: true }) + description: string; +} diff --git a/src/modules/web-information/faq/data/services/faq-data.service.ts b/src/modules/web-information/faq/data/services/faq-data.service.ts new file mode 100644 index 0000000..ea40735 --- /dev/null +++ b/src/modules/web-information/faq/data/services/faq-data.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; +import { FaqEntity } from '../../domain/entities/faq.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { FaqModel } from '../models/faq.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; + +@Injectable() +export class FaqDataService extends BaseDataService { + constructor( + @InjectRepository(FaqModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/faq/data/services/faq-read.service.ts b/src/modules/web-information/faq/data/services/faq-read.service.ts new file mode 100644 index 0000000..cfd09be --- /dev/null +++ b/src/modules/web-information/faq/data/services/faq-read.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { FaqEntity } from '../../domain/entities/faq.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { FaqModel } from '../models/faq.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; +import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; + +@Injectable() +export class FaqReadService extends BaseReadService { + constructor( + @InjectRepository(FaqModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/faq/domain/entities/event/faq-change-status.event.ts b/src/modules/web-information/faq/domain/entities/event/faq-change-status.event.ts new file mode 100644 index 0000000..5694e39 --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/event/faq-change-status.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class FaqChangeStatusEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/faq/domain/entities/event/faq-created.event.ts b/src/modules/web-information/faq/domain/entities/event/faq-created.event.ts new file mode 100644 index 0000000..7e8178c --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/event/faq-created.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class FaqCreatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/faq/domain/entities/event/faq-deleted.event.ts b/src/modules/web-information/faq/domain/entities/event/faq-deleted.event.ts new file mode 100644 index 0000000..07985e1 --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/event/faq-deleted.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class FaqDeletedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/faq/domain/entities/event/faq-updated.event.ts b/src/modules/web-information/faq/domain/entities/event/faq-updated.event.ts new file mode 100644 index 0000000..c48de05 --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/event/faq-updated.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class FaqUpdatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/faq/domain/entities/faq.entity.ts b/src/modules/web-information/faq/domain/entities/faq.entity.ts new file mode 100644 index 0000000..a25e3c6 --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/faq.entity.ts @@ -0,0 +1,6 @@ +import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity'; + +export interface FaqEntity extends BaseStatusEntity { + title: string; + description: string; +} diff --git a/src/modules/web-information/faq/domain/entities/filter-faq.entity.ts b/src/modules/web-information/faq/domain/entities/filter-faq.entity.ts new file mode 100644 index 0000000..9488909 --- /dev/null +++ b/src/modules/web-information/faq/domain/entities/filter-faq.entity.ts @@ -0,0 +1,3 @@ +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; + +export interface FilterFaqEntity extends BaseFilterEntity {} diff --git a/src/modules/web-information/faq/domain/usecases/faq-data.orchestrator.ts b/src/modules/web-information/faq/domain/usecases/faq-data.orchestrator.ts new file mode 100644 index 0000000..c82096c --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/faq-data.orchestrator.ts @@ -0,0 +1,106 @@ +import { Injectable } from '@nestjs/common'; +import { CreateFaqManager } from './managers/create-faq.manager'; +import { FaqDataService } from '../../data/services/faq-data.service'; +import { FaqEntity } from '../entities/faq.entity'; +import { DeleteFaqManager } from './managers/delete-faq.manager'; +import { UpdateFaqManager } from './managers/update-faq.manager'; +import { BaseDataTransactionOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-data-transaction.orchestrator'; +import { ActiveFaqManager } from './managers/active-faq.manager'; +import { InactiveFaqManager } from './managers/inactive-faq.manager'; +import { ConfirmFaqManager } from './managers/confirm-faq.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchConfirmFaqManager } from './managers/batch-confirm-faq.manager'; +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'; + +@Injectable() +export class FaqDataOrchestrator extends BaseDataTransactionOrchestrator { + constructor( + private createManager: CreateFaqManager, + private updateManager: UpdateFaqManager, + private deleteManager: DeleteFaqManager, + private activeManager: ActiveFaqManager, + private confirmManager: ConfirmFaqManager, + private inactiveManager: InactiveFaqManager, + private batchDeleteManager: BatchDeleteFaqManager, + private batchActiveManager: BatchActiveFaqManager, + private batchConfirmManager: BatchConfirmFaqManager, + private batchInactiveManager: BatchInactiveFaqManager, + private serviceData: FaqDataService, + ) { + super(); + } + + async create(data): Promise { + this.createManager.setData(data); + this.createManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.createManager.execute(); + return this.createManager.getResult(); + } + + async update(dataId, data): Promise { + this.updateManager.setData(dataId, data); + this.updateManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.updateManager.execute(); + return this.updateManager.getResult(); + } + + async delete(dataId): Promise { + this.deleteManager.setData(dataId); + this.deleteManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.deleteManager.execute(); + return this.deleteManager.getResult(); + } + + async batchDelete(dataIds: string[]): Promise { + this.batchDeleteManager.setData(dataIds); + this.batchDeleteManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.batchDeleteManager.execute(); + return this.batchDeleteManager.getResult(); + } + + async active(dataId): Promise { + this.activeManager.setData(dataId, STATUS.ACTIVE); + this.activeManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.activeManager.execute(); + return this.activeManager.getResult(); + } + + async batchActive(dataIds: string[]): Promise { + this.batchActiveManager.setData(dataIds, STATUS.ACTIVE); + this.batchActiveManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.batchActiveManager.execute(); + return this.batchActiveManager.getResult(); + } + + async confirm(dataId): Promise { + this.confirmManager.setData(dataId, STATUS.ACTIVE); + this.confirmManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.confirmManager.execute(); + return this.confirmManager.getResult(); + } + + async batchConfirm(dataIds: string[]): Promise { + this.batchConfirmManager.setData(dataIds, STATUS.ACTIVE); + this.batchConfirmManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.batchConfirmManager.execute(); + return this.batchConfirmManager.getResult(); + } + + async inactive(dataId): Promise { + this.inactiveManager.setData(dataId, STATUS.INACTIVE); + this.inactiveManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.inactiveManager.execute(); + return this.inactiveManager.getResult(); + } + + async batchInactive(dataIds: string[]): Promise { + this.batchInactiveManager.setData(dataIds, STATUS.INACTIVE); + this.batchInactiveManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.batchInactiveManager.execute(); + return this.batchInactiveManager.getResult(); + } +} diff --git a/src/modules/web-information/faq/domain/usecases/faq-read.orchestrator.ts b/src/modules/web-information/faq/domain/usecases/faq-read.orchestrator.ts new file mode 100644 index 0000000..02e11cb --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/faq-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexFaqManager } from './managers/index-faq.manager'; +import { FaqReadService } from '../../data/services/faq-read.service'; +import { FaqEntity } from '../entities/faq.entity'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailFaqManager } from './managers/detail-faq.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class FaqReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexFaqManager, + private detailManager: DetailFaqManager, + private serviceData: FaqReadService, + ) { + super(); + } + + async index(params): Promise> { + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.indexManager.execute(); + return this.indexManager.getResult(); + } + + async detail(dataId: string): Promise { + this.detailManager.setData(dataId); + this.detailManager.setService(this.serviceData, TABLE_NAME.FAQ); + await this.detailManager.execute(); + return this.detailManager.getResult(); + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/active-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/active-faq.manager.ts new file mode 100644 index 0000000..c33c3bb --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/active-faq.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; + +@Injectable() +export class ActiveFaqManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/batch-active-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/batch-active-faq.manager.ts new file mode 100644 index 0000000..f385801 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/batch-active-faq.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchActiveFaqManager extends BaseBatchUpdateStatusManager { + validateData(data: FaqEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/batch-confirm-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/batch-confirm-faq.manager.ts new file mode 100644 index 0000000..4c0bc93 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/batch-confirm-faq.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchConfirmFaqManager extends BaseBatchUpdateStatusManager { + validateData(data: FaqEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/batch-delete-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/batch-delete-faq.manager.ts new file mode 100644 index 0000000..5476e9a --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/batch-delete-faq.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqDeletedEvent } from '../../entities/event/faq-deleted.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchDeleteFaqManager extends BaseBatchDeleteManager { + async beforeProcess(): Promise { + return; + } + + async validateData(data: FaqEntity): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqDeletedEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/batch-inactive-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/batch-inactive-faq.manager.ts new file mode 100644 index 0000000..c587411 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/batch-inactive-faq.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchInactiveFaqManager extends BaseBatchUpdateStatusManager { + validateData(data: FaqEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/confirm-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/confirm-faq.manager.ts new file mode 100644 index 0000000..86b6c51 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/confirm-faq.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; + +@Injectable() +export class ConfirmFaqManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/create-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/create-faq.manager.ts new file mode 100644 index 0000000..dc79622 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/create-faq.manager.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqEntity } from '../../entities/faq.entity'; +import { FaqModel } from '../../../data/models/faq.model'; +import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; +import { FaqCreatedEvent } from '../../entities/event/faq-created.event'; + +@Injectable() +export class CreateFaqManager extends BaseCreateManager { + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqCreatedEvent, + data: this.data, + }, + ]; + } + + get entityTarget(): any { + return FaqModel; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/delete-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/delete-faq.manager.ts new file mode 100644 index 0000000..da3ac12 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/delete-faq.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqDeletedEvent } from '../../entities/event/faq-deleted.event'; + +@Injectable() +export class DeleteFaqManager extends BaseDeleteManager { + getResult(): string { + return `Success`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqDeletedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/detail-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/detail-faq.manager.ts new file mode 100644 index 0000000..a44ee48 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/detail-faq.manager.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class DetailFaqManager extends BaseDetailManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.title`, + `${this.tableName}.description`, + ]; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/inactive-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/inactive-faq.manager.ts new file mode 100644 index 0000000..2e02d12 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/inactive-faq.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqChangeStatusEvent } from '../../entities/event/faq-change-status.event'; + +@Injectable() +export class InactiveFaqManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success inactive data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/index-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/index-faq.manager.ts new file mode 100644 index 0000000..a1508eb --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/index-faq.manager.ts @@ -0,0 +1,64 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class IndexFaqManager extends BaseIndexManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.title`, + `${this.tableName}.description`, + ]; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.name`, + data: this.filterParam.names, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + return queryBuilder; + } +} diff --git a/src/modules/web-information/faq/domain/usecases/managers/update-faq.manager.ts b/src/modules/web-information/faq/domain/usecases/managers/update-faq.manager.ts new file mode 100644 index 0000000..17aef38 --- /dev/null +++ b/src/modules/web-information/faq/domain/usecases/managers/update-faq.manager.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; +import { FaqEntity } from '../../entities/faq.entity'; +import { FaqModel } from '../../../data/models/faq.model'; +import { FaqUpdatedEvent } from '../../entities/event/faq-updated.event'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; + +@Injectable() +export class UpdateFaqManager extends BaseUpdateManager { + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get entityTarget(): any { + return FaqModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: FaqUpdatedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/faq/faq.module.ts b/src/modules/web-information/faq/faq.module.ts new file mode 100644 index 0000000..0554fbe --- /dev/null +++ b/src/modules/web-information/faq/faq.module.ts @@ -0,0 +1,54 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { FaqDataService } from './data/services/faq-data.service'; +import { FaqReadService } from './data/services/faq-read.service'; +import { FaqReadController } from './infrastructure/faq-read.controller'; +import { FaqReadOrchestrator } from './domain/usecases/faq-read.orchestrator'; +import { FaqDataController } from './infrastructure/faq-data.controller'; +import { FaqDataOrchestrator } from './domain/usecases/faq-data.orchestrator'; +import { CreateFaqManager } from './domain/usecases/managers/create-faq.manager'; +import { CqrsModule } from '@nestjs/cqrs'; +import { IndexFaqManager } from './domain/usecases/managers/index-faq.manager'; +import { DeleteFaqManager } from './domain/usecases/managers/delete-faq.manager'; +import { UpdateFaqManager } from './domain/usecases/managers/update-faq.manager'; +import { ActiveFaqManager } from './domain/usecases/managers/active-faq.manager'; +import { ConfirmFaqManager } from './domain/usecases/managers/confirm-faq.manager'; +import { InactiveFaqManager } from './domain/usecases/managers/inactive-faq.manager'; +import { DetailFaqManager } from './domain/usecases/managers/detail-faq.manager'; +import { BatchDeleteFaqManager } from './domain/usecases/managers/batch-delete-faq.manager'; +import { BatchActiveFaqManager } from './domain/usecases/managers/batch-active-faq.manager'; +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'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature([FaqModel], CONNECTION_NAME.DEFAULT), + CqrsModule, + ], + controllers: [FaqDataController, FaqReadController], + providers: [ + IndexFaqManager, + DetailFaqManager, + CreateFaqManager, + DeleteFaqManager, + UpdateFaqManager, + ActiveFaqManager, + ConfirmFaqManager, + InactiveFaqManager, + BatchDeleteFaqManager, + BatchActiveFaqManager, + BatchConfirmFaqManager, + BatchInactiveFaqManager, + + FaqDataService, + FaqReadService, + + FaqDataOrchestrator, + FaqReadOrchestrator, + ], +}) +export class FaqModule {} diff --git a/src/modules/web-information/faq/index.ts b/src/modules/web-information/faq/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/web-information/faq/infrastructure/dto/faq.dto.ts b/src/modules/web-information/faq/infrastructure/dto/faq.dto.ts new file mode 100644 index 0000000..11e8346 --- /dev/null +++ b/src/modules/web-information/faq/infrastructure/dto/faq.dto.ts @@ -0,0 +1,21 @@ +import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.dto'; +import { FaqEntity } from '../../domain/entities/faq.entity'; +import { IsString } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class FaqDto extends BaseStatusDto implements FaqEntity { + @ApiProperty({ + type: String, + required: true, + example: 'Booking', + }) + @IsString() + title: string; + + @ApiProperty({ + type: String, + required: false, + example: 'Booking descs', + }) + description: string; +} diff --git a/src/modules/web-information/faq/infrastructure/dto/filter-faq.dto.ts b/src/modules/web-information/faq/infrastructure/dto/filter-faq.dto.ts new file mode 100644 index 0000000..ce6a148 --- /dev/null +++ b/src/modules/web-information/faq/infrastructure/dto/filter-faq.dto.ts @@ -0,0 +1,4 @@ +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterFaqEntity } from '../../domain/entities/filter-faq.entity'; + +export class FilterFaqDto extends BaseFilterDto implements FilterFaqEntity {} diff --git a/src/modules/web-information/faq/infrastructure/faq-data.controller.ts b/src/modules/web-information/faq/infrastructure/faq-data.controller.ts new file mode 100644 index 0000000..0a55d27 --- /dev/null +++ b/src/modules/web-information/faq/infrastructure/faq-data.controller.ts @@ -0,0 +1,78 @@ +import { + Body, + Controller, + Delete, + Param, + Patch, + Post, + Put, +} from '@nestjs/common'; +import { FaqDataOrchestrator } from '../domain/usecases/faq-data.orchestrator'; +import { FaqDto } from './dto/faq.dto'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +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'; + +@ApiTags(`${MODULE_NAME.FAQ.split('-').join(' ')} - data`) +@Controller(`v1/${MODULE_NAME.FAQ}`) +@Public(false) +@ApiBearerAuth('JWT') +export class FaqDataController { + constructor(private orchestrator: FaqDataOrchestrator) {} + + @Post() + async create(@Body() data: FaqDto): Promise { + return await this.orchestrator.create(data); + } + + @Put('/batch-delete') + async batchDeleted(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchDelete(body.ids); + } + + @Patch(':id/active') + async active(@Param('id') dataId: string): Promise { + return await this.orchestrator.active(dataId); + } + + @Put('/batch-active') + async batchActive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchActive(body.ids); + } + + @Patch(':id/confirm') + async confirm(@Param('id') dataId: string): Promise { + return await this.orchestrator.confirm(dataId); + } + + @Put('/batch-confirm') + async batchConfirm(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchConfirm(body.ids); + } + + @Patch(':id/inactive') + async inactive(@Param('id') dataId: string): Promise { + return await this.orchestrator.inactive(dataId); + } + + @Put('/batch-inactive') + async batchInactive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchInactive(body.ids); + } + + @Put(':id') + async update( + @Param('id') dataId: string, + @Body() data: FaqDto, + ): Promise { + return await this.orchestrator.update(dataId, data); + } + + @Delete(':id') + async delete(@Param('id') dataId: string): Promise { + return await this.orchestrator.delete(dataId); + } +} diff --git a/src/modules/web-information/faq/infrastructure/faq-read.controller.ts b/src/modules/web-information/faq/infrastructure/faq-read.controller.ts new file mode 100644 index 0000000..e282038 --- /dev/null +++ b/src/modules/web-information/faq/infrastructure/faq-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterFaqDto } from './dto/filter-faq.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { FaqEntity } from '../domain/entities/faq.entity'; +import { FaqReadOrchestrator } from '../domain/usecases/faq-read.orchestrator'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { Public } from 'src/core/guards'; + +@ApiTags(`${MODULE_NAME.FAQ.split('-').join(' ')} - read`) +@Controller(`v1/${MODULE_NAME.FAQ}`) +@Public(false) +@ApiBearerAuth('JWT') +export class FaqReadController { + constructor(private orchestrator: FaqReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterFaqDto, + ): Promise> { + return await this.orchestrator.index(params); + } + + @Get(':id') + async detail(@Param('id') id: string): Promise { + return await this.orchestrator.detail(id); + } +} diff --git a/src/modules/web-information/gate/constants.ts b/src/modules/web-information/gate/constants.ts new file mode 100644 index 0000000..ee23e1b --- /dev/null +++ b/src/modules/web-information/gate/constants.ts @@ -0,0 +1,4 @@ +export enum GateType { + GATE_IN = 'gate masuk', + GATE_OUT = 'gate keluar', +} diff --git a/src/modules/web-information/gate/data/models/gate.model.ts b/src/modules/web-information/gate/data/models/gate.model.ts new file mode 100644 index 0000000..0940d28 --- /dev/null +++ b/src/modules/web-information/gate/data/models/gate.model.ts @@ -0,0 +1,34 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { GateEntity } from '../../domain/entities/gate.entity'; +import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { BaseStatusModel } from 'src/core/modules/data/model/base-status.model'; +import { GateType } from '../../constants'; +import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; + +@Entity(TABLE_NAME.GATE) +export class GateModel + extends BaseStatusModel + implements GateEntity +{ + @Column('enum', { + name: 'type', + enum: GateType, + default: GateType.GATE_IN, + }) + type: GateType; + + @Column('varchar', { name: 'code', nullable: true }) + code: string; + + @Column('text', { name: 'note', nullable: true }) + note: string; + + @Column('varchar', { name: 'item_id', nullable: true }) + item_id: string; + @ManyToOne(() => ItemModel, (model) => model.gates, { + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + @JoinColumn({ name: 'item_id' }) + item: ItemModel; +} diff --git a/src/modules/web-information/gate/data/services/gate-data.service.ts b/src/modules/web-information/gate/data/services/gate-data.service.ts new file mode 100644 index 0000000..0e9c015 --- /dev/null +++ b/src/modules/web-information/gate/data/services/gate-data.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; +import { GateEntity } from '../../domain/entities/gate.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { GateModel } from '../models/gate.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; + +@Injectable() +export class GateDataService extends BaseDataService { + constructor( + @InjectRepository(GateModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/gate/data/services/gate-read.service.ts b/src/modules/web-information/gate/data/services/gate-read.service.ts new file mode 100644 index 0000000..0dc74f2 --- /dev/null +++ b/src/modules/web-information/gate/data/services/gate-read.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { GateEntity } from '../../domain/entities/gate.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { GateModel } from '../models/gate.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; +import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; + +@Injectable() +export class GateReadService extends BaseReadService { + constructor( + @InjectRepository(GateModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/gate/domain/entities/event/gate-change-status.event.ts b/src/modules/web-information/gate/domain/entities/event/gate-change-status.event.ts new file mode 100644 index 0000000..cba58f9 --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/event/gate-change-status.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class GateChangeStatusEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/gate/domain/entities/event/gate-created.event.ts b/src/modules/web-information/gate/domain/entities/event/gate-created.event.ts new file mode 100644 index 0000000..808ce86 --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/event/gate-created.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class GateCreatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/gate/domain/entities/event/gate-deleted.event.ts b/src/modules/web-information/gate/domain/entities/event/gate-deleted.event.ts new file mode 100644 index 0000000..a81314c --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/event/gate-deleted.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class GateDeletedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/gate/domain/entities/event/gate-updated.event.ts b/src/modules/web-information/gate/domain/entities/event/gate-updated.event.ts new file mode 100644 index 0000000..2ccb9fd --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/event/gate-updated.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class GateUpdatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/gate/domain/entities/filter-gate.entity.ts b/src/modules/web-information/gate/domain/entities/filter-gate.entity.ts new file mode 100644 index 0000000..36e1f08 --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/filter-gate.entity.ts @@ -0,0 +1,8 @@ +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; + +export interface FilterGateEntity extends BaseFilterEntity { + codes: string[]; + types: string[]; + item_names: string[]; + notes: string[]; +} diff --git a/src/modules/web-information/gate/domain/entities/gate.entity.ts b/src/modules/web-information/gate/domain/entities/gate.entity.ts new file mode 100644 index 0000000..5ef2f0a --- /dev/null +++ b/src/modules/web-information/gate/domain/entities/gate.entity.ts @@ -0,0 +1,10 @@ +import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity'; +import { GateType } from '../../constants'; + +export interface GateEntity extends BaseStatusEntity { + type: GateType; + code: string; + note: string; + + item_id: string; +} diff --git a/src/modules/web-information/gate/domain/usecases/gate-data.orchestrator.ts b/src/modules/web-information/gate/domain/usecases/gate-data.orchestrator.ts new file mode 100644 index 0000000..1c6dd3e --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/gate-data.orchestrator.ts @@ -0,0 +1,106 @@ +import { Injectable } from '@nestjs/common'; +import { CreateGateManager } from './managers/create-gate.manager'; +import { GateDataService } from '../../data/services/gate-data.service'; +import { GateEntity } from '../entities/gate.entity'; +import { DeleteGateManager } from './managers/delete-gate.manager'; +import { UpdateGateManager } from './managers/update-gate.manager'; +import { BaseDataTransactionOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-data-transaction.orchestrator'; +import { ActiveGateManager } from './managers/active-gate.manager'; +import { InactiveGateManager } from './managers/inactive-gate.manager'; +import { ConfirmGateManager } from './managers/confirm-gate.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchConfirmGateManager } from './managers/batch-confirm-gate.manager'; +import { BatchInactiveGateManager } from './managers/batch-inactive-gate.manager'; +import { BatchActiveGateManager } from './managers/batch-active-gate.manager'; +import { BatchDeleteGateManager } from './managers/batch-delete-gate.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class GateDataOrchestrator extends BaseDataTransactionOrchestrator { + constructor( + private createManager: CreateGateManager, + private updateManager: UpdateGateManager, + private deleteManager: DeleteGateManager, + private activeManager: ActiveGateManager, + private confirmManager: ConfirmGateManager, + private inactiveManager: InactiveGateManager, + private batchDeleteManager: BatchDeleteGateManager, + private batchActiveManager: BatchActiveGateManager, + private batchConfirmManager: BatchConfirmGateManager, + private batchInactiveManager: BatchInactiveGateManager, + private serviceData: GateDataService, + ) { + super(); + } + + async create(data): Promise { + this.createManager.setData(data); + this.createManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.createManager.execute(); + return this.createManager.getResult(); + } + + async update(dataId, data): Promise { + this.updateManager.setData(dataId, data); + this.updateManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.updateManager.execute(); + return this.updateManager.getResult(); + } + + async delete(dataId): Promise { + this.deleteManager.setData(dataId); + this.deleteManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.deleteManager.execute(); + return this.deleteManager.getResult(); + } + + async batchDelete(dataIds: string[]): Promise { + this.batchDeleteManager.setData(dataIds); + this.batchDeleteManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.batchDeleteManager.execute(); + return this.batchDeleteManager.getResult(); + } + + async active(dataId): Promise { + this.activeManager.setData(dataId, STATUS.ACTIVE); + this.activeManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.activeManager.execute(); + return this.activeManager.getResult(); + } + + async batchActive(dataIds: string[]): Promise { + this.batchActiveManager.setData(dataIds, STATUS.ACTIVE); + this.batchActiveManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.batchActiveManager.execute(); + return this.batchActiveManager.getResult(); + } + + async confirm(dataId): Promise { + this.confirmManager.setData(dataId, STATUS.ACTIVE); + this.confirmManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.confirmManager.execute(); + return this.confirmManager.getResult(); + } + + async batchConfirm(dataIds: string[]): Promise { + this.batchConfirmManager.setData(dataIds, STATUS.ACTIVE); + this.batchConfirmManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.batchConfirmManager.execute(); + return this.batchConfirmManager.getResult(); + } + + async inactive(dataId): Promise { + this.inactiveManager.setData(dataId, STATUS.INACTIVE); + this.inactiveManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.inactiveManager.execute(); + return this.inactiveManager.getResult(); + } + + async batchInactive(dataIds: string[]): Promise { + this.batchInactiveManager.setData(dataIds, STATUS.INACTIVE); + this.batchInactiveManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.batchInactiveManager.execute(); + return this.batchInactiveManager.getResult(); + } +} diff --git a/src/modules/web-information/gate/domain/usecases/gate-read.orchestrator.ts b/src/modules/web-information/gate/domain/usecases/gate-read.orchestrator.ts new file mode 100644 index 0000000..d7ed7f6 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/gate-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexGateManager } from './managers/index-gate.manager'; +import { GateReadService } from '../../data/services/gate-read.service'; +import { GateEntity } from '../entities/gate.entity'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailGateManager } from './managers/detail-gate.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class GateReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexGateManager, + private detailManager: DetailGateManager, + private serviceData: GateReadService, + ) { + super(); + } + + async index(params): Promise> { + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.indexManager.execute(); + return this.indexManager.getResult(); + } + + async detail(dataId: string): Promise { + this.detailManager.setData(dataId); + this.detailManager.setService(this.serviceData, TABLE_NAME.GATE); + await this.detailManager.execute(); + return this.detailManager.getResult(); + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/active-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/active-gate.manager.ts new file mode 100644 index 0000000..05a0cdc --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/active-gate.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; + +@Injectable() +export class ActiveGateManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data gate ${this.result.code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/batch-active-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/batch-active-gate.manager.ts new file mode 100644 index 0000000..1517173 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/batch-active-gate.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchActiveGateManager extends BaseBatchUpdateStatusManager { + validateData(data: GateEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/batch-confirm-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/batch-confirm-gate.manager.ts new file mode 100644 index 0000000..660e729 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/batch-confirm-gate.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchConfirmGateManager extends BaseBatchUpdateStatusManager { + validateData(data: GateEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/batch-delete-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/batch-delete-gate.manager.ts new file mode 100644 index 0000000..975f1fd --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/batch-delete-gate.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateDeletedEvent } from '../../entities/event/gate-deleted.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchDeleteGateManager extends BaseBatchDeleteManager { + async beforeProcess(): Promise { + return; + } + + async validateData(data: GateEntity): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateDeletedEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/batch-inactive-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/batch-inactive-gate.manager.ts new file mode 100644 index 0000000..6c3c055 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/batch-inactive-gate.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchInactiveGateManager extends BaseBatchUpdateStatusManager { + validateData(data: GateEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/confirm-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/confirm-gate.manager.ts new file mode 100644 index 0000000..5a409c5 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/confirm-gate.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; + +@Injectable() +export class ConfirmGateManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data gate ${this.result.code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/create-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/create-gate.manager.ts new file mode 100644 index 0000000..d8ec3f4 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/create-gate.manager.ts @@ -0,0 +1,48 @@ +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateEntity } from '../../entities/gate.entity'; +import { GateModel } from '../../../data/models/gate.model'; +import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; +import { GateCreatedEvent } from '../../entities/event/gate-created.event'; +import { validateItemGate } from './helpers/validate-item-gate.helper'; + +@Injectable() +export class CreateGateManager extends BaseCreateManager { + async beforeProcess(): Promise { + await validateItemGate(this.dataService, this.data); + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateCreatedEvent, + data: this.data, + }, + ]; + } + + get entityTarget(): any { + return GateModel; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/delete-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/delete-gate.manager.ts new file mode 100644 index 0000000..f60323d --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/delete-gate.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateDeletedEvent } from '../../entities/event/gate-deleted.event'; + +@Injectable() +export class DeleteGateManager extends BaseDeleteManager { + getResult(): string { + return `Success`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateDeletedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/detail-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/detail-gate.manager.ts new file mode 100644 index 0000000..39fdf54 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/detail-gate.manager.ts @@ -0,0 +1,59 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class DetailGateManager extends BaseDetailManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: ['item'], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.creator_name`, + `${this.tableName}.created_at`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.type`, + `${this.tableName}.code`, + `${this.tableName}.note`, + + 'item.id', + 'item.name', + 'item.status', + 'item.item_type', + 'item.base_price', + 'item.hpp', + ]; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/helpers/validate-item-gate.helper.ts b/src/modules/web-information/gate/domain/usecases/managers/helpers/validate-item-gate.helper.ts new file mode 100644 index 0000000..725d624 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/helpers/validate-item-gate.helper.ts @@ -0,0 +1,38 @@ +import { HttpStatus, UnprocessableEntityException } from '@nestjs/common'; +import { EMPTY_UUID } from 'src/core/strings/constants/base.constants'; +import { In, Not } from 'typeorm'; + +export async function validateItemGate(dataService, data, id?) { + // validate same code + const existCode = await dataService.getOneByOptions({ + where: { + code: data.code, + id: Not(In([id ?? EMPTY_UUID])), + }, + }); + + if (existCode) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! Gate with code ${data.code} already exist`, + error: 'Unprocessable Entity', + }); + } + + // validate type item + const existType = await dataService.getOneByOptions({ + where: { + item_id: data.item.id, + type: data.type, + id: Not(In([id ?? EMPTY_UUID])), + }, + }); + + if (existType) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! Gate type ${data.type} with item ${data.item.name} already exist`, + error: 'Unprocessable Entity', + }); + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/inactive-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/inactive-gate.manager.ts new file mode 100644 index 0000000..94c08ab --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/inactive-gate.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateChangeStatusEvent } from '../../entities/event/gate-change-status.event'; + +@Injectable() +export class InactiveGateManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success inactive data gate ${this.result.code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/index-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/index-gate.manager.ts new file mode 100644 index 0000000..0298552 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/index-gate.manager.ts @@ -0,0 +1,84 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class IndexGateManager extends BaseIndexManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: ['item'], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.creator_name`, + `${this.tableName}.created_at`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.type`, + `${this.tableName}.code`, + `${this.tableName}.note`, + + 'item.id', + 'item.name', + 'item.status', + 'item.item_type', + 'item.base_price', + 'item.hpp', + ]; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.code`, + data: this.filterParam.codes, + }, + { + cols: `${this.tableName}.type`, + data: this.filterParam.types, + }, + { + cols: `${this.tableName}.note`, + data: this.filterParam.notes, + }, + { + cols: `item.name`, + data: this.filterParam.item_names, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + return queryBuilder; + } +} diff --git a/src/modules/web-information/gate/domain/usecases/managers/update-gate.manager.ts b/src/modules/web-information/gate/domain/usecases/managers/update-gate.manager.ts new file mode 100644 index 0000000..1018675 --- /dev/null +++ b/src/modules/web-information/gate/domain/usecases/managers/update-gate.manager.ts @@ -0,0 +1,48 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; +import { GateEntity } from '../../entities/gate.entity'; +import { GateModel } from '../../../data/models/gate.model'; +import { GateUpdatedEvent } from '../../entities/event/gate-updated.event'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { validateItemGate } from './helpers/validate-item-gate.helper'; + +@Injectable() +export class UpdateGateManager extends BaseUpdateManager { + async validateProcess(): Promise { + await validateItemGate(this.dataService, this.data, this.dataId); + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get entityTarget(): any { + return GateModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: GateUpdatedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/gate/gate.module.ts b/src/modules/web-information/gate/gate.module.ts new file mode 100644 index 0000000..92298cb --- /dev/null +++ b/src/modules/web-information/gate/gate.module.ts @@ -0,0 +1,54 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { GateDataService } from './data/services/gate-data.service'; +import { GateReadService } from './data/services/gate-read.service'; +import { GateReadController } from './infrastructure/gate-read.controller'; +import { GateReadOrchestrator } from './domain/usecases/gate-read.orchestrator'; +import { GateDataController } from './infrastructure/gate-data.controller'; +import { GateDataOrchestrator } from './domain/usecases/gate-data.orchestrator'; +import { CreateGateManager } from './domain/usecases/managers/create-gate.manager'; +import { CqrsModule } from '@nestjs/cqrs'; +import { IndexGateManager } from './domain/usecases/managers/index-gate.manager'; +import { DeleteGateManager } from './domain/usecases/managers/delete-gate.manager'; +import { UpdateGateManager } from './domain/usecases/managers/update-gate.manager'; +import { ActiveGateManager } from './domain/usecases/managers/active-gate.manager'; +import { ConfirmGateManager } from './domain/usecases/managers/confirm-gate.manager'; +import { InactiveGateManager } from './domain/usecases/managers/inactive-gate.manager'; +import { DetailGateManager } from './domain/usecases/managers/detail-gate.manager'; +import { BatchDeleteGateManager } from './domain/usecases/managers/batch-delete-gate.manager'; +import { BatchActiveGateManager } from './domain/usecases/managers/batch-active-gate.manager'; +import { BatchConfirmGateManager } from './domain/usecases/managers/batch-confirm-gate.manager'; +import { BatchInactiveGateManager } from './domain/usecases/managers/batch-inactive-gate.manager'; +import { GateModel } from './data/models/gate.model'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature([GateModel], CONNECTION_NAME.DEFAULT), + CqrsModule, + ], + controllers: [GateDataController, GateReadController], + providers: [ + IndexGateManager, + DetailGateManager, + CreateGateManager, + DeleteGateManager, + UpdateGateManager, + ActiveGateManager, + ConfirmGateManager, + InactiveGateManager, + BatchDeleteGateManager, + BatchActiveGateManager, + BatchConfirmGateManager, + BatchInactiveGateManager, + + GateDataService, + GateReadService, + + GateDataOrchestrator, + GateReadOrchestrator, + ], +}) +export class GateModule {} diff --git a/src/modules/web-information/gate/index.ts b/src/modules/web-information/gate/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/web-information/gate/infrastructure/dto/filter-gate.dto.ts b/src/modules/web-information/gate/infrastructure/dto/filter-gate.dto.ts new file mode 100644 index 0000000..d3da747 --- /dev/null +++ b/src/modules/web-information/gate/infrastructure/dto/filter-gate.dto.ts @@ -0,0 +1,30 @@ +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterGateEntity } from '../../domain/entities/filter-gate.entity'; +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; + +export class FilterGateDto extends BaseFilterDto implements FilterGateEntity { + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + codes: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + types: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + item_names: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + notes: string[]; +} diff --git a/src/modules/web-information/gate/infrastructure/dto/gate.dto.ts b/src/modules/web-information/gate/infrastructure/dto/gate.dto.ts new file mode 100644 index 0000000..37167d5 --- /dev/null +++ b/src/modules/web-information/gate/infrastructure/dto/gate.dto.ts @@ -0,0 +1,45 @@ +import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.dto'; +import { GateEntity } from '../../domain/entities/gate.entity'; +import { GateType } from '../../constants'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsObject, IsString } from 'class-validator'; +import { Exclude } from 'class-transformer'; +import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity'; + +export class GateDto extends BaseStatusDto implements GateEntity { + @ApiProperty({ + type: String, + required: true, + example: GateType.GATE_IN, + }) + @IsString() + type: GateType; + + @ApiProperty({ + type: String, + required: true, + example: '41245', + }) + code: string; + + @ApiProperty({ + type: String, + required: false, + example: '41245', + }) + note: string; + + @ApiProperty({ + type: Object, + required: true, + example: { + id: 'uuid', + name: 'whana', + }, + }) + @IsObject() + item: ItemEntity; + + @Exclude() + item_id: string; +} diff --git a/src/modules/web-information/gate/infrastructure/gate-data.controller.ts b/src/modules/web-information/gate/infrastructure/gate-data.controller.ts new file mode 100644 index 0000000..96074d9 --- /dev/null +++ b/src/modules/web-information/gate/infrastructure/gate-data.controller.ts @@ -0,0 +1,78 @@ +import { + Body, + Controller, + Delete, + Param, + Patch, + Post, + Put, +} from '@nestjs/common'; +import { GateDataOrchestrator } from '../domain/usecases/gate-data.orchestrator'; +import { GateDto } from './dto/gate.dto'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { GateEntity } from '../domain/entities/gate.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'; + +@ApiTags(`${MODULE_NAME.GATE.split('-').join(' ')} - data`) +@Controller(`v1/${MODULE_NAME.GATE}`) +@Public(false) +@ApiBearerAuth('JWT') +export class GateDataController { + constructor(private orchestrator: GateDataOrchestrator) {} + + @Post() + async create(@Body() data: GateDto): Promise { + return await this.orchestrator.create(data); + } + + @Put('/batch-delete') + async batchDeleted(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchDelete(body.ids); + } + + @Patch(':id/active') + async active(@Param('id') dataId: string): Promise { + return await this.orchestrator.active(dataId); + } + + @Put('/batch-active') + async batchActive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchActive(body.ids); + } + + @Patch(':id/confirm') + async confirm(@Param('id') dataId: string): Promise { + return await this.orchestrator.confirm(dataId); + } + + @Put('/batch-confirm') + async batchConfirm(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchConfirm(body.ids); + } + + @Patch(':id/inactive') + async inactive(@Param('id') dataId: string): Promise { + return await this.orchestrator.inactive(dataId); + } + + @Put('/batch-inactive') + async batchInactive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchInactive(body.ids); + } + + @Put(':id') + async update( + @Param('id') dataId: string, + @Body() data: GateDto, + ): Promise { + return await this.orchestrator.update(dataId, data); + } + + @Delete(':id') + async delete(@Param('id') dataId: string): Promise { + return await this.orchestrator.delete(dataId); + } +} diff --git a/src/modules/web-information/gate/infrastructure/gate-read.controller.ts b/src/modules/web-information/gate/infrastructure/gate-read.controller.ts new file mode 100644 index 0000000..b6d213a --- /dev/null +++ b/src/modules/web-information/gate/infrastructure/gate-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterGateDto } from './dto/filter-gate.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { GateEntity } from '../domain/entities/gate.entity'; +import { GateReadOrchestrator } from '../domain/usecases/gate-read.orchestrator'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { Public } from 'src/core/guards'; + +@ApiTags(`${MODULE_NAME.GATE.split('-').join(' ')} - read`) +@Controller(`v1/${MODULE_NAME.GATE}`) +@Public(false) +@ApiBearerAuth('JWT') +export class GateReadController { + constructor(private orchestrator: GateReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterGateDto, + ): Promise> { + return await this.orchestrator.index(params); + } + + @Get(':id') + async detail(@Param('id') id: string): Promise { + return await this.orchestrator.detail(id); + } +} diff --git a/src/modules/web-information/term-condition/constants.ts b/src/modules/web-information/term-condition/constants.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/web-information/term-condition/data/models/term-condition.model.ts b/src/modules/web-information/term-condition/data/models/term-condition.model.ts new file mode 100644 index 0000000..08a3ade --- /dev/null +++ b/src/modules/web-information/term-condition/data/models/term-condition.model.ts @@ -0,0 +1,16 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { TermConditionEntity } from '../../domain/entities/term-condition.entity'; +import { Column, Entity } from 'typeorm'; +import { BaseStatusModel } from 'src/core/modules/data/model/base-status.model'; + +@Entity(TABLE_NAME.TERM_CONDITION) +export class TermConditionModel + extends BaseStatusModel + implements TermConditionEntity +{ + @Column('varchar', { name: 'title', nullable: true }) + title: string; + + @Column('text', { name: 'description', nullable: true }) + description: string; +} diff --git a/src/modules/web-information/term-condition/data/services/term-condition-data.service.ts b/src/modules/web-information/term-condition/data/services/term-condition-data.service.ts new file mode 100644 index 0000000..832e472 --- /dev/null +++ b/src/modules/web-information/term-condition/data/services/term-condition-data.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; +import { TermConditionEntity } from '../../domain/entities/term-condition.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { TermConditionModel } from '../models/term-condition.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; + +@Injectable() +export class TermConditionDataService extends BaseDataService { + constructor( + @InjectRepository(TermConditionModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/term-condition/data/services/term-condition-read.service.ts b/src/modules/web-information/term-condition/data/services/term-condition-read.service.ts new file mode 100644 index 0000000..98d4bc1 --- /dev/null +++ b/src/modules/web-information/term-condition/data/services/term-condition-read.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { TermConditionEntity } from '../../domain/entities/term-condition.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { TermConditionModel } from '../models/term-condition.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; +import { BaseReadService } from 'src/core/modules/data/service/base-read.service'; + +@Injectable() +export class TermConditionReadService extends BaseReadService { + constructor( + @InjectRepository(TermConditionModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/web-information/term-condition/domain/entities/event/term-condition-change-status.event.ts b/src/modules/web-information/term-condition/domain/entities/event/term-condition-change-status.event.ts new file mode 100644 index 0000000..80e32e1 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/event/term-condition-change-status.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TermConditionChangeStatusEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/term-condition/domain/entities/event/term-condition-created.event.ts b/src/modules/web-information/term-condition/domain/entities/event/term-condition-created.event.ts new file mode 100644 index 0000000..0defc89 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/event/term-condition-created.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TermConditionCreatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/term-condition/domain/entities/event/term-condition-deleted.event.ts b/src/modules/web-information/term-condition/domain/entities/event/term-condition-deleted.event.ts new file mode 100644 index 0000000..d2a108a --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/event/term-condition-deleted.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TermConditionDeletedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/term-condition/domain/entities/event/term-condition-updated.event.ts b/src/modules/web-information/term-condition/domain/entities/event/term-condition-updated.event.ts new file mode 100644 index 0000000..0bde406 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/event/term-condition-updated.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TermConditionUpdatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/web-information/term-condition/domain/entities/filter-term-condition.entity.ts b/src/modules/web-information/term-condition/domain/entities/filter-term-condition.entity.ts new file mode 100644 index 0000000..66cee61 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/filter-term-condition.entity.ts @@ -0,0 +1,3 @@ +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; + +export interface FilterTermConditionEntity extends BaseFilterEntity {} diff --git a/src/modules/web-information/term-condition/domain/entities/term-condition.entity.ts b/src/modules/web-information/term-condition/domain/entities/term-condition.entity.ts new file mode 100644 index 0000000..3e662e3 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/entities/term-condition.entity.ts @@ -0,0 +1,6 @@ +import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity'; + +export interface TermConditionEntity extends BaseStatusEntity { + title: string; + description: string; +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/active-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/active-term-condition.manager.ts new file mode 100644 index 0000000..9daee6f --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/active-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; + +@Injectable() +export class ActiveTermConditionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/batch-active-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/batch-active-term-condition.manager.ts new file mode 100644 index 0000000..cb85f8f --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/batch-active-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchActiveTermConditionManager extends BaseBatchUpdateStatusManager { + validateData(data: TermConditionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/batch-confirm-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/batch-confirm-term-condition.manager.ts new file mode 100644 index 0000000..5403de8 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/batch-confirm-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchConfirmTermConditionManager extends BaseBatchUpdateStatusManager { + validateData(data: TermConditionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/batch-delete-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/batch-delete-term-condition.manager.ts new file mode 100644 index 0000000..7246193 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/batch-delete-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionDeletedEvent } from '../../entities/event/term-condition-deleted.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchDeleteTermConditionManager extends BaseBatchDeleteManager { + async beforeProcess(): Promise { + return; + } + + async validateData(data: TermConditionEntity): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionDeletedEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/batch-inactive-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/batch-inactive-term-condition.manager.ts new file mode 100644 index 0000000..b234d43 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/batch-inactive-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchInactiveTermConditionManager extends BaseBatchUpdateStatusManager { + validateData(data: TermConditionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/confirm-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/confirm-term-condition.manager.ts new file mode 100644 index 0000000..7a0adfc --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/confirm-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; + +@Injectable() +export class ConfirmTermConditionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/create-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/create-term-condition.manager.ts new file mode 100644 index 0000000..ab08d99 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/create-term-condition.manager.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; +import { TermConditionCreatedEvent } from '../../entities/event/term-condition-created.event'; + +@Injectable() +export class CreateTermConditionManager extends BaseCreateManager { + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionCreatedEvent, + data: this.data, + }, + ]; + } + + get entityTarget(): any { + return TermConditionModel; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/delete-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/delete-term-condition.manager.ts new file mode 100644 index 0000000..7732a48 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/delete-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionDeletedEvent } from '../../entities/event/term-condition-deleted.event'; + +@Injectable() +export class DeleteTermConditionManager extends BaseDeleteManager { + getResult(): string { + return `Success`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionDeletedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/detail-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/detail-term-condition.manager.ts new file mode 100644 index 0000000..6810339 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/detail-term-condition.manager.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class DetailTermConditionManager extends BaseDetailManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.title`, + `${this.tableName}.description`, + ]; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/inactive-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/inactive-term-condition.manager.ts new file mode 100644 index 0000000..5fa1432 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/inactive-term-condition.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionChangeStatusEvent } from '../../entities/event/term-condition-change-status.event'; + +@Injectable() +export class InactiveTermConditionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success inactive data ${this.result.title}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/index-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/index-term-condition.manager.ts new file mode 100644 index 0000000..7897eca --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/index-term-condition.manager.ts @@ -0,0 +1,64 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class IndexTermConditionManager extends BaseIndexManager { + async prepareData(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get relations(): RelationParam { + return { + // relation only join (for query purpose) + joinRelations: [], + + // relation join and select (relasi yang ingin ditampilkan), + selectRelations: [], + + // relation yang hanya ingin dihitung (akan return number) + countRelations: [], + }; + } + + get selects(): string[] { + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.updated_at`, + `${this.tableName}.editor_name`, + `${this.tableName}.title`, + `${this.tableName}.description`, + ]; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.name`, + data: this.filterParam.names, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + return queryBuilder; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/managers/update-term-condition.manager.ts b/src/modules/web-information/term-condition/domain/usecases/managers/update-term-condition.manager.ts new file mode 100644 index 0000000..8c08145 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/managers/update-term-condition.manager.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; +import { TermConditionEntity } from '../../entities/term-condition.entity'; +import { TermConditionModel } from '../../../data/models/term-condition.model'; +import { TermConditionUpdatedEvent } from '../../entities/event/term-condition-updated.event'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; + +@Injectable() +export class UpdateTermConditionManager extends BaseUpdateManager { + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get entityTarget(): any { + return TermConditionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TermConditionUpdatedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/term-condition-data.orchestrator.ts b/src/modules/web-information/term-condition/domain/usecases/term-condition-data.orchestrator.ts new file mode 100644 index 0000000..c1b41f9 --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/term-condition-data.orchestrator.ts @@ -0,0 +1,121 @@ +import { Injectable } from '@nestjs/common'; +import { CreateTermConditionManager } from './managers/create-term-condition.manager'; +import { TermConditionDataService } from '../../data/services/term-condition-data.service'; +import { TermConditionEntity } from '../entities/term-condition.entity'; +import { DeleteTermConditionManager } from './managers/delete-term-condition.manager'; +import { UpdateTermConditionManager } from './managers/update-term-condition.manager'; +import { BaseDataTransactionOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-data-transaction.orchestrator'; +import { ActiveTermConditionManager } from './managers/active-term-condition.manager'; +import { InactiveTermConditionManager } from './managers/inactive-term-condition.manager'; +import { ConfirmTermConditionManager } from './managers/confirm-term-condition.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchConfirmTermConditionManager } from './managers/batch-confirm-term-condition.manager'; +import { BatchInactiveTermConditionManager } from './managers/batch-inactive-term-condition.manager'; +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'; + +@Injectable() +export class TermConditionDataOrchestrator extends BaseDataTransactionOrchestrator { + constructor( + private createManager: CreateTermConditionManager, + private updateManager: UpdateTermConditionManager, + private deleteManager: DeleteTermConditionManager, + private activeManager: ActiveTermConditionManager, + private confirmManager: ConfirmTermConditionManager, + private inactiveManager: InactiveTermConditionManager, + private batchDeleteManager: BatchDeleteTermConditionManager, + private batchActiveManager: BatchActiveTermConditionManager, + private batchConfirmManager: BatchConfirmTermConditionManager, + private batchInactiveManager: BatchInactiveTermConditionManager, + private serviceData: TermConditionDataService, + ) { + super(); + } + + async create(data): Promise { + this.createManager.setData(data); + this.createManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.createManager.execute(); + return this.createManager.getResult(); + } + + async update(dataId, data): Promise { + this.updateManager.setData(dataId, data); + this.updateManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.updateManager.execute(); + return this.updateManager.getResult(); + } + + async delete(dataId): Promise { + this.deleteManager.setData(dataId); + this.deleteManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.deleteManager.execute(); + return this.deleteManager.getResult(); + } + + async batchDelete(dataIds: string[]): Promise { + this.batchDeleteManager.setData(dataIds); + this.batchDeleteManager.setService( + this.serviceData, + TABLE_NAME.TERM_CONDITION, + ); + await this.batchDeleteManager.execute(); + return this.batchDeleteManager.getResult(); + } + + async active(dataId): Promise { + this.activeManager.setData(dataId, STATUS.ACTIVE); + this.activeManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.activeManager.execute(); + return this.activeManager.getResult(); + } + + async batchActive(dataIds: string[]): Promise { + this.batchActiveManager.setData(dataIds, STATUS.ACTIVE); + this.batchActiveManager.setService( + this.serviceData, + TABLE_NAME.TERM_CONDITION, + ); + await this.batchActiveManager.execute(); + return this.batchActiveManager.getResult(); + } + + async confirm(dataId): Promise { + this.confirmManager.setData(dataId, STATUS.ACTIVE); + this.confirmManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.confirmManager.execute(); + return this.confirmManager.getResult(); + } + + async batchConfirm(dataIds: string[]): Promise { + this.batchConfirmManager.setData(dataIds, STATUS.ACTIVE); + this.batchConfirmManager.setService( + this.serviceData, + TABLE_NAME.TERM_CONDITION, + ); + await this.batchConfirmManager.execute(); + return this.batchConfirmManager.getResult(); + } + + async inactive(dataId): Promise { + this.inactiveManager.setData(dataId, STATUS.INACTIVE); + this.inactiveManager.setService( + this.serviceData, + TABLE_NAME.TERM_CONDITION, + ); + await this.inactiveManager.execute(); + return this.inactiveManager.getResult(); + } + + async batchInactive(dataIds: string[]): Promise { + this.batchInactiveManager.setData(dataIds, STATUS.INACTIVE); + this.batchInactiveManager.setService( + this.serviceData, + TABLE_NAME.TERM_CONDITION, + ); + await this.batchInactiveManager.execute(); + return this.batchInactiveManager.getResult(); + } +} diff --git a/src/modules/web-information/term-condition/domain/usecases/term-condition-read.orchestrator.ts b/src/modules/web-information/term-condition/domain/usecases/term-condition-read.orchestrator.ts new file mode 100644 index 0000000..00427fd --- /dev/null +++ b/src/modules/web-information/term-condition/domain/usecases/term-condition-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexTermConditionManager } from './managers/index-term-condition.manager'; +import { TermConditionReadService } from '../../data/services/term-condition-read.service'; +import { TermConditionEntity } from '../entities/term-condition.entity'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailTermConditionManager } from './managers/detail-term-condition.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class TermConditionReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexTermConditionManager, + private detailManager: DetailTermConditionManager, + private serviceData: TermConditionReadService, + ) { + super(); + } + + async index(params): Promise> { + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.indexManager.execute(); + return this.indexManager.getResult(); + } + + async detail(dataId: string): Promise { + this.detailManager.setData(dataId); + this.detailManager.setService(this.serviceData, TABLE_NAME.TERM_CONDITION); + await this.detailManager.execute(); + return this.detailManager.getResult(); + } +} diff --git a/src/modules/web-information/term-condition/index.ts b/src/modules/web-information/term-condition/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/web-information/term-condition/infrastructure/dto/filter-term-condition.dto.ts b/src/modules/web-information/term-condition/infrastructure/dto/filter-term-condition.dto.ts new file mode 100644 index 0000000..ffcac6f --- /dev/null +++ b/src/modules/web-information/term-condition/infrastructure/dto/filter-term-condition.dto.ts @@ -0,0 +1,6 @@ +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterTermConditionEntity } from '../../domain/entities/filter-term-condition.entity'; + +export class FilterTermConditionDto + extends BaseFilterDto + implements FilterTermConditionEntity {} diff --git a/src/modules/web-information/term-condition/infrastructure/dto/term-condition.dto.ts b/src/modules/web-information/term-condition/infrastructure/dto/term-condition.dto.ts new file mode 100644 index 0000000..b0eb01f --- /dev/null +++ b/src/modules/web-information/term-condition/infrastructure/dto/term-condition.dto.ts @@ -0,0 +1,24 @@ +import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.dto'; +import { TermConditionEntity } from '../../domain/entities/term-condition.entity'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class TermConditionDto + extends BaseStatusDto + implements TermConditionEntity +{ + @ApiProperty({ + type: String, + required: true, + example: 'Booking', + }) + @IsString() + title: string; + + @ApiProperty({ + type: String, + required: false, + example: 'Booking descs', + }) + description: string; +} diff --git a/src/modules/web-information/term-condition/infrastructure/term-condition-data.controller.ts b/src/modules/web-information/term-condition/infrastructure/term-condition-data.controller.ts new file mode 100644 index 0000000..2f497c9 --- /dev/null +++ b/src/modules/web-information/term-condition/infrastructure/term-condition-data.controller.ts @@ -0,0 +1,78 @@ +import { + Body, + Controller, + Delete, + Param, + Patch, + Post, + Put, +} from '@nestjs/common'; +import { TermConditionDataOrchestrator } from '../domain/usecases/term-condition-data.orchestrator'; +import { TermConditionDto } from './dto/term-condition.dto'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +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'; + +@ApiTags(`${MODULE_NAME.TERM_CONDITION.split('-').join(' ')} - data`) +@Controller(`v1/${MODULE_NAME.TERM_CONDITION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class TermConditionDataController { + constructor(private orchestrator: TermConditionDataOrchestrator) {} + + @Post() + async create(@Body() data: TermConditionDto): Promise { + return await this.orchestrator.create(data); + } + + @Put('/batch-delete') + async batchDeleted(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchDelete(body.ids); + } + + @Patch(':id/active') + async active(@Param('id') dataId: string): Promise { + return await this.orchestrator.active(dataId); + } + + @Put('/batch-active') + async batchActive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchActive(body.ids); + } + + @Patch(':id/confirm') + async confirm(@Param('id') dataId: string): Promise { + return await this.orchestrator.confirm(dataId); + } + + @Put('/batch-confirm') + async batchConfirm(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchConfirm(body.ids); + } + + @Patch(':id/inactive') + async inactive(@Param('id') dataId: string): Promise { + return await this.orchestrator.inactive(dataId); + } + + @Put('/batch-inactive') + async batchInactive(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchInactive(body.ids); + } + + @Put(':id') + async update( + @Param('id') dataId: string, + @Body() data: TermConditionDto, + ): Promise { + return await this.orchestrator.update(dataId, data); + } + + @Delete(':id') + async delete(@Param('id') dataId: string): Promise { + return await this.orchestrator.delete(dataId); + } +} diff --git a/src/modules/web-information/term-condition/infrastructure/term-condition-read.controller.ts b/src/modules/web-information/term-condition/infrastructure/term-condition-read.controller.ts new file mode 100644 index 0000000..773b939 --- /dev/null +++ b/src/modules/web-information/term-condition/infrastructure/term-condition-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterTermConditionDto } from './dto/filter-term-condition.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { TermConditionEntity } from '../domain/entities/term-condition.entity'; +import { TermConditionReadOrchestrator } from '../domain/usecases/term-condition-read.orchestrator'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { Public } from 'src/core/guards'; + +@ApiTags(`${MODULE_NAME.TERM_CONDITION.split('-').join(' ')} - read`) +@Controller(`v1/${MODULE_NAME.TERM_CONDITION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class TermConditionReadController { + constructor(private orchestrator: TermConditionReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterTermConditionDto, + ): Promise> { + return await this.orchestrator.index(params); + } + + @Get(':id') + async detail(@Param('id') id: string): Promise { + return await this.orchestrator.detail(id); + } +} diff --git a/src/modules/web-information/term-condition/term-condition.module.ts b/src/modules/web-information/term-condition/term-condition.module.ts new file mode 100644 index 0000000..0f2e156 --- /dev/null +++ b/src/modules/web-information/term-condition/term-condition.module.ts @@ -0,0 +1,54 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { TermConditionDataService } from './data/services/term-condition-data.service'; +import { TermConditionReadService } from './data/services/term-condition-read.service'; +import { TermConditionReadController } from './infrastructure/term-condition-read.controller'; +import { TermConditionReadOrchestrator } from './domain/usecases/term-condition-read.orchestrator'; +import { TermConditionDataController } from './infrastructure/term-condition-data.controller'; +import { TermConditionDataOrchestrator } from './domain/usecases/term-condition-data.orchestrator'; +import { CreateTermConditionManager } from './domain/usecases/managers/create-term-condition.manager'; +import { CqrsModule } from '@nestjs/cqrs'; +import { IndexTermConditionManager } from './domain/usecases/managers/index-term-condition.manager'; +import { DeleteTermConditionManager } from './domain/usecases/managers/delete-term-condition.manager'; +import { UpdateTermConditionManager } from './domain/usecases/managers/update-term-condition.manager'; +import { ActiveTermConditionManager } from './domain/usecases/managers/active-term-condition.manager'; +import { ConfirmTermConditionManager } from './domain/usecases/managers/confirm-term-condition.manager'; +import { InactiveTermConditionManager } from './domain/usecases/managers/inactive-term-condition.manager'; +import { DetailTermConditionManager } from './domain/usecases/managers/detail-term-condition.manager'; +import { BatchDeleteTermConditionManager } from './domain/usecases/managers/batch-delete-term-condition.manager'; +import { BatchActiveTermConditionManager } from './domain/usecases/managers/batch-active-term-condition.manager'; +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'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature([TermConditionModel], CONNECTION_NAME.DEFAULT), + CqrsModule, + ], + controllers: [TermConditionDataController, TermConditionReadController], + providers: [ + IndexTermConditionManager, + DetailTermConditionManager, + CreateTermConditionManager, + DeleteTermConditionManager, + UpdateTermConditionManager, + ActiveTermConditionManager, + ConfirmTermConditionManager, + InactiveTermConditionManager, + BatchDeleteTermConditionManager, + BatchActiveTermConditionManager, + BatchConfirmTermConditionManager, + BatchInactiveTermConditionManager, + + TermConditionDataService, + TermConditionReadService, + + TermConditionDataOrchestrator, + TermConditionReadOrchestrator, + ], +}) +export class TermConditionModule {}