From 8ce58981c74d8fc6c46141af5b95c2dd55296013 Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah <98192542+Asharaswin@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:18:35 +0700 Subject: [PATCH] wip-feat(SPG-383) REST API CUD Booking/Pemesanan --- src/app.module.ts | 4 + .../migrations/1719572714752-transaction.ts | 55 ++++++ .../transaction/transaction/constants.ts | 31 ++++ .../data/models/transaction-item.model.ts | 59 ++++++ .../data/models/transaction-tax.model.ts | 29 +++ .../data/models/transaction.model.ts | 171 ++++++++++++++++++ .../data/services/transaction-data.service.ts | 17 ++ .../data/services/transaction-read.service.ts | 17 ++ .../event/transaction-change-status.event.ts | 5 + .../event/transaction-created.event.ts | 5 + .../event/transaction-deleted.event.ts | 5 + .../event/transaction-updated.event.ts | 5 + .../entities/filter-transaction.entity.ts | 3 + .../entities/transaction-item.entity.ts | 21 +++ .../domain/entities/transaction-tax.entity.ts | 7 + .../domain/entities/transaction.entity.ts | 62 +++++++ .../managers/active-transaction.manager.ts | 45 +++++ .../batch-active-transaction.manager.ts | 45 +++++ .../batch-confirm-transaction.manager.ts | 45 +++++ .../batch-delete-transaction.manager.ts | 45 +++++ .../batch-inactive-transaction.manager.ts | 45 +++++ .../managers/confirm-transaction.manager.ts | 45 +++++ .../managers/create-transaction.manager.ts | 69 +++++++ .../managers/delete-transaction.manager.ts | 45 +++++ .../managers/detail-transaction.manager.ts | 42 +++++ .../managers/inactive-transaction.manager.ts | 45 +++++ .../managers/index-transaction.manager.ts | 55 ++++++ .../managers/update-transaction.manager.ts | 46 +++++ .../usecases/transaction-data.orchestrator.ts | 118 ++++++++++++ .../usecases/transaction-read.orchestrator.ts | 33 ++++ src/modules/transaction/transaction/index.ts | 0 .../dto/filter-transaction.dto.ts | 6 + .../dto/transaction-item.dto.ts | 39 ++++ .../infrastructure/dto/transaction.dto.ts | 145 +++++++++++++++ .../transaction-data.controller.ts | 78 ++++++++ .../transaction-read.controller.ts | 30 +++ .../transaction/transaction.module.ts | 54 ++++++ 37 files changed, 1571 insertions(+) create mode 100644 src/database/migrations/1719572714752-transaction.ts create mode 100644 src/modules/transaction/transaction/constants.ts create mode 100644 src/modules/transaction/transaction/data/models/transaction-item.model.ts create mode 100644 src/modules/transaction/transaction/data/models/transaction-tax.model.ts create mode 100644 src/modules/transaction/transaction/data/models/transaction.model.ts create mode 100644 src/modules/transaction/transaction/data/services/transaction-data.service.ts create mode 100644 src/modules/transaction/transaction/data/services/transaction-read.service.ts create mode 100644 src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event.ts create mode 100644 src/modules/transaction/transaction/domain/entities/event/transaction-created.event.ts create mode 100644 src/modules/transaction/transaction/domain/entities/event/transaction-deleted.event.ts create mode 100644 src/modules/transaction/transaction/domain/entities/event/transaction-updated.event.ts create mode 100644 src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts create mode 100644 src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts create mode 100644 src/modules/transaction/transaction/domain/entities/transaction-tax.entity.ts create mode 100644 src/modules/transaction/transaction/domain/entities/transaction.entity.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/batch-delete-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/delete-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/index-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/managers/update-transaction.manager.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/transaction-data.orchestrator.ts create mode 100644 src/modules/transaction/transaction/domain/usecases/transaction-read.orchestrator.ts create mode 100644 src/modules/transaction/transaction/index.ts create mode 100644 src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts create mode 100644 src/modules/transaction/transaction/infrastructure/dto/transaction-item.dto.ts create mode 100644 src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts create mode 100644 src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts create mode 100644 src/modules/transaction/transaction/infrastructure/transaction-read.controller.ts create mode 100644 src/modules/transaction/transaction/transaction.module.ts diff --git a/src/app.module.ts b/src/app.module.ts index f430b37..92ce21d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -42,6 +42,8 @@ import { SeasonPeriodModel } from './modules/season-related/season-period/data/m import { ItemRateModule } from './modules/item-related/item-rate/item-rate.module'; import { ItemRateModel } from './modules/item-related/item-rate/data/models/item-rate.model'; import { GoogleCalendarModule } from './modules/configuration/google-calendar/google-calendar.module'; +import { TransactionModule } from './modules/transaction/transaction/transaction.module'; +import { TransactionModels } from './modules/transaction/transaction/constants'; @Module({ imports: [ @@ -69,6 +71,7 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go SeasonPeriodModel, SeasonTypeModel, TaxModel, + ...TransactionModels, UserModel, VipCategoryModel, VipCodeModel, @@ -98,6 +101,7 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go ProfitShareFormulaModule, SalesPriceFormulaModule, TaxModule, + TransactionModule, VipCategoryModule, VipCodeModule, diff --git a/src/database/migrations/1719572714752-transaction.ts b/src/database/migrations/1719572714752-transaction.ts new file mode 100644 index 0000000..dd488a7 --- /dev/null +++ b/src/database/migrations/1719572714752-transaction.ts @@ -0,0 +1,55 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class Transaction1719572714752 implements MigrationInterface { + name = 'Transaction1719572714752'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "transaction_items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "item_id" character varying, "item_name" character varying, "item_type" character varying, "item_price" bigint, "item_tenant_id" character varying, "item_tenant_name" character varying, "item_tenant_share_margin" numeric, "total_price" numeric, "total_hpp" numeric, "total_profit" numeric, "total_share_tenant" numeric, "qty" integer, "transaction_id" uuid, CONSTRAINT "PK_ff5a487ad820dccafd53bebf578" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TABLE "transaction_taxes" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "tax_id" character varying, "tax_name" character varying, "taxt_value" character varying, "transaction_id" uuid, CONSTRAINT "PK_208b2abdb10640e1991972fc754" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_type_enum" AS ENUM('counter', 'admin', 'online')`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_customer_type_enum" AS ENUM('group', 'vip')`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_payment_type_enum" AS ENUM('midtrans', 'bank transfer', 'qris', 'counter', 'cash', 'credit card', 'debit', 'e-money')`, + ); + await queryRunner.query( + `CREATE TABLE "transactions" ("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"."transactions_status_enum" NOT NULL DEFAULT 'draft', "type" "public"."transactions_type_enum" NOT NULL DEFAULT 'admin', "invoice_code" character varying, "creator_counter_no" integer, "season_period_id" character varying, "season_period_name" character varying, "season_period_type_id" character varying, "season_period_type_name" character varying, "customer_type" "public"."transactions_customer_type_enum", "customer_category_id" character varying, "customer_category_name" character varying, "customer_name" character varying, "customer_phone" character varying, "customer_email" character varying, "customer_description" character varying, "no_of_group" character varying, "booking_date" date, "settlement_date" date, "invoice_date" date, "discount_code_id" character varying, "discount_code" character varying, "discount_percentage" integer, "discount_value" numeric, "payment_type" "public"."transactions_payment_type_enum" NOT NULL DEFAULT 'bank transfer', "payment_type_method_id" character varying, "payment_type_method_name" character varying, "payment_type_method_qr" character varying, "payment_card_information" character varying, "payment_code_reference" character varying, "payment_date" date, "payment_sub_total" numeric, "payment_discount_total" numeric, "payment_total" numeric, "payment_total_pay" numeric, "payment_change" numeric, "payment_total_share" numeric, "payment_total_tax" numeric, "payment_total_profit" numeric, "profit_share_formula" character varying, "sales_price_formula" character varying, CONSTRAINT "PK_a219afd8dd77ed80f5a862f1db9" PRIMARY KEY ("id"))`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" ADD CONSTRAINT "FK_5926425896b30c0d681fe879af0" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_taxes" ADD CONSTRAINT "FK_d21db1756c6656efc7c082fbaa6" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE CASCADE ON UPDATE CASCADE`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "transaction_taxes" DROP CONSTRAINT "FK_d21db1756c6656efc7c082fbaa6"`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" DROP CONSTRAINT "FK_5926425896b30c0d681fe879af0"`, + ); + await queryRunner.query(`DROP TABLE "transactions"`); + await queryRunner.query( + `DROP TYPE "public"."transactions_payment_type_enum"`, + ); + await queryRunner.query( + `DROP TYPE "public"."transactions_customer_type_enum"`, + ); + await queryRunner.query(`DROP TYPE "public"."transactions_type_enum"`); + await queryRunner.query(`DROP TYPE "public"."transactions_status_enum"`); + await queryRunner.query(`DROP TABLE "transaction_taxes"`); + await queryRunner.query(`DROP TABLE "transaction_items"`); + } +} diff --git a/src/modules/transaction/transaction/constants.ts b/src/modules/transaction/transaction/constants.ts new file mode 100644 index 0000000..c03e7de --- /dev/null +++ b/src/modules/transaction/transaction/constants.ts @@ -0,0 +1,31 @@ +import { TransactionItemModel } from './data/models/transaction-item.model'; +import { TransactionTaxModel } from './data/models/transaction-tax.model'; +import { TransactionModel } from './data/models/transaction.model'; + +export enum TransactionPaymentType { + MIDTRANS = 'midtrans', + BANK_TRANSFER = 'bank transfer', + QRIS = 'qris', + COUNTER = 'counter', + CASH = 'cash', + CC = 'credit card', + DEBIT = 'debit', + EMONEY = 'e-money', +} + +export enum TransactionType { + COUNTER = 'counter', // transaksi yang dibuat dari POS / Counter + ADMIN = 'admin', // transaksi yang dibuat dari ADMIN page booking + ONLINE = 'online', // transaksi yang dibuat dari USER booking online +} + +export enum TransactionUserType { + GROUP = 'group', + VIP = 'vip', +} + +export const TransactionModels = [ + TransactionModel, + TransactionItemModel, + TransactionTaxModel, +]; diff --git a/src/modules/transaction/transaction/data/models/transaction-item.model.ts b/src/modules/transaction/transaction/data/models/transaction-item.model.ts new file mode 100644 index 0000000..a328ecd --- /dev/null +++ b/src/modules/transaction/transaction/data/models/transaction-item.model.ts @@ -0,0 +1,59 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { BaseCoreModel } from 'src/core/modules/data/model/base-core.model'; +import { TransactionItemEntity } from '../../domain/entities/transaction-item.entity'; +import { TransactionModel } from './transaction.model'; + +@Entity(TABLE_NAME.TRANSACTION_ITEM) +export class TransactionItemModel + extends BaseCoreModel + implements TransactionItemEntity +{ + // item data + @Column('varchar', { name: 'item_id', nullable: true }) + item_id: string; + + @Column('varchar', { name: 'item_name', nullable: true }) + item_name: string; + + @Column('varchar', { name: 'item_type', nullable: true }) + item_type: string; + + @Column('bigint', { name: 'item_price', nullable: true }) + item_price: number; + + // item tenant data + @Column('varchar', { name: 'item_tenant_id', nullable: true }) + item_tenant_id: string; + + @Column('varchar', { name: 'item_tenant_name', nullable: true }) + item_tenant_name: string; + + @Column('decimal', { name: 'item_tenant_share_margin', nullable: true }) + item_tenant_share_margin: number; + + // calculation data + @Column('decimal', { name: 'total_price', nullable: true }) + total_price: number; + + @Column('decimal', { name: 'total_hpp', nullable: true }) + total_hpp: number; + + @Column('decimal', { name: 'total_profit', nullable: true }) + total_profit: number; + + @Column('decimal', { name: 'total_share_tenant', nullable: true }) + total_share_tenant: number; + + @Column('int', { name: 'qty', nullable: true }) + qty: number; + + @Column('varchar', { name: 'transaction_id', nullable: true }) + transaction_id: string; + @ManyToOne(() => TransactionModel, (model) => model.items, { + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + @JoinColumn({ name: 'transaction_id' }) + transaction: TransactionModel; +} diff --git a/src/modules/transaction/transaction/data/models/transaction-tax.model.ts b/src/modules/transaction/transaction/data/models/transaction-tax.model.ts new file mode 100644 index 0000000..c069bee --- /dev/null +++ b/src/modules/transaction/transaction/data/models/transaction-tax.model.ts @@ -0,0 +1,29 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; +import { TransactionTaxEntity } from '../../domain/entities/transaction-tax.entity'; +import { BaseCoreModel } from 'src/core/modules/data/model/base-core.model'; +import { TransactionModel } from './transaction.model'; + +@Entity(TABLE_NAME.TRANSACTION_TAX) +export class TransactionTaxModel + extends BaseCoreModel + implements TransactionTaxEntity +{ + @Column('varchar', { name: 'tax_id', nullable: true }) + tax_id: string; + + @Column('varchar', { name: 'tax_name', nullable: true }) + tax_name: string; + + @Column('varchar', { name: 'taxt_value', nullable: true }) + taxt_value: number; + + @Column('varchar', { name: 'transaction_id', nullable: true }) + transaction_id: string; + @ManyToOne(() => TransactionModel, (model) => model.taxes, { + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + @JoinColumn({ name: 'transaction_id' }) + transaction: TransactionModel; +} diff --git a/src/modules/transaction/transaction/data/models/transaction.model.ts b/src/modules/transaction/transaction/data/models/transaction.model.ts new file mode 100644 index 0000000..dd9194a --- /dev/null +++ b/src/modules/transaction/transaction/data/models/transaction.model.ts @@ -0,0 +1,171 @@ +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { TransactionEntity } from '../../domain/entities/transaction.entity'; +import { Column, Entity, OneToMany } from 'typeorm'; +import { BaseStatusModel } from 'src/core/modules/data/model/base-status.model'; +import { + TransactionType, + TransactionUserType, + TransactionPaymentType, +} from '../../constants'; +import { TransactionItemEntity } from '../../domain/entities/transaction-item.entity'; +import { TransactionItemModel } from './transaction-item.model'; +import { TransactionTaxModel } from './transaction-tax.model'; + +@Entity(TABLE_NAME.TRANSACTION) +export class TransactionModel + extends BaseStatusModel + implements TransactionEntity +{ + // general info + @Column('enum', { + name: 'type', + enum: TransactionType, + default: TransactionType.ADMIN, + }) + type: TransactionType; + + @Column('varchar', { name: 'invoice_code', nullable: true }) + invoice_code: string; + + @Column('int', { name: 'creator_counter_no', nullable: true }) + creator_counter_no: number; + + // season data + @Column('varchar', { name: 'season_period_id', nullable: true }) + season_period_id: string; + + @Column('varchar', { name: 'season_period_name', nullable: true }) + season_period_name: string; + + @Column('varchar', { name: 'season_period_type_id', nullable: true }) + season_period_type_id: string; + + @Column('varchar', { name: 'season_period_type_name', nullable: true }) + season_period_type_name: string; + + // customer info + @Column('enum', { + name: 'customer_type', + enum: TransactionUserType, + nullable: true, + }) + customer_type: TransactionUserType; + + @Column('varchar', { name: 'customer_category_id', nullable: true }) + customer_category_id: string; + + @Column('varchar', { name: 'customer_category_name', nullable: true }) + customer_category_name: string; + + @Column('varchar', { name: 'customer_name', nullable: true }) + customer_name: string; + + @Column('varchar', { name: 'customer_phone', nullable: true }) + customer_phone: string; + + @Column('varchar', { name: 'customer_email', nullable: true }) + customer_email: string; + + @Column('varchar', { name: 'customer_description', nullable: true }) + customer_description: string; + + @Column('varchar', { name: 'no_of_group', nullable: true }) + no_of_group: number; + + @Column('date', { name: 'booking_date', nullable: true }) + booking_date: Date; + + @Column('date', { name: 'settlement_date', nullable: true }) + settlement_date: Date; + + @Column('date', { name: 'invoice_date', nullable: true }) + invoice_date: Date; + + // discount data + @Column('varchar', { name: 'discount_code_id', nullable: true }) + discount_code_id: string; + + @Column('varchar', { name: 'discount_code', nullable: true }) + discount_code: string; + + @Column('int', { name: 'discount_percentage', nullable: true }) + discount_percentage: number; + + @Column('decimal', { name: 'discount_value', nullable: true }) + discount_value: number; + + // payment data + @Column('enum', { + name: 'payment_type', + enum: TransactionPaymentType, + default: TransactionPaymentType.BANK_TRANSFER, + }) + payment_type: TransactionPaymentType; + + @Column('varchar', { name: 'payment_type_method_id', nullable: true }) + payment_type_method_id: string; + + @Column('varchar', { name: 'payment_type_method_name', nullable: true }) + payment_type_method_name: string; + + @Column('varchar', { name: 'payment_type_method_qr', nullable: true }) + payment_type_method_qr: string; + + @Column('varchar', { name: 'payment_card_information', nullable: true }) + payment_card_information: string; + + @Column('varchar', { name: 'payment_code_reference', nullable: true }) + payment_code_reference: string; + + @Column('date', { name: 'payment_date', nullable: true }) + payment_date: Date; + + // calculation data + + @Column('decimal', { name: 'payment_sub_total', nullable: true }) + payment_sub_total: number; + + @Column('decimal', { name: 'payment_discount_total', nullable: true }) + payment_discount_total: number; + + @Column('decimal', { name: 'payment_total', nullable: true }) + payment_total: number; + + @Column('decimal', { name: 'payment_total_pay', nullable: true }) + payment_total_pay: number; + + @Column('decimal', { name: 'payment_change', nullable: true }) + payment_change: number; + + // share and profit data + @Column('decimal', { name: 'payment_total_share', nullable: true }) + payment_total_share: number; + + @Column('decimal', { name: 'payment_total_tax', nullable: true }) + payment_total_tax: number; + + @Column('decimal', { name: 'payment_total_profit', nullable: true }) + payment_total_profit: number; + + @Column('varchar', { name: 'profit_share_formula', nullable: true }) + profit_share_formula: string; + + @Column('varchar', { name: 'sales_price_formula', nullable: true }) + sales_price_formula: string; + + // relations to item + @OneToMany(() => TransactionItemModel, (model) => model.transaction, { + cascade: true, + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + items: TransactionItemEntity[]; + + // relations to tax data + @OneToMany(() => TransactionTaxModel, (model) => model.transaction, { + cascade: true, + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + taxes: TransactionTaxModel[]; +} diff --git a/src/modules/transaction/transaction/data/services/transaction-data.service.ts b/src/modules/transaction/transaction/data/services/transaction-data.service.ts new file mode 100644 index 0000000..f13c3b7 --- /dev/null +++ b/src/modules/transaction/transaction/data/services/transaction-data.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; +import { TransactionEntity } from '../../domain/entities/transaction.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { TransactionModel } from '../models/transaction.model'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { Repository } from 'typeorm'; + +@Injectable() +export class TransactionDataService extends BaseDataService { + constructor( + @InjectRepository(TransactionModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/transaction/transaction/data/services/transaction-read.service.ts b/src/modules/transaction/transaction/data/services/transaction-read.service.ts new file mode 100644 index 0000000..ddd488a --- /dev/null +++ b/src/modules/transaction/transaction/data/services/transaction-read.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { TransactionEntity } from '../../domain/entities/transaction.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { TransactionModel } from '../models/transaction.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 TransactionReadService extends BaseReadService { + constructor( + @InjectRepository(TransactionModel, CONNECTION_NAME.DEFAULT) + private repo: Repository, + ) { + super(repo); + } +} diff --git a/src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event.ts b/src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event.ts new file mode 100644 index 0000000..53ffa35 --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/event/transaction-change-status.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TransactionChangeStatusEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/transaction/transaction/domain/entities/event/transaction-created.event.ts b/src/modules/transaction/transaction/domain/entities/event/transaction-created.event.ts new file mode 100644 index 0000000..2e02ca9 --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/event/transaction-created.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TransactionCreatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/transaction/transaction/domain/entities/event/transaction-deleted.event.ts b/src/modules/transaction/transaction/domain/entities/event/transaction-deleted.event.ts new file mode 100644 index 0000000..db26934 --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/event/transaction-deleted.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TransactionDeletedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/transaction/transaction/domain/entities/event/transaction-updated.event.ts b/src/modules/transaction/transaction/domain/entities/event/transaction-updated.event.ts new file mode 100644 index 0000000..e3a82c9 --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/event/transaction-updated.event.ts @@ -0,0 +1,5 @@ +import { IEvent } from 'src/core/strings/constants/interface.constants'; + +export class TransactionUpdatedEvent { + constructor(public readonly data: IEvent) {} +} diff --git a/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts b/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts new file mode 100644 index 0000000..13bd3af --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts @@ -0,0 +1,3 @@ +import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; + +export interface FilterTransactionEntity extends BaseFilterEntity {} diff --git a/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts b/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts new file mode 100644 index 0000000..a1313ad --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts @@ -0,0 +1,21 @@ +import { BaseCoreEntity } from 'src/core/modules/domain/entities/base-core.entity'; + +export interface TransactionItemEntity extends BaseCoreEntity { + // item detail + item_id: string; + item_name: string; + item_type: string; + item_price: number; + + // item tenant data + item_tenant_id: string; + item_tenant_name: string; + item_tenant_share_margin: number; + + // calculation data + total_price: number; + total_hpp: number; + total_profit: number; + total_share_tenant: number; + qty: number; +} diff --git a/src/modules/transaction/transaction/domain/entities/transaction-tax.entity.ts b/src/modules/transaction/transaction/domain/entities/transaction-tax.entity.ts new file mode 100644 index 0000000..a73ac6b --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/transaction-tax.entity.ts @@ -0,0 +1,7 @@ +import { BaseCoreEntity } from 'src/core/modules/domain/entities/base-core.entity'; + +export interface TransactionTaxEntity extends BaseCoreEntity { + tax_id: string; + tax_name: string; + taxt_value: number; +} diff --git a/src/modules/transaction/transaction/domain/entities/transaction.entity.ts b/src/modules/transaction/transaction/domain/entities/transaction.entity.ts new file mode 100644 index 0000000..f7fea17 --- /dev/null +++ b/src/modules/transaction/transaction/domain/entities/transaction.entity.ts @@ -0,0 +1,62 @@ +import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.entity'; +import { + TransactionPaymentType, + TransactionType, + TransactionUserType, +} from '../../constants'; + +export interface TransactionEntity extends BaseStatusEntity { + // general info + type: TransactionType; + invoice_code: string; + creator_counter_no: number; // nomor pos transaksi dibuat + + // season data + season_period_id: string; + season_period_name: string; + season_period_type_id: string; + season_period_type_name: string; + + // customer info + customer_category_id: string; + customer_category_name: string; + customer_type: TransactionUserType; + customer_name: string; + customer_phone: string; + customer_email: string; + customer_description: string; + no_of_group: number; + + booking_date: Date; // tnaggal untuk booking + settlement_date: Date; // tanggal status berubah menjadi settlement + invoice_date: Date; // tanggal invoice terkirim + + // discount data + discount_code_id: string; + discount_code: string; + discount_percentage: number; + discount_value: number; + + // payment data + payment_type: TransactionPaymentType; + payment_type_method_id: string; + payment_type_method_name: string; + payment_type_method_qr: string; + payment_card_information: string; + payment_code_reference: string; + payment_date: Date; + + // calculation data + payment_sub_total: number; // total invoice tanpa discount + payment_discount_total: number; // total discount + payment_total: number; // total invoice + payment_total_pay: number; // total pembayaran user + payment_change: number; // total kembalian + + // share and profit data + payment_total_share: number; // total share untuk para tenant + payment_total_tax: number; // total untuk tax + payment_total_profit: number; // total untuk profit perusahan + profit_share_formula: string; + sales_price_formula: string; +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts new file mode 100644 index 0000000..8287849 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/active-transaction.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 { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; + +@Injectable() +export class ActiveTransactionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.invoice_code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts new file mode 100644 index 0000000..48ad15c --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchActiveTransactionManager extends BaseBatchUpdateStatusManager { + validateData(data: TransactionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-transaction.manager.ts new file mode 100644 index 0000000..542348d --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-transaction.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchConfirmTransactionManager extends BaseBatchUpdateStatusManager { + validateData(data: TransactionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-delete-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-delete-transaction.manager.ts new file mode 100644 index 0000000..9e7510e --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-delete-transaction.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchDeleteManager } from 'src/core/modules/domain/usecase/managers/base-batch-delete.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionDeletedEvent } from '../../entities/event/transaction-deleted.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchDeleteTransactionManager extends BaseBatchDeleteManager { + async beforeProcess(): Promise { + return; + } + + async validateData(data: TransactionEntity): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionDeletedEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts new file mode 100644 index 0000000..010e827 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts @@ -0,0 +1,45 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class BatchInactiveTransactionManager extends BaseBatchUpdateStatusManager { + validateData(data: TransactionEntity): Promise { + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + }, + ]; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.manager.ts new file mode 100644 index 0000000..32e055b --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.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 { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; + +@Injectable() +export class ConfirmTransactionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.invoice_code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts new file mode 100644 index 0000000..39ae5e5 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@nestjs/common'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { BaseCreateManager } from 'src/core/modules/domain/usecase/managers/base-create.manager'; +import { TransactionCreatedEvent } from '../../entities/event/transaction-created.event'; +import { TransactionType } from '../../../constants'; + +@Injectable() +export class CreateTransactionManager extends BaseCreateManager { + async beforeProcess(): Promise { + Object.assign(this.data, { + type: TransactionType.ADMIN, + customer_category_id: this.data.customer_category?.id ?? null, + customer_category_name: this.data.customer_category?.name ?? null, + season_period_id: this.data.season_period?.id ?? null, + season_period_name: this.data.season_period?.holiday_name ?? null, + season_period_type_id: this.data.season_period?.season_type?.id ?? null, + season_period_type_name: + this.data.season_period?.season_type?.name ?? null, + }); + + this.data.items?.map((item) => { + Object.assign(item, { + item_id: item.item.id, + item_name: item.item.name, + item_type: item.item.item_type, + item_price: item.item.base_price, + item_tenant_id: item.item.tenant?.id ?? null, + item_tenant_name: item.item.tenant?.id ?? null, + item_tenant_percentage: item.item.tenant?.share_margin ?? null, + }); + }); + + console.log(this.data, 'data'); + throw new Error('das'); + + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionCreatedEvent, + data: this.data, + }, + ]; + } + + get entityTarget(): any { + return TransactionModel; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/delete-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/delete-transaction.manager.ts new file mode 100644 index 0000000..de6e3e6 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/delete-transaction.manager.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDeleteManager } from 'src/core/modules/domain/usecase/managers/base-delete.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionDeletedEvent } from '../../entities/event/transaction-deleted.event'; + +@Injectable() +export class DeleteTransactionManager 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 TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionDeletedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts new file mode 100644 index 0000000..16da999 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts @@ -0,0 +1,42 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class DetailTransactionManager 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 []; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts new file mode 100644 index 0000000..a7a54b1 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.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 { TransactionEntity } from '../../entities/transaction.entity'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionChangeStatusEvent } from '../../entities/event/transaction-change-status.event'; + +@Injectable() +export class InactiveTransactionManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success inactive data ${this.result.invoice_code}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionChangeStatusEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/index-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/index-transaction.manager.ts new file mode 100644 index 0000000..ec368f1 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/index-transaction.manager.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; + +@Injectable() +export class IndexTransactionManager 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 []; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.name`, + data: this.filterParam.names, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + return queryBuilder; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/managers/update-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/update-transaction.manager.ts new file mode 100644 index 0000000..db5f517 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/managers/update-transaction.manager.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; +import { TransactionEntity } from '../../entities/transaction.entity'; +import { TransactionModel } from '../../../data/models/transaction.model'; +import { TransactionUpdatedEvent } from '../../entities/event/transaction-updated.event'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; + +@Injectable() +export class UpdateTransactionManager 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 TransactionModel; + } + + get eventTopics(): EventTopics[] { + return [ + { + topic: TransactionUpdatedEvent, + data: this.data, + }, + ]; + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/transaction-data.orchestrator.ts b/src/modules/transaction/transaction/domain/usecases/transaction-data.orchestrator.ts new file mode 100644 index 0000000..6a6f71c --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/transaction-data.orchestrator.ts @@ -0,0 +1,118 @@ +import { Injectable } from '@nestjs/common'; +import { CreateTransactionManager } from './managers/create-transaction.manager'; +import { TransactionDataService } from '../../data/services/transaction-data.service'; +import { TransactionEntity } from '../entities/transaction.entity'; +import { DeleteTransactionManager } from './managers/delete-transaction.manager'; +import { UpdateTransactionManager } from './managers/update-transaction.manager'; +import { BaseDataTransactionOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-data-transaction.orchestrator'; +import { ActiveTransactionManager } from './managers/active-transaction.manager'; +import { InactiveTransactionManager } from './managers/inactive-transaction.manager'; +import { ConfirmTransactionManager } from './managers/confirm-transaction.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchConfirmTransactionManager } from './managers/batch-confirm-transaction.manager'; +import { BatchInactiveTransactionManager } from './managers/batch-inactive-transaction.manager'; +import { BatchActiveTransactionManager } from './managers/batch-active-transaction.manager'; +import { BatchDeleteTransactionManager } from './managers/batch-delete-transaction.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class TransactionDataOrchestrator extends BaseDataTransactionOrchestrator { + constructor( + private createManager: CreateTransactionManager, + private updateManager: UpdateTransactionManager, + private deleteManager: DeleteTransactionManager, + private activeManager: ActiveTransactionManager, + private confirmManager: ConfirmTransactionManager, + private inactiveManager: InactiveTransactionManager, + private batchDeleteManager: BatchDeleteTransactionManager, + private batchActiveManager: BatchActiveTransactionManager, + private batchConfirmManager: BatchConfirmTransactionManager, + private batchInactiveManager: BatchInactiveTransactionManager, + private serviceData: TransactionDataService, + ) { + super(); + } + + async create(data): Promise { + this.createManager.setData(data); + this.createManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + 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.TRANSACTION); + await this.updateManager.execute(); + return this.updateManager.getResult(); + } + + async delete(dataId): Promise { + this.deleteManager.setData(dataId); + this.deleteManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + await this.deleteManager.execute(); + return this.deleteManager.getResult(); + } + + async batchDelete(dataIds: string[]): Promise { + this.batchDeleteManager.setData(dataIds); + this.batchDeleteManager.setService( + this.serviceData, + TABLE_NAME.TRANSACTION, + ); + 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.TRANSACTION); + 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.TRANSACTION, + ); + 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.TRANSACTION); + 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.TRANSACTION, + ); + 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.TRANSACTION); + 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.TRANSACTION, + ); + await this.batchInactiveManager.execute(); + return this.batchInactiveManager.getResult(); + } +} diff --git a/src/modules/transaction/transaction/domain/usecases/transaction-read.orchestrator.ts b/src/modules/transaction/transaction/domain/usecases/transaction-read.orchestrator.ts new file mode 100644 index 0000000..4f39239 --- /dev/null +++ b/src/modules/transaction/transaction/domain/usecases/transaction-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexTransactionManager } from './managers/index-transaction.manager'; +import { TransactionReadService } from '../../data/services/transaction-read.service'; +import { TransactionEntity } from '../entities/transaction.entity'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailTransactionManager } from './managers/detail-transaction.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; + +@Injectable() +export class TransactionReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexTransactionManager, + private detailManager: DetailTransactionManager, + private serviceData: TransactionReadService, + ) { + super(); + } + + async index(params): Promise> { + this.indexManager.setFilterParam(params); + this.indexManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + await this.indexManager.execute(); + return this.indexManager.getResult(); + } + + async detail(dataId: string): Promise { + this.detailManager.setData(dataId); + this.detailManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + await this.detailManager.execute(); + return this.detailManager.getResult(); + } +} diff --git a/src/modules/transaction/transaction/index.ts b/src/modules/transaction/transaction/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts new file mode 100644 index 0000000..57ec65a --- /dev/null +++ b/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts @@ -0,0 +1,6 @@ +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterTransactionEntity } from '../../domain/entities/filter-transaction.entity'; + +export class FilterTransactionDto + extends BaseFilterDto + implements FilterTransactionEntity {} diff --git a/src/modules/transaction/transaction/infrastructure/dto/transaction-item.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/transaction-item.dto.ts new file mode 100644 index 0000000..4ccb047 --- /dev/null +++ b/src/modules/transaction/transaction/infrastructure/dto/transaction-item.dto.ts @@ -0,0 +1,39 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber, IsObject } from 'class-validator'; +import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity'; + +export class TransactionItemDto { + @ApiProperty({ + type: Object, + required: true, + example: { + id: 'uuid', + name: 'Bundling 1', + price: 10000, + hpp: 1000, + tenant: { + id: 'uuid', + name: 'tenant 1', + share_margin: 10, + }, + }, + }) + @IsObject() + item: ItemEntity; + + @ApiProperty({ + type: Number, + required: true, + example: 1, + }) + @IsNumber() + total_price: number; + + @ApiProperty({ + type: Number, + required: true, + example: 1, + }) + @IsNumber() + qty: number; +} diff --git a/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts new file mode 100644 index 0000000..60ae4d9 --- /dev/null +++ b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts @@ -0,0 +1,145 @@ +import { BaseStatusDto } from 'src/core/modules/infrastructure/dto/base-status.dto'; +import { TransactionUserType, TransactionPaymentType } from '../../constants'; +import { ApiProperty } from '@nestjs/swagger'; +import { + IsArray, + IsEmail, + IsNumber, + IsObject, + IsString, + ValidateIf, +} from 'class-validator'; +import { SeasonPeriodEntity } from 'src/modules/season-related/season-period/domain/entities/season-period.entity'; +import { TransactionItemEntity } from '../../domain/entities/transaction-item.entity'; +import { TransactionItemDto } from './transaction-item.dto'; + +export class TransactionDto extends BaseStatusDto { + @ApiProperty({ + type: Object, + required: false, + example: { + id: 'uuid', + season_type: { + id: 'uuid', + name: 'high season', + }, + }, + }) + @IsObject() + @ValidateIf((body) => body.season_period) + season_period: SeasonPeriodEntity; + + @ApiProperty({ + type: String, + required: true, + example: TransactionUserType.GROUP, + }) + @IsString() + customer_type: TransactionUserType; + + @ApiProperty({ + type: String, + required: true, + example: 'Andika', + }) + @IsString() + customer_name: string; + + @ApiProperty({ + type: String, + required: false, + example: '0823...', + }) + @ValidateIf((body) => body.customer_phone) + customer_phone: string; + + @ApiProperty({ required: false, example: 'andika@mail.com' }) + @IsEmail({ ignore_max_length: true }) + @ValidateIf((body) => body.customer_email) + customer_email: string; + + @ApiProperty({ + type: String, + required: false, + example: 'Influencer', + }) + @ValidateIf((body) => body.customer_description) + customer_description: string; + + @ApiProperty({ + type: Number, + required: true, + example: 1, + }) + @IsNumber() + no_of_group: number; + + @ApiProperty({ + type: Date, + required: true, + example: '2024-01-01', + }) + booking_date: Date; + + @ApiProperty({ + type: String, + required: false, + }) + @ValidateIf((body) => body.discount_code) + discount_code: string; + + @ApiProperty({ + type: Number, + required: false, + }) + @ValidateIf((body) => body.discount_percentage) + discount_percentage: number; + + @ApiProperty({ + type: Number, + required: false, + }) + @ValidateIf((body) => body.discount_value) + discount_value: number; + + @ApiProperty({ + type: String, + required: true, + example: TransactionPaymentType.MIDTRANS, + }) + @IsString() + payment_type: TransactionPaymentType; + + @ApiProperty({ + type: Number, + required: true, + example: 7000000, + }) + @IsNumber() + payment_sub_total: number; + + @ApiProperty({ + type: Number, + required: false, + example: 3500000, + }) + @IsNumber() + @ValidateIf((body) => body.payment_discount_total) + payment_discount_total: number; + + @ApiProperty({ + type: Number, + required: true, + example: 3500000, + }) + @IsNumber() + payment_total: number; + + @ApiProperty({ + type: [Object], + required: true, + example: TransactionItemDto, + }) + @IsArray() + items: TransactionItemEntity[]; +} diff --git a/src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts b/src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts new file mode 100644 index 0000000..9f841d8 --- /dev/null +++ b/src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts @@ -0,0 +1,78 @@ +import { + Body, + Controller, + Delete, + Param, + Patch, + Post, + Put, +} from '@nestjs/common'; +import { TransactionDataOrchestrator } from '../domain/usecases/transaction-data.orchestrator'; +import { TransactionDto } from './dto/transaction.dto'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { TransactionEntity } from '../domain/entities/transaction.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.TRANSACTION.split('-').join(' ')} - data`) +@Controller(`v1/${MODULE_NAME.TRANSACTION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class TransactionDataController { + constructor(private orchestrator: TransactionDataOrchestrator) {} + + @Post() + async create(@Body() data: TransactionDto): 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: TransactionDto, + ): 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/transaction/transaction/infrastructure/transaction-read.controller.ts b/src/modules/transaction/transaction/infrastructure/transaction-read.controller.ts new file mode 100644 index 0000000..099cc0d --- /dev/null +++ b/src/modules/transaction/transaction/infrastructure/transaction-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterTransactionDto } from './dto/filter-transaction.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { TransactionEntity } from '../domain/entities/transaction.entity'; +import { TransactionReadOrchestrator } from '../domain/usecases/transaction-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.TRANSACTION.split('-').join(' ')} - read`) +@Controller(`v1/${MODULE_NAME.TRANSACTION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class TransactionReadController { + constructor(private orchestrator: TransactionReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterTransactionDto, + ): 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/transaction/transaction/transaction.module.ts b/src/modules/transaction/transaction/transaction.module.ts new file mode 100644 index 0000000..f745821 --- /dev/null +++ b/src/modules/transaction/transaction/transaction.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 { TransactionDataService } from './data/services/transaction-data.service'; +import { TransactionReadService } from './data/services/transaction-read.service'; +import { TransactionReadController } from './infrastructure/transaction-read.controller'; +import { TransactionReadOrchestrator } from './domain/usecases/transaction-read.orchestrator'; +import { TransactionDataController } from './infrastructure/transaction-data.controller'; +import { TransactionDataOrchestrator } from './domain/usecases/transaction-data.orchestrator'; +import { CreateTransactionManager } from './domain/usecases/managers/create-transaction.manager'; +import { CqrsModule } from '@nestjs/cqrs'; +import { IndexTransactionManager } from './domain/usecases/managers/index-transaction.manager'; +import { DeleteTransactionManager } from './domain/usecases/managers/delete-transaction.manager'; +import { UpdateTransactionManager } from './domain/usecases/managers/update-transaction.manager'; +import { ActiveTransactionManager } from './domain/usecases/managers/active-transaction.manager'; +import { ConfirmTransactionManager } from './domain/usecases/managers/confirm-transaction.manager'; +import { InactiveTransactionManager } from './domain/usecases/managers/inactive-transaction.manager'; +import { DetailTransactionManager } from './domain/usecases/managers/detail-transaction.manager'; +import { BatchDeleteTransactionManager } from './domain/usecases/managers/batch-delete-transaction.manager'; +import { BatchActiveTransactionManager } from './domain/usecases/managers/batch-active-transaction.manager'; +import { BatchConfirmTransactionManager } from './domain/usecases/managers/batch-confirm-transaction.manager'; +import { BatchInactiveTransactionManager } from './domain/usecases/managers/batch-inactive-transaction.manager'; +import { TransactionModels } from './constants'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature(TransactionModels, CONNECTION_NAME.DEFAULT), + CqrsModule, + ], + controllers: [TransactionDataController, TransactionReadController], + providers: [ + IndexTransactionManager, + DetailTransactionManager, + CreateTransactionManager, + DeleteTransactionManager, + UpdateTransactionManager, + ActiveTransactionManager, + ConfirmTransactionManager, + InactiveTransactionManager, + BatchDeleteTransactionManager, + BatchActiveTransactionManager, + BatchConfirmTransactionManager, + BatchInactiveTransactionManager, + + TransactionDataService, + TransactionReadService, + + TransactionDataOrchestrator, + TransactionReadOrchestrator, + ], +}) +export class TransactionModule {}