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 1/6] 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 {} From a84a48c2923a19755d2bfa89c6a59d0227108799 Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah <98192542+Asharaswin@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:45:04 +0700 Subject: [PATCH 2/6] feat(SPG-394) REST API CU MDR --- .../transaction/reconciliation/constants.ts | 0 .../batch-cancel-reconciliation.manager.ts | 61 ++++++++++++++++++ .../batch-confirm-reconciliation.manager.ts | 53 +++++++++++++++ .../managers/cancel-reconciliation.manager.ts | 59 +++++++++++++++++ .../confirm-reconciliation.manager.ts | 46 +++++++++++++ .../managers/update-reconciliation.manager.ts | 51 +++++++++++++++ .../reconciliation-data.orchestrator.ts | 64 +++++++++++++++++++ .../transaction/reconciliation/index.ts | 0 .../infrastructure/dto/reconciliation.dto.ts | 17 +++++ .../reconciliation-data.controller.ts | 53 +++++++++++++++ .../reconciliation/reconciliation.module.ts | 44 +++++++++++++ 11 files changed, 448 insertions(+) create mode 100644 src/modules/transaction/reconciliation/constants.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/batch-cancel-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/batch-confirm-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/cancel-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/confirm-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/update-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/reconciliation-data.orchestrator.ts create mode 100644 src/modules/transaction/reconciliation/index.ts create mode 100644 src/modules/transaction/reconciliation/infrastructure/dto/reconciliation.dto.ts create mode 100644 src/modules/transaction/reconciliation/infrastructure/reconciliation-data.controller.ts create mode 100644 src/modules/transaction/reconciliation/reconciliation.module.ts diff --git a/src/modules/transaction/reconciliation/constants.ts b/src/modules/transaction/reconciliation/constants.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/batch-cancel-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/batch-cancel-reconciliation.manager.ts new file mode 100644 index 0000000..b70dd80 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/batch-cancel-reconciliation.manager.ts @@ -0,0 +1,61 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; + +@Injectable() +export class BatchCancelReconciliationManager extends BaseBatchUpdateStatusManager { + validateData(data: TransactionEntity): Promise { + Object.assign(data, { + reconciliation_mdr: this.data.reconciliation_mdr ?? null, + reconciliation_confirm_by: this.user.name, + reconciliation_confirm_date: new Date().getTime(), + status: this.dataStatus, + reconciliation_status: this.dataStatus, + payment_date: this.data.payment_date, + }); + + if (data.is_recap_transaction) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! cant cancel recap data`, + error: 'Unprocessable Entity', + }); + } + + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return []; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/batch-confirm-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/batch-confirm-reconciliation.manager.ts new file mode 100644 index 0000000..e074b10 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/batch-confirm-reconciliation.manager.ts @@ -0,0 +1,53 @@ +import { BaseBatchUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-batch-update-status.manager'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { Injectable } from '@nestjs/common'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; + +@Injectable() +export class BatchConfirmReconciliationManager extends BaseBatchUpdateStatusManager { + validateData(data: TransactionEntity): Promise { + const net_profit = data.reconciliation_mdr + ? Number(this.data.payment_total) - Number(this.data.reconciliation_mdr) + : null; + + Object.assign(data, { + reconciliation_mdr: this.data.reconciliation_mdr ?? null, + reconciliation_confirm_by: this.user.name, + reconciliation_confirm_date: new Date().getTime(), + status: this.oldData.status, + reconciliation_status: this.dataStatus, + payment_total_net_profit: net_profit, + payment_date: this.data.payment_date, + }); + return; + } + + beforeProcess(): Promise { + return; + } + + afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return []; + } + + getResult(): BatchResult { + return this.result; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/cancel-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/cancel-reconciliation.manager.ts new file mode 100644 index 0000000..8874667 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/cancel-reconciliation.manager.ts @@ -0,0 +1,59 @@ +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; + +@Injectable() +export class CancelReconciliationManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.id}`; + } + + async validateProcess(): Promise { + if (this.data.is_recap_transaction) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! cant cancel recap data`, + error: 'Unprocessable Entity', + }); + } + return; + } + + async beforeProcess(): Promise { + Object.assign(this.data, { + reconciliation_mdr: this.data.reconciliation_mdr ?? null, + reconciliation_confirm_by: this.user.name, + reconciliation_confirm_date: new Date().getTime(), + status: this.dataStatus, + reconciliation_status: this.dataStatus, + payment_date: this.data.payment_date, + }); + + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return []; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/confirm-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/confirm-reconciliation.manager.ts new file mode 100644 index 0000000..bca70d8 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/confirm-reconciliation.manager.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; +import { + EventTopics, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; + +@Injectable() +export class ConfirmReconciliationManager extends BaseUpdateStatusManager { + getResult(): string { + return `Success active data ${this.result.id}`; + } + + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + Object.assign(this.data, { + reconciliation_confirm_by: this.user.name, + reconciliation_confirm_date: new Date().getTime(), + status: this.oldData.status, + reconciliation_status: this.dataStatus, + }); + + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return []; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/update-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/update-reconciliation.manager.ts new file mode 100644 index 0000000..3c30fc1 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/update-reconciliation.manager.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@nestjs/common'; +import { BaseUpdateManager } from 'src/core/modules/domain/usecase/managers/base-update.manager'; +import { + EventTopics, + columnUniques, + validateRelations, +} from 'src/core/strings/constants/interface.constants'; +import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; + +@Injectable() +export class UpdateReconciliationManager extends BaseUpdateManager { + async validateProcess(): Promise { + return; + } + + async beforeProcess(): Promise { + const net_profit = this.data.reconciliation_mdr + ? Number(this.oldData.payment_total) - + Number(this.data.reconciliation_mdr) + : null; + + Object.assign(this.data, { + reconciliation_mdr: this.data.reconciliation_mdr ?? null, + payment_total_net_profit: net_profit, + payment_date: this.data.payment_date ?? this.oldData.payment_total, + }); + + return; + } + + async afterProcess(): Promise { + return; + } + + get validateRelations(): validateRelations[] { + return []; + } + + get uniqueColumns(): columnUniques[] { + return []; + } + + get entityTarget(): any { + return TransactionModel; + } + + get eventTopics(): EventTopics[] { + return []; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/reconciliation-data.orchestrator.ts b/src/modules/transaction/reconciliation/domain/usecases/reconciliation-data.orchestrator.ts new file mode 100644 index 0000000..34bf1a6 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/reconciliation-data.orchestrator.ts @@ -0,0 +1,64 @@ +import { Injectable } from '@nestjs/common'; +import { UpdateReconciliationManager } from './managers/update-reconciliation.manager'; +import { ConfirmReconciliationManager } from './managers/confirm-reconciliation.manager'; +import { STATUS } from 'src/core/strings/constants/base.constants'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchConfirmReconciliationManager } from './managers/batch-confirm-reconciliation.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { CancelReconciliationManager } from './managers/cancel-reconciliation.manager'; +import { BatchCancelReconciliationManager } from './managers/batch-cancel-reconciliation.manager'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { TransactionDataService } from 'src/modules/transaction/transaction/data/services/transaction-data.service'; + +@Injectable() +export class ReconciliationDataOrchestrator { + constructor( + private updateManager: UpdateReconciliationManager, + private confirmManager: ConfirmReconciliationManager, + private cancelManager: CancelReconciliationManager, + private batchConfirmManager: BatchConfirmReconciliationManager, + private batchCancelManager: BatchCancelReconciliationManager, + private serviceData: TransactionDataService, + ) {} + + 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 confirm(dataId): Promise { + this.confirmManager.setData(dataId, STATUS.CONFIRMED); + 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.CONFIRMED); + this.batchConfirmManager.setService( + this.serviceData, + TABLE_NAME.TRANSACTION, + ); + await this.batchConfirmManager.execute(); + return this.batchConfirmManager.getResult(); + } + + async cancel(dataId): Promise { + this.cancelManager.setData(dataId, STATUS.REJECTED); + this.cancelManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + await this.cancelManager.execute(); + return this.cancelManager.getResult(); + } + + async batchCancel(dataIds: string[]): Promise { + this.batchCancelManager.setData(dataIds, STATUS.REJECTED); + this.batchCancelManager.setService( + this.serviceData, + TABLE_NAME.TRANSACTION, + ); + await this.batchCancelManager.execute(); + return this.batchCancelManager.getResult(); + } +} diff --git a/src/modules/transaction/reconciliation/index.ts b/src/modules/transaction/reconciliation/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/transaction/reconciliation/infrastructure/dto/reconciliation.dto.ts b/src/modules/transaction/reconciliation/infrastructure/dto/reconciliation.dto.ts new file mode 100644 index 0000000..a8226e8 --- /dev/null +++ b/src/modules/transaction/reconciliation/infrastructure/dto/reconciliation.dto.ts @@ -0,0 +1,17 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class UpdateReconciliationDto { + @ApiProperty({ + type: Date, + required: true, + example: '2024/06/06', + }) + payment_date: Date; + + @ApiProperty({ + type: Number, + required: false, + example: 350000, + }) + reconciliation_mdr: number; +} diff --git a/src/modules/transaction/reconciliation/infrastructure/reconciliation-data.controller.ts b/src/modules/transaction/reconciliation/infrastructure/reconciliation-data.controller.ts new file mode 100644 index 0000000..00c87c0 --- /dev/null +++ b/src/modules/transaction/reconciliation/infrastructure/reconciliation-data.controller.ts @@ -0,0 +1,53 @@ +import { + Body, + Controller, + Delete, + Param, + Patch, + Post, + Put, +} from '@nestjs/common'; +import { ReconciliationDataOrchestrator } from '../domain/usecases/reconciliation-data.orchestrator'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { BatchResult } from 'src/core/response/domain/ok-response.interface'; +import { BatchIdsDto } from 'src/core/modules/infrastructure/dto/base-batch.dto'; +import { Public } from 'src/core/guards'; +import { TransactionEntity } from '../../transaction/domain/entities/transaction.entity'; +import { UpdateReconciliationDto } from './dto/reconciliation.dto'; + +@ApiTags(`${MODULE_NAME.RECONCILIATION.split('-').join(' ')} - data`) +@Controller(`v1/${MODULE_NAME.RECONCILIATION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class ReconciliationDataController { + constructor(private orchestrator: ReconciliationDataOrchestrator) {} + + @Put('/batch-confirm') + async batchConfirm(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchConfirm(body.ids); + } + + @Patch(':id/confirm') + async confirm(@Param('id') dataId: string): Promise { + return await this.orchestrator.confirm(dataId); + } + + @Patch(':id/cancel') + async cancel(@Param('id') dataId: string): Promise { + return await this.orchestrator.cancel(dataId); + } + + @Put('/batch-cancel') + async batchCancel(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchCancel(body.ids); + } + + @Put(':id') + async update( + @Param('id') dataId: string, + @Body() data: UpdateReconciliationDto, + ): Promise { + return await this.orchestrator.update(dataId, data); + } +} diff --git a/src/modules/transaction/reconciliation/reconciliation.module.ts b/src/modules/transaction/reconciliation/reconciliation.module.ts new file mode 100644 index 0000000..7b8d1e0 --- /dev/null +++ b/src/modules/transaction/reconciliation/reconciliation.module.ts @@ -0,0 +1,44 @@ +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 { ReconciliationReadController } from './infrastructure/reconciliation-read.controller'; +import { ReconciliationReadOrchestrator } from './domain/usecases/reconciliation-read.orchestrator'; +import { ReconciliationDataController } from './infrastructure/reconciliation-data.controller'; +import { ReconciliationDataOrchestrator } from './domain/usecases/reconciliation-data.orchestrator'; +import { CqrsModule } from '@nestjs/cqrs'; +import { IndexReconciliationManager } from './domain/usecases/managers/index-reconciliation.manager'; +import { UpdateReconciliationManager } from './domain/usecases/managers/update-reconciliation.manager'; +import { ConfirmReconciliationManager } from './domain/usecases/managers/confirm-reconciliation.manager'; +import { DetailReconciliationManager } from './domain/usecases/managers/detail-reconciliation.manager'; +import { TransactionModel } from '../transaction/data/models/transaction.model'; +import { TransactionDataService } from '../transaction/data/services/transaction-data.service'; +import { TransactionReadService } from '../transaction/data/services/transaction-read.service'; +import { CancelReconciliationManager } from './domain/usecases/managers/cancel-reconciliation.manager'; +import { BatchCancelReconciliationManager } from './domain/usecases/managers/batch-cancel-reconciliation.manager'; +import { BatchConfirmReconciliationManager } from './domain/usecases/managers/batch-confirm-reconciliation.manager'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature([TransactionModel], CONNECTION_NAME.DEFAULT), + CqrsModule, + ], + controllers: [ReconciliationDataController, ReconciliationReadController], + providers: [ + IndexReconciliationManager, + DetailReconciliationManager, + UpdateReconciliationManager, + ConfirmReconciliationManager, + BatchConfirmReconciliationManager, + CancelReconciliationManager, + BatchCancelReconciliationManager, + + TransactionDataService, + TransactionReadService, + + ReconciliationDataOrchestrator, + ReconciliationReadOrchestrator, + ], +}) +export class ReconciliationModule {} From db005426bdba6aa15b4f541b271c9af528aab147 Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah <98192542+Asharaswin@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:45:51 +0700 Subject: [PATCH 3/6] feat(SPG-395) REST API Read Rekonsiliasi --- .../managers/detail-reconciliation.manager.ts | 55 +++++++ .../managers/index-reconciliation.manager.ts | 151 ++++++++++++++++++ .../reconciliation-read.orchestrator.ts | 33 ++++ .../dto/filter-reconciliation.dto.ts | 60 +++++++ .../reconciliation-read.controller.ts | 30 ++++ 5 files changed, 329 insertions(+) create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/detail-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/managers/index-reconciliation.manager.ts create mode 100644 src/modules/transaction/reconciliation/domain/usecases/reconciliation-read.orchestrator.ts create mode 100644 src/modules/transaction/reconciliation/infrastructure/dto/filter-reconciliation.dto.ts create mode 100644 src/modules/transaction/reconciliation/infrastructure/reconciliation-read.controller.ts diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/detail-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/detail-reconciliation.manager.ts new file mode 100644 index 0000000..2598647 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/detail-reconciliation.manager.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@nestjs/common'; +import { BaseDetailManager } from 'src/core/modules/domain/usecase/managers/base-detail.manager'; +import { RelationParam } from 'src/core/modules/domain/entities/base-filter.entity'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; + +@Injectable() +export class DetailReconciliationManager 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}.reconciliation_mdr`, + + `${this.tableName}.payment_type`, + `${this.tableName}.payment_type_method_id`, + `${this.tableName}.payment_type_method_name`, + `${this.tableName}.payment_type_method_number`, + `${this.tableName}.payment_code_reference`, + `${this.tableName}.payment_date`, + + `${this.tableName}.payment_total`, + `${this.tableName}.payment_total_net_profit`, + ]; + } + + get setFindProperties(): any { + return { + id: this.dataId, + }; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/managers/index-reconciliation.manager.ts b/src/modules/transaction/reconciliation/domain/usecases/managers/index-reconciliation.manager.ts new file mode 100644 index 0000000..6fc6ec5 --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/managers/index-reconciliation.manager.ts @@ -0,0 +1,151 @@ +import { Injectable } from '@nestjs/common'; +import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager'; +import { SelectQueryBuilder } from 'typeorm'; +import { + Param, + RelationParam, +} from 'src/core/modules/domain/entities/base-filter.entity'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { BetweenQueryHelper } from 'src/core/helpers/query/between-query.helper'; + +@Injectable() +export class IndexReconciliationManager 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}.type`, + `${this.tableName}.reconciliation_status`, + `${this.tableName}.reconciliation_mdr`, + `${this.tableName}.reconciliation_confirm_date`, + `${this.tableName}.reconciliation_confirm_by`, + + `${this.tableName}.customer_name`, + + `${this.tableName}.payment_type`, + `${this.tableName}.payment_type_method_id`, + `${this.tableName}.payment_type_method_name`, + `${this.tableName}.payment_type_method_number`, + `${this.tableName}.payment_code_reference`, + `${this.tableName}.payment_date`, + + `${this.tableName}.payment_total`, + `${this.tableName}.payment_total_net_profit`, + ]; + } + + get specificFilter(): Param[] { + return [ + { + cols: `${this.tableName}.customer_name`, + data: this.filterParam.customer_names, + }, + { + cols: `${this.tableName}.reconciliation_confirm_by`, + data: this.filterParam.confirm_by_names, + }, + { + cols: `${this.tableName}.payment_type_method_name`, + data: this.filterParam.payment_banks, + }, + { + cols: `${this.tableName}.payment_type_method_number`, + data: this.filterParam.payment_bank_numbers, + }, + ]; + } + + setQueryFilter( + queryBuilder: SelectQueryBuilder, + ): SelectQueryBuilder { + if (this.filterParam.payment_date_from) { + new BetweenQueryHelper( + queryBuilder, + this.tableName, + 'payment_date', + this.filterParam.payment_date_from, + this.filterParam.payment_date_to, + 'payment_created', + ).getQuery(); + } + + if (this.filterParam.transaction_type) { + queryBuilder.andWhere(`${this.tableName}.type In (:...types)`, { + types: [this.filterParam.transaction_type], + }); + } + + if (this.filterParam.couner_no) { + queryBuilder.andWhere( + `${this.tableName}.creator_counter_no In (:...counters)`, + { + counters: [this.filterParam.couner_no], + }, + ); + } + + if (this.filterParam.payment_type) { + queryBuilder.andWhere( + `${this.tableName}.creator_counter_no In (:...counters)`, + { + counters: [this.filterParam.couner_no], + }, + ); + } + + if (this.filterParam.payment_via) { + queryBuilder.andWhere(`${this.tableName}.payment_type In (:...type)`, { + type: [this.filterParam.payment_via], + }); + } + + if (this.filterParam.payment_bank) { + queryBuilder.andWhere( + `${this.tableName}.payment_type_method_name In (:...banks)`, + { + banks: [this.filterParam.payment_bank], + }, + ); + } + + if (this.filterParam.confirmation_date_from) { + new BetweenQueryHelper( + queryBuilder, + this.tableName, + 'payment_date', + this.filterParam.confirmation_date_from, + this.filterParam.confirmation_date_to, + 'payment_created', + ).getQuery(); + } + + queryBuilder.andWhere( + `${this.tableName}.reconciliation_status Is Not Null`, + ); + return queryBuilder; + } +} diff --git a/src/modules/transaction/reconciliation/domain/usecases/reconciliation-read.orchestrator.ts b/src/modules/transaction/reconciliation/domain/usecases/reconciliation-read.orchestrator.ts new file mode 100644 index 0000000..c5372dc --- /dev/null +++ b/src/modules/transaction/reconciliation/domain/usecases/reconciliation-read.orchestrator.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { IndexReconciliationManager } from './managers/index-reconciliation.manager'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator'; +import { DetailReconciliationManager } from './managers/detail-reconciliation.manager'; +import { TABLE_NAME } from 'src/core/strings/constants/table.constants'; +import { TransactionEntity } from 'src/modules/transaction/transaction/domain/entities/transaction.entity'; +import { TransactionReadService } from 'src/modules/transaction/transaction/data/services/transaction-read.service'; + +@Injectable() +export class ReconciliationReadOrchestrator extends BaseReadOrchestrator { + constructor( + private indexManager: IndexReconciliationManager, + private detailManager: DetailReconciliationManager, + 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/reconciliation/infrastructure/dto/filter-reconciliation.dto.ts b/src/modules/transaction/reconciliation/infrastructure/dto/filter-reconciliation.dto.ts new file mode 100644 index 0000000..c9b6c2e --- /dev/null +++ b/src/modules/transaction/reconciliation/infrastructure/dto/filter-reconciliation.dto.ts @@ -0,0 +1,60 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; +import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; +import { FilterTransactionEntity } from 'src/modules/transaction/transaction/domain/entities/filter-transaction.entity'; + +export class FilterReconciliationDto + extends BaseFilterDto + implements FilterTransactionEntity +{ + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + customer_names: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + confirm_by_names: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + payment_banks: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + payment_bank_numbers: string[]; + + @ApiProperty({ type: Date, required: false }) + payment_date_from: Date; + + @ApiProperty({ type: Date, required: false }) + payment_date_to: Date; + + @ApiProperty({ type: Number, required: false }) + couner_no: number; + + @ApiProperty({ type: String, required: false }) + payment_type: string; + + @ApiProperty({ type: Date, required: false }) + confirmation_date_from: Date; + + @ApiProperty({ type: Date, required: false }) + confirmation_date_to: Date; + + @ApiProperty({ type: String, required: false }) + transaction_type: string; + + @ApiProperty({ type: String, required: false }) + payment_via: string; + + @ApiProperty({ type: String, required: false }) + payment_bank: string; +} diff --git a/src/modules/transaction/reconciliation/infrastructure/reconciliation-read.controller.ts b/src/modules/transaction/reconciliation/infrastructure/reconciliation-read.controller.ts new file mode 100644 index 0000000..4b3f1fb --- /dev/null +++ b/src/modules/transaction/reconciliation/infrastructure/reconciliation-read.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param, Query } from '@nestjs/common'; +import { FilterReconciliationDto } from './dto/filter-reconciliation.dto'; +import { Pagination } from 'src/core/response'; +import { PaginationResponse } from 'src/core/response/domain/ok-response.interface'; +import { ReconciliationReadOrchestrator } from '../domain/usecases/reconciliation-read.orchestrator'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { MODULE_NAME } from 'src/core/strings/constants/module.constants'; +import { Public } from 'src/core/guards'; +import { TransactionEntity } from '../../transaction/domain/entities/transaction.entity'; + +@ApiTags(`${MODULE_NAME.RECONCILIATION.split('-').join(' ')} - read`) +@Controller(`v1/${MODULE_NAME.RECONCILIATION}`) +@Public(false) +@ApiBearerAuth('JWT') +export class ReconciliationReadController { + constructor(private orchestrator: ReconciliationReadOrchestrator) {} + + @Get() + @Pagination() + async index( + @Query() params: FilterReconciliationDto, + ): Promise> { + return await this.orchestrator.index(params); + } + + @Get(':id') + async detail(@Param('id') id: string): Promise { + return await this.orchestrator.detail(id); + } +} From 36d430484e0dc5eea8d565e9952b1a4cbab3f168 Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah <98192542+Asharaswin@users.noreply.github.com> Date: Tue, 2 Jul 2024 23:12:55 +0700 Subject: [PATCH 4/6] feat(SPG-383) REST API CUD Booking/Pemesanan --- src/app.module.ts | 12 ++- .../base-batch-update-status.manager.ts | 25 ++++--- .../strings/constants/module.constants.ts | 2 + src/core/strings/constants/table.constants.ts | 3 + ...54657-add-column-priority-season-period.ts | 25 ++++--- ...90145-add-reconciliation-to-transaction.ts | 61 +++++++++++++++ .../1719934464407-update-table-transaction.ts | 71 ++++++++++++++++++ .../data/models/transaction-item.model.ts | 12 +++ .../data/models/transaction.model.ts | 45 ++++++++++- .../entities/transaction-item.entity.ts | 4 + .../domain/entities/transaction.entity.ts | 16 ++++ ...ts => batch-cancel-transaction.manager.ts} | 17 ++++- ...batch-confirm-data-transaction.manager.ts} | 17 ++++- ...nager.ts => cancel-transaction.manager.ts} | 20 ++++- ...ts => confirm-data-transaction.manager.ts} | 31 +++++++- .../managers/confirm-transaction.manager.ts | 18 ++++- .../managers/create-transaction.manager.ts | 3 - .../usecases/transaction-data.orchestrator.ts | 74 +++++++++---------- .../infrastructure/dto/transaction.dto.ts | 29 +++++++- .../transaction-data.controller.ts | 24 +++--- .../transaction/transaction.module.ts | 25 ++++--- 21 files changed, 437 insertions(+), 97 deletions(-) create mode 100644 src/database/migrations/1719925690145-add-reconciliation-to-transaction.ts create mode 100644 src/database/migrations/1719934464407-update-table-transaction.ts rename src/modules/transaction/transaction/domain/usecases/managers/{batch-active-transaction.manager.ts => batch-cancel-transaction.manager.ts} (66%) rename src/modules/transaction/transaction/domain/usecases/managers/{batch-inactive-transaction.manager.ts => batch-confirm-data-transaction.manager.ts} (65%) rename src/modules/transaction/transaction/domain/usecases/managers/{active-transaction.manager.ts => cancel-transaction.manager.ts} (59%) rename src/modules/transaction/transaction/domain/usecases/managers/{inactive-transaction.manager.ts => confirm-data-transaction.manager.ts} (51%) diff --git a/src/app.module.ts b/src/app.module.ts index 92ce21d..3e1dba0 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -43,7 +43,10 @@ import { ItemRateModule } from './modules/item-related/item-rate/item-rate.modul 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'; +import { TransactionModel } from './modules/transaction/transaction/data/models/transaction.model'; +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'; @Module({ imports: [ @@ -71,7 +74,9 @@ import { TransactionModels } from './modules/transaction/transaction/constants'; SeasonPeriodModel, SeasonTypeModel, TaxModel, - ...TransactionModels, + TransactionModel, + TransactionItemModel, + TransactionTaxModel, UserModel, VipCategoryModel, VipCodeModel, @@ -99,6 +104,7 @@ import { TransactionModels } from './modules/transaction/transaction/constants'; // transaction PaymentMethodModule, ProfitShareFormulaModule, + ReconciliationModule, SalesPriceFormulaModule, TaxModule, TransactionModule, @@ -139,4 +145,4 @@ import { TransactionModels } from './modules/transaction/transaction/constants'; }, ], }) -export class AppModule {} +export class AppModule { } diff --git a/src/core/modules/domain/usecase/managers/base-batch-update-status.manager.ts b/src/core/modules/domain/usecase/managers/base-batch-update-status.manager.ts index dc91982..670e398 100644 --- a/src/core/modules/domain/usecase/managers/base-batch-update-status.manager.ts +++ b/src/core/modules/domain/usecase/managers/base-batch-update-status.manager.ts @@ -4,11 +4,13 @@ import { HttpStatus, NotFoundException } from '@nestjs/common'; import { OPERATION, STATUS } from 'src/core/strings/constants/base.constants'; import { ValidateRelationHelper } from 'src/core/helpers/validation/validate-relation.helper'; import { RecordLog } from 'src/modules/configuration/log/domain/entities/log.event'; +import * as _ from 'lodash'; export abstract class BaseBatchUpdateStatusManager extends BaseManager { protected dataIds: string[]; protected result: BatchResult; protected dataStatus: STATUS; + protected oldData: Entity; abstract get entityTarget(): any; setData(ids: string[], status: STATUS): void { @@ -40,10 +42,17 @@ export abstract class BaseBatchUpdateStatusManager extends BaseManager { if (!entity) { throw new NotFoundException({ statusCode: HttpStatus.NOT_FOUND, - message: `Failed! Entity with id ${ id } not found`, + message: `Failed! Entity with id ${id} not found`, error: 'Entity Not Found', }); } + this.oldData = _.cloneDeep(entity); + Object.assign(entity, { + status: this.dataStatus, + editor_id: this.user.id, + editor_name: this.user.name, + updated_at: new Date().getTime(), + }); await this.validateData(entity); await new ValidateRelationHelper( @@ -57,15 +66,10 @@ export abstract class BaseBatchUpdateStatusManager extends BaseManager { this.queryRunner, this.entityTarget, { id: id }, - { - status: this.dataStatus, - editor_id: this.user.id, - editor_name: this.user.name, - updated_at: new Date().getTime(), - }, + entity, ); - this.publishEvents(entity, result); + this.publishEvents(this.oldData, result); totalSuccess = totalSuccess + 1; } catch (error) { @@ -92,7 +96,7 @@ export abstract class BaseBatchUpdateStatusManager extends BaseManager { old: dataOld, data: dataNew, user: this.user, - description: `${ this.user.name } update batch data ${ this.tableName }`, + description: `${this.user.name} update batch data ${this.tableName}`, module: this.tableName, op: OPERATION.UPDATE, }), @@ -100,7 +104,6 @@ export abstract class BaseBatchUpdateStatusManager extends BaseManager { if (!this.eventTopics.length) return; for (const topic of this.eventTopics) { - let data; if (!topic.relations) { data = await this.dataService.getOneByOptions({ @@ -108,7 +111,7 @@ export abstract class BaseBatchUpdateStatusManager extends BaseManager { id: dataNew.id, }, relations: topic.relations, - }) + }); } this.eventBus.publishAll([ diff --git a/src/core/strings/constants/module.constants.ts b/src/core/strings/constants/module.constants.ts index ccc5889..77e6def 100644 --- a/src/core/strings/constants/module.constants.ts +++ b/src/core/strings/constants/module.constants.ts @@ -3,10 +3,12 @@ export enum MODULE_NAME { ITEM_CATEGORY = 'item-categories', ITEM_RATE = 'item-rates', PAYMENT_METHOD = 'payment-methods', + RECONCILIATION = 'reconciliations', SEASON_TYPE = 'season-types', SEASON_PERIOD = 'season-periods', TAX = 'taxes', TENANT = 'tenants', + TRANSACTION = 'transactions', USER = 'users', USER_PRIVILEGE = 'user-privileges', USER_PRIVILEGE_CONFIGURATION = 'user-privilege-configurations', diff --git a/src/core/strings/constants/table.constants.ts b/src/core/strings/constants/table.constants.ts index 53aa6bb..f803516 100644 --- a/src/core/strings/constants/table.constants.ts +++ b/src/core/strings/constants/table.constants.ts @@ -10,6 +10,9 @@ export enum TABLE_NAME { SEASON_PERIOD = 'season_periods', TAX = 'taxes', TENANT = 'tenants', + TRANSACTION = 'transactions', + TRANSACTION_ITEM = 'transaction_items', + TRANSACTION_TAX = 'transaction_taxes', USER = 'users', USER_PRIVILEGE = 'user_privileges', USER_PRIVILEGE_CONFIGURATION = 'user_privilege_configurations', diff --git a/src/database/migrations/1719227554657-add-column-priority-season-period.ts b/src/database/migrations/1719227554657-add-column-priority-season-period.ts index 711e155..f80b55a 100644 --- a/src/database/migrations/1719227554657-add-column-priority-season-period.ts +++ b/src/database/migrations/1719227554657-add-column-priority-season-period.ts @@ -1,14 +1,19 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm'; -export class AddColumnPrioritySeasonPeriod1719227554657 implements MigrationInterface { - name = 'AddColumnPrioritySeasonPeriod1719227554657' +export class AddColumnPrioritySeasonPeriod1719227554657 + implements MigrationInterface +{ + name = 'AddColumnPrioritySeasonPeriod1719227554657'; - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "season_periods" ADD "priority" integer NOT NULL DEFAULT '3'`); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "season_periods" DROP COLUMN "priority"`); - } + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "season_periods" ADD "priority" integer NOT NULL DEFAULT '3'`, + ); + } + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "season_periods" DROP COLUMN "priority"`, + ); + } } diff --git a/src/database/migrations/1719925690145-add-reconciliation-to-transaction.ts b/src/database/migrations/1719925690145-add-reconciliation-to-transaction.ts new file mode 100644 index 0000000..7914ef1 --- /dev/null +++ b/src/database/migrations/1719925690145-add-reconciliation-to-transaction.ts @@ -0,0 +1,61 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddReconciliationToTransaction1719925690145 + implements MigrationInterface +{ + name = 'AddReconciliationToTransaction1719925690145'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "transactions" ADD "is_recap_transaction" boolean NOT NULL DEFAULT true`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "payment_type_method_number" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "reconciliation_mdr" numeric`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_reconciliation_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "reconciliation_status" "public"."transactions_reconciliation_status_enum" NOT NULL DEFAULT 'draft'`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "reconciliation_confirm_date" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "reconciliation_confirm_by" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "payment_total_net_profit" numeric`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "payment_total_net_profit"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "reconciliation_confirm_by"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "reconciliation_confirm_date"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "reconciliation_status"`, + ); + await queryRunner.query( + `DROP TYPE "public"."transactions_reconciliation_status_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "reconciliation_mdr"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "payment_type_method_number"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "is_recap_transaction"`, + ); + } +} diff --git a/src/database/migrations/1719934464407-update-table-transaction.ts b/src/database/migrations/1719934464407-update-table-transaction.ts new file mode 100644 index 0000000..cbf38d9 --- /dev/null +++ b/src/database/migrations/1719934464407-update-table-transaction.ts @@ -0,0 +1,71 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class UpdateTableTransaction1719934464407 implements MigrationInterface { + name = 'UpdateTableTransaction1719934464407'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "transaction_items" ADD "item_hpp" bigint`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" ADD "item_category_id" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" ADD "item_category_name" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" ADD "item_bundlings" json`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_sending_invoice_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "sending_invoice_status" "public"."transactions_sending_invoice_status_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "sending_invoice_at" bigint`, + ); + await queryRunner.query( + `CREATE TYPE "public"."transactions_sending_qr_status_enum" AS ENUM('active', 'cancel', 'confirmed', 'draft', 'expired', 'inactive', 'pending', 'refunded', 'rejected', 'settled', 'waiting')`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "sending_qr_status" "public"."transactions_sending_qr_status_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" ADD "sending_qr_at" bigint`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "sending_qr_at"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "sending_qr_status"`, + ); + await queryRunner.query( + `DROP TYPE "public"."transactions_sending_qr_status_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "sending_invoice_at"`, + ); + await queryRunner.query( + `ALTER TABLE "transactions" DROP COLUMN "sending_invoice_status"`, + ); + await queryRunner.query( + `DROP TYPE "public"."transactions_sending_invoice_status_enum"`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" DROP COLUMN "item_bundlings"`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" DROP COLUMN "item_category_name"`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" DROP COLUMN "item_category_id"`, + ); + await queryRunner.query( + `ALTER TABLE "transaction_items" DROP COLUMN "item_hpp"`, + ); + } +} diff --git a/src/modules/transaction/transaction/data/models/transaction-item.model.ts b/src/modules/transaction/transaction/data/models/transaction-item.model.ts index a328ecd..68bfd21 100644 --- a/src/modules/transaction/transaction/data/models/transaction-item.model.ts +++ b/src/modules/transaction/transaction/data/models/transaction-item.model.ts @@ -22,6 +22,18 @@ export class TransactionItemModel @Column('bigint', { name: 'item_price', nullable: true }) item_price: number; + @Column('bigint', { name: 'item_hpp', nullable: true }) + item_hpp: number; + + @Column('varchar', { name: 'item_category_id', nullable: true }) + item_category_id: string; + + @Column('varchar', { name: 'item_category_name', nullable: true }) + item_category_name: string; + + @Column('json', { name: 'item_bundlings', nullable: true }) + item_bundlings: string; + // item tenant data @Column('varchar', { name: 'item_tenant_id', nullable: true }) item_tenant_id: string; diff --git a/src/modules/transaction/transaction/data/models/transaction.model.ts b/src/modules/transaction/transaction/data/models/transaction.model.ts index dd9194a..126731a 100644 --- a/src/modules/transaction/transaction/data/models/transaction.model.ts +++ b/src/modules/transaction/transaction/data/models/transaction.model.ts @@ -10,6 +10,7 @@ import { import { TransactionItemEntity } from '../../domain/entities/transaction-item.entity'; import { TransactionItemModel } from './transaction-item.model'; import { TransactionTaxModel } from './transaction-tax.model'; +import { STATUS } from 'src/core/strings/constants/base.constants'; @Entity(TABLE_NAME.TRANSACTION) export class TransactionModel @@ -17,6 +18,9 @@ export class TransactionModel implements TransactionEntity { // general info + @Column('bool', { name: 'is_recap_transaction', default: true }) + is_recap_transaction: boolean; + @Column('enum', { name: 'type', enum: TransactionType, @@ -108,6 +112,9 @@ export class TransactionModel @Column('varchar', { name: 'payment_type_method_name', nullable: true }) payment_type_method_name: string; + @Column('varchar', { name: 'payment_type_method_number', nullable: true }) + payment_type_method_number: string; + @Column('varchar', { name: 'payment_type_method_qr', nullable: true }) payment_type_method_qr: string; @@ -121,7 +128,6 @@ export class TransactionModel payment_date: Date; // calculation data - @Column('decimal', { name: 'payment_sub_total', nullable: true }) payment_sub_total: number; @@ -153,6 +159,43 @@ export class TransactionModel @Column('varchar', { name: 'sales_price_formula', nullable: true }) sales_price_formula: string; + // mdr + @Column('decimal', { name: 'reconciliation_mdr', nullable: true }) + reconciliation_mdr: number; + + @Column('enum', { + name: 'reconciliation_status', + enum: STATUS, + default: STATUS.DRAFT, + }) + reconciliation_status: STATUS; + + @Column('varchar', { name: 'reconciliation_confirm_date', nullable: true }) + reconciliation_confirm_date: string; + + @Column('varchar', { name: 'reconciliation_confirm_by', nullable: true }) + reconciliation_confirm_by: string; + + @Column('decimal', { name: 'payment_total_net_profit', nullable: true }) + payment_total_net_profit: number; + + // sending data + @Column('enum', { + name: 'sending_invoice_status', + enum: STATUS, + nullable: true, + }) + sending_invoice_status: STATUS; + + @Column({ name: 'sending_invoice_at', type: 'bigint', nullable: true }) + sending_invoice_at: number; + + @Column('enum', { name: 'sending_qr_status', enum: STATUS, nullable: true }) + sending_qr_status: STATUS; + + @Column({ name: 'sending_qr_at', type: 'bigint', nullable: true }) + sending_qr_at: number; + // relations to item @OneToMany(() => TransactionItemModel, (model) => model.transaction, { cascade: true, diff --git a/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts b/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts index a1313ad..1a638d2 100644 --- a/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts +++ b/src/modules/transaction/transaction/domain/entities/transaction-item.entity.ts @@ -6,6 +6,10 @@ export interface TransactionItemEntity extends BaseCoreEntity { item_name: string; item_type: string; item_price: number; + item_hpp: number; + item_category_id: string; + item_category_name: string; + item_bundlings: string; // item tenant data item_tenant_id: string; diff --git a/src/modules/transaction/transaction/domain/entities/transaction.entity.ts b/src/modules/transaction/transaction/domain/entities/transaction.entity.ts index f7fea17..9d7c3ae 100644 --- a/src/modules/transaction/transaction/domain/entities/transaction.entity.ts +++ b/src/modules/transaction/transaction/domain/entities/transaction.entity.ts @@ -4,9 +4,11 @@ import { TransactionType, TransactionUserType, } from '../../constants'; +import { STATUS } from 'src/core/strings/constants/base.constants'; export interface TransactionEntity extends BaseStatusEntity { // general info + is_recap_transaction: boolean; type: TransactionType; invoice_code: string; creator_counter_no: number; // nomor pos transaksi dibuat @@ -41,6 +43,7 @@ export interface TransactionEntity extends BaseStatusEntity { payment_type: TransactionPaymentType; payment_type_method_id: string; payment_type_method_name: string; + payment_type_method_number: string; payment_type_method_qr: string; payment_card_information: string; payment_code_reference: string; @@ -59,4 +62,17 @@ export interface TransactionEntity extends BaseStatusEntity { payment_total_profit: number; // total untuk profit perusahan profit_share_formula: string; sales_price_formula: string; + + // mdr data + reconciliation_mdr: number; + reconciliation_status: STATUS; + reconciliation_confirm_date: string; + reconciliation_confirm_by: string; + payment_total_net_profit: number; // net pendapatan + + // sending data + sending_invoice_at: number; + sending_invoice_status: STATUS; + sending_qr_at: number; + sending_qr_status: STATUS; } diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-cancel-transaction.manager.ts similarity index 66% rename from src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts rename to src/modules/transaction/transaction/domain/usecases/managers/batch-cancel-transaction.manager.ts index 48ad15c..4fb4157 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/batch-active-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-cancel-transaction.manager.ts @@ -7,11 +7,24 @@ import { 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'; +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; +import { STATUS } from 'src/core/strings/constants/base.constants'; @Injectable() -export class BatchActiveTransactionManager extends BaseBatchUpdateStatusManager { +export class BatchCancelTransactionManager extends BaseBatchUpdateStatusManager { validateData(data: TransactionEntity): Promise { + if (![STATUS.EXPIRED, STATUS.PENDING].includes(data.status)) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, + error: 'Unprocessable Entity', + }); + } + return; } diff --git a/src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts similarity index 65% rename from src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts rename to src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts index 010e827..eb34365 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/batch-inactive-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/batch-confirm-data-transaction.manager.ts @@ -7,11 +7,24 @@ import { 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'; +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; +import { STATUS } from 'src/core/strings/constants/base.constants'; @Injectable() -export class BatchInactiveTransactionManager extends BaseBatchUpdateStatusManager { +export class BatchConfirmDataTransactionManager extends BaseBatchUpdateStatusManager { validateData(data: TransactionEntity): Promise { + if (data.status != STATUS.DRAFT) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, + error: 'Unprocessable Entity', + }); + } + return; } diff --git a/src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/cancel-transaction.manager.ts similarity index 59% rename from src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts rename to src/modules/transaction/transaction/domain/usecases/managers/cancel-transaction.manager.ts index 8287849..2e939e3 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/active-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/cancel-transaction.manager.ts @@ -1,4 +1,8 @@ -import { Injectable } from '@nestjs/common'; +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; import { TransactionEntity } from '../../entities/transaction.entity'; import { @@ -7,18 +11,30 @@ import { } from 'src/core/strings/constants/interface.constants'; 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'; @Injectable() -export class ActiveTransactionManager extends BaseUpdateStatusManager { +export class CancelTransactionManager extends BaseUpdateStatusManager { getResult(): string { return `Success active data ${this.result.invoice_code}`; } async validateProcess(): Promise { + if (![STATUS.EXPIRED, STATUS.PENDING].includes(this.data.status)) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, + error: 'Unprocessable Entity', + }); + } return; } async beforeProcess(): Promise { + const freeTransaction = this.data.payment_total < 1; + Object.assign(this.data, { + status: freeTransaction ? STATUS.ACTIVE : STATUS.PENDING, + }); return; } diff --git a/src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts b/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts similarity index 51% rename from src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts rename to src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts index a7a54b1..1c54e85 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/inactive-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/confirm-data-transaction.manager.ts @@ -7,11 +7,12 @@ import { } from 'src/core/strings/constants/interface.constants'; 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'; @Injectable() -export class InactiveTransactionManager extends BaseUpdateStatusManager { +export class ConfirmDataTransactionManager extends BaseUpdateStatusManager { getResult(): string { - return `Success inactive data ${this.result.invoice_code}`; + return `Success active data ${this.result.invoice_code}`; } async validateProcess(): Promise { @@ -19,6 +20,32 @@ export class InactiveTransactionManager extends BaseUpdateStatusManager { + const old_status = this.oldData.status; + + switch (old_status) { + // jika confirm status pending + // maka akan kebuat reconsiliasi + case STATUS.PENDING: + this.data.reconciliation_status = STATUS.PENDING; + break; + + // jika confirm status rejected + case STATUS.REJECTED: + this.data.reconciliation_status = STATUS.PENDING; + break; + + // jika confirm status expired + case STATUS.EXPIRED: + break; + + default: + this.data.reconciliation_status = STATUS.PENDING; + break; + } + const freeTransaction = this.data.payment_total < 1; + Object.assign(this.data, { + status: freeTransaction ? STATUS.ACTIVE : STATUS.PENDING, + }); return; } 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 index 32e055b..bd8e88c 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/confirm-transaction.manager.ts @@ -1,4 +1,8 @@ -import { Injectable } from '@nestjs/common'; +import { + HttpStatus, + Injectable, + UnprocessableEntityException, +} from '@nestjs/common'; import { BaseUpdateStatusManager } from 'src/core/modules/domain/usecase/managers/base-update-status.manager'; import { TransactionEntity } from '../../entities/transaction.entity'; import { @@ -7,6 +11,7 @@ import { } from 'src/core/strings/constants/interface.constants'; 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'; @Injectable() export class ConfirmTransactionManager extends BaseUpdateStatusManager { @@ -15,10 +20,21 @@ export class ConfirmTransactionManager extends BaseUpdateStatusManager { + if (this.data.status != STATUS.DRAFT) { + throw new UnprocessableEntityException({ + statusCode: HttpStatus.UNPROCESSABLE_ENTITY, + message: `Failed! only data booking with status ${STATUS.ACTIVE} can be confirm`, + error: 'Unprocessable Entity', + }); + } return; } async beforeProcess(): Promise { + const freeTransaction = this.data.payment_total < 1; + Object.assign(this.data, { + status: freeTransaction ? STATUS.ACTIVE : STATUS.PENDING, + }); return; } 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 index 39ae5e5..23c3a3f 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/create-transaction.manager.ts @@ -36,9 +36,6 @@ export class CreateTransactionManager extends BaseCreateManager { +export class TransactionDataOrchestrator { 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 confirmDataManager: ConfirmDataTransactionManager, + private batchConfirmDataManager: BatchConfirmDataTransactionManager, + private deleteManager: DeleteTransactionManager, + private batchDeleteManager: BatchDeleteTransactionManager, + private cancelManager: CancelTransactionManager, + private batchCancelManager: BatchCancelTransactionManager, private serviceData: TransactionDataService, - ) { - super(); - } + ) {} async create(data): Promise { this.createManager.setData(data); @@ -65,21 +62,21 @@ export class TransactionDataOrchestrator extends BaseDataTransactionOrchestrator 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 cancel(dataId): Promise { + this.cancelManager.setData(dataId, STATUS.CANCEL); + this.cancelManager.setService(this.serviceData, TABLE_NAME.TRANSACTION); + await this.cancelManager.execute(); + return this.cancelManager.getResult(); } - async batchActive(dataIds: string[]): Promise { - this.batchActiveManager.setData(dataIds, STATUS.ACTIVE); - this.batchActiveManager.setService( + async batchCancel(dataIds: string[]): Promise { + this.batchCancelManager.setData(dataIds, STATUS.CANCEL); + this.batchCancelManager.setService( this.serviceData, TABLE_NAME.TRANSACTION, ); - await this.batchActiveManager.execute(); - return this.batchActiveManager.getResult(); + await this.batchCancelManager.execute(); + return this.batchCancelManager.getResult(); } async confirm(dataId): Promise { @@ -99,20 +96,23 @@ export class TransactionDataOrchestrator extends BaseDataTransactionOrchestrator 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( + async confirmData(dataId): Promise { + this.confirmDataManager.setData(dataId, STATUS.ACTIVE); + this.confirmDataManager.setService( this.serviceData, TABLE_NAME.TRANSACTION, ); - await this.batchInactiveManager.execute(); - return this.batchInactiveManager.getResult(); + await this.confirmDataManager.execute(); + return this.confirmDataManager.getResult(); + } + + async batchConfirmData(dataIds: string[]): Promise { + this.batchConfirmDataManager.setData(dataIds, STATUS.ACTIVE); + this.batchConfirmDataManager.setService( + this.serviceData, + TABLE_NAME.TRANSACTION, + ); + await this.batchConfirmDataManager.execute(); + return this.batchConfirmDataManager.getResult(); } } diff --git a/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts index 60ae4d9..cc03ddf 100644 --- a/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts +++ b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts @@ -138,7 +138,34 @@ export class TransactionDto extends BaseStatusDto { @ApiProperty({ type: [Object], required: true, - example: TransactionItemDto, + example: [ + { + item: { + id: '68aa12f7-2cce-422b-9bae-185eb1343b94', + created_at: '1718876384378', + status: 'active', + name: 'tes', + item_type: 'bundling', + hpp: '100000', + base_price: '100000', + limit_type: 'no limit', + limit_value: 0, + item_category: { + id: 'ab15981a-a656-4efc-856c-b2abfbe30979', + name: 'Kategori Bundling 2', + }, + bundling_items: [ + { + id: 'bd5a7a38-df25-4203-a1cd-bf94867946b2', + name: 'Wahana 21 panjangggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg', + }, + ], + tenant: null, + }, + qty: 40, + total_price: 4000000, + }, + ], }) @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 index 9f841d8..07b1364 100644 --- a/src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts +++ b/src/modules/transaction/transaction/infrastructure/transaction-data.controller.ts @@ -33,14 +33,14 @@ export class TransactionDataController { return await this.orchestrator.batchDelete(body.ids); } - @Patch(':id/active') - async active(@Param('id') dataId: string): Promise { - return await this.orchestrator.active(dataId); + @Patch(':id/confirm-data') + async confirmData(@Param('id') dataId: string): Promise { + return await this.orchestrator.confirmData(dataId); } - @Put('/batch-active') - async batchActive(@Body() body: BatchIdsDto): Promise { - return await this.orchestrator.batchActive(body.ids); + @Put('/batch-confirm-data') + async batchConfirmData(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchConfirmData(body.ids); } @Patch(':id/confirm') @@ -53,14 +53,14 @@ export class TransactionDataController { return await this.orchestrator.batchConfirm(body.ids); } - @Patch(':id/inactive') - async inactive(@Param('id') dataId: string): Promise { - return await this.orchestrator.inactive(dataId); + @Patch(':id/cancel') + async cancel(@Param('id') dataId: string): Promise { + return await this.orchestrator.cancel(dataId); } - @Put('/batch-inactive') - async batchInactive(@Body() body: BatchIdsDto): Promise { - return await this.orchestrator.batchInactive(body.ids); + @Put('/batch-cancel') + async batchCancel(@Body() body: BatchIdsDto): Promise { + return await this.orchestrator.batchCancel(body.ids); } @Put(':id') diff --git a/src/modules/transaction/transaction/transaction.module.ts b/src/modules/transaction/transaction/transaction.module.ts index f745821..228171d 100644 --- a/src/modules/transaction/transaction/transaction.module.ts +++ b/src/modules/transaction/transaction/transaction.module.ts @@ -13,20 +13,25 @@ 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'; +import { TransactionModel } from './data/models/transaction.model'; +import { TransactionItemModel } from './data/models/transaction-item.model'; +import { TransactionTaxModel } from './data/models/transaction-tax.model'; +import { CancelTransactionManager } from './domain/usecases/managers/cancel-transaction.manager'; +import { BatchCancelTransactionManager } from './domain/usecases/managers/batch-cancel-transaction.manager'; +import { ConfirmDataTransactionManager } from './domain/usecases/managers/confirm-data-transaction.manager'; +import { BatchConfirmDataTransactionManager } from './domain/usecases/managers/batch-confirm-data-transaction.manager'; @Module({ imports: [ ConfigModule.forRoot(), - TypeOrmModule.forFeature(TransactionModels, CONNECTION_NAME.DEFAULT), + TypeOrmModule.forFeature( + [TransactionModel, TransactionItemModel, TransactionTaxModel], + CONNECTION_NAME.DEFAULT, + ), CqrsModule, ], controllers: [TransactionDataController, TransactionReadController], @@ -36,13 +41,13 @@ import { TransactionModels } from './constants'; CreateTransactionManager, DeleteTransactionManager, UpdateTransactionManager, - ActiveTransactionManager, ConfirmTransactionManager, - InactiveTransactionManager, BatchDeleteTransactionManager, - BatchActiveTransactionManager, BatchConfirmTransactionManager, - BatchInactiveTransactionManager, + CancelTransactionManager, + BatchCancelTransactionManager, + ConfirmDataTransactionManager, + BatchConfirmDataTransactionManager, TransactionDataService, TransactionReadService, From ac522bc55a51960ab85cbfd289abc22405e5f45b Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah <98192542+Asharaswin@users.noreply.github.com> Date: Tue, 2 Jul 2024 23:38:41 +0700 Subject: [PATCH 5/6] feat(SPG-384) REST API Read Booking --- .../entities/filter-transaction.entity.ts | 35 +++++- .../managers/detail-transaction.manager.ts | 103 +++++++++++++++++- .../managers/index-transaction.manager.ts | 24 +++- .../dto/filter-transaction.dto.ts | 71 +++++++++++- .../infrastructure/dto/transaction.dto.ts | 1 - 5 files changed, 227 insertions(+), 7 deletions(-) diff --git a/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts b/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts index 13bd3af..719a7fb 100644 --- a/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts +++ b/src/modules/transaction/transaction/domain/entities/filter-transaction.entity.ts @@ -1,3 +1,36 @@ import { BaseFilterEntity } from 'src/core/modules/domain/entities/base-filter.entity'; -export interface FilterTransactionEntity extends BaseFilterEntity {} +export interface FilterTransactionEntity extends BaseFilterEntity { + // search mdr + customer_names?: string[]; + confirm_by_names?: string[]; + payment_banks?: string[]; + payment_bank_numbers?: string[]; + + // seatch booking; + payment_types?: string[]; + types?: string[]; + customer_types?: string[]; + invoice_codes?: string[]; + refund_codes?: string[]; + creator_names?: string[]; + + // filter mdr + payment_date_from?: Date; + payment_date_to?: Date; + transaction_type?: string; + couner_no?: number; + payment_type?: string; + payment_via?: string; + payment_bank?: string; + confirmation_date_from?: Date; + confirmation_date_to?: Date; + + // filter booking + booking_date_from?: Date; + booking_date_to?: Date; + invoice_date_from?: Date; + invoice_date_to?: Date; + settlement_date_from?: Date; + settlement_date_to?: Date; +} 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 index 16da999..593fdb7 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/detail-transaction.manager.ts @@ -14,6 +14,69 @@ export class DetailTransactionManager extends BaseDetailManager { + let payment_type_bank; + + const season_period = { + id: this.result.season_period_id, + holiday_name: this.result.season_period_name, + season_type: { + id: this.result.season_period_type_id, + name: this.result.season_period_type_name, + }, + }; + + if (this.result.payment_type_method_id) { + payment_type_bank = { + id: this.result.payment_type_method_id, + issuer_name: this.result.payment_type_method_name, + account_number: this.result.payment_type_method_number, + }; + } + + const items = this.result?.['items']?.map((itemData) => { + let tenant; + + if (itemData.item_tenant_id) { + tenant = { + id: itemData.item_tenant_id, + name: itemData.item_tenant_name, + share_margin: itemData.item_tenant_share_margin, + }; + } + + return { + item: { + id: itemData.item_id, + name: itemData.item_name, + item_type: itemData.item_type, + base_price: itemData.item_price, + hpp: itemData.item_hpp, + tenant: tenant, + item_category: { + id: itemData.item_category_id, + name: itemData.item_category_name, + }, + }, + id: itemData.item_category_id, + name: itemData.item_category_name, + }; + }); + + Object.assign(this.result, { + season_period: season_period, + items: items, + payment_type_bank: payment_type_bank, + }); + + delete this.result.season_period_id; + delete this.result.season_period_name; + delete this.result.season_period_type_id; + delete this.result.season_period_type_name; + + delete this.result.payment_type_method_id; + delete this.result.payment_type_method_name; + delete this.result.payment_type_method_number; + return; } @@ -23,7 +86,7 @@ export class DetailTransactionManager extends BaseDetailManager joinRelations: [], // relation join and select (relasi yang ingin ditampilkan), - selectRelations: [], + selectRelations: ['items'], // relation yang hanya ingin dihitung (akan return number) countRelations: [], @@ -35,7 +35,26 @@ export class IndexTransactionManager extends BaseIndexManager } get selects(): string[] { - return []; + return [ + `${this.tableName}.id`, + `${this.tableName}.status`, + `${this.tableName}.invoice_code`, + `${this.tableName}.booking_date`, + `${this.tableName}.no_of_group`, + `${this.tableName}.type`, + `${this.tableName}.payment_total`, + `${this.tableName}.customer_type`, + `${this.tableName}.customer_name`, + `${this.tableName}.customer_phone`, + `${this.tableName}.customer_description`, + `${this.tableName}.customer_email`, + `${this.tableName}.invoice_date`, + `${this.tableName}.settlement_date`, + `${this.tableName}.created_at`, + `${this.tableName}.creator_name`, + `${this.tableName}.editor_id`, + `${this.tableName}.editor_name`, + ]; } get specificFilter(): Param[] { @@ -50,6 +69,7 @@ export class IndexTransactionManager extends BaseIndexManager setQueryFilter( queryBuilder: SelectQueryBuilder, ): SelectQueryBuilder { + queryBuilder.andWhere(`${this.tableName}.is_recap_transaction is false`); return queryBuilder; } } diff --git a/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts index 57ec65a..fc83ebf 100644 --- a/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts +++ b/src/modules/transaction/transaction/infrastructure/dto/filter-transaction.dto.ts @@ -1,6 +1,75 @@ import { BaseFilterDto } from 'src/core/modules/infrastructure/dto/base-filter.dto'; import { FilterTransactionEntity } from '../../domain/entities/filter-transaction.entity'; +import { Transform } from 'class-transformer'; +import { ApiProperty } from '@nestjs/swagger'; export class FilterTransactionDto extends BaseFilterDto - implements FilterTransactionEntity {} + implements FilterTransactionEntity +{ + @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]; + }) + customer_types?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + customer_names?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + payment_types?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + payment_banks?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + invoice_codes?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + refund_codes?: string[]; + + @ApiProperty({ type: ['string'], required: false }) + @Transform((body) => { + return Array.isArray(body.value) ? body.value : [body.value]; + }) + creator_names?: string[]; + + @ApiProperty({ type: Date, required: false }) + booking_date_from?: Date; + + @ApiProperty({ type: Date, required: false }) + booking_date_to?: Date; + + @ApiProperty({ type: Date, required: false }) + invoice_date_from?: Date; + + @ApiProperty({ type: Date, required: false }) + invoice_date_to?: Date; + + @ApiProperty({ type: Date, required: false }) + settlement_date_from?: Date; + + @ApiProperty({ type: Date, required: false }) + settlement_date_to?: Date; +} diff --git a/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts index cc03ddf..cbb954b 100644 --- a/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts +++ b/src/modules/transaction/transaction/infrastructure/dto/transaction.dto.ts @@ -11,7 +11,6 @@ import { } 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({ From 5dfe9da0ffa609cdbb48da4afacd215047803769 Mon Sep 17 00:00:00 2001 From: Aswin Ashar Abdullah Date: Wed, 3 Jul 2024 00:28:41 +0700 Subject: [PATCH 6/6] fix(couch) perbaikan couch controller --- src/app.module.ts | 2 +- .../configuration/couch/couch.module.ts | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/app.module.ts b/src/app.module.ts index 3e1dba0..ecb975e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -145,4 +145,4 @@ import { ReconciliationModule } from './modules/transaction/reconciliation/recon }, ], }) -export class AppModule { } +export class AppModule {} diff --git a/src/modules/configuration/couch/couch.module.ts b/src/modules/configuration/couch/couch.module.ts index aa75b30..5655e67 100644 --- a/src/modules/configuration/couch/couch.module.ts +++ b/src/modules/configuration/couch/couch.module.ts @@ -15,9 +15,27 @@ import { SeasonPeriodDeletedHandler, SeasonPeriodUpdatedHandler, } from './domain/managers/season-period.handler'; +import { + ItemDeletedHandler, + ItemUpdatedHandler, +} from './domain/managers/item.handler'; +import { + UserDeletedHandler, + UserUpdatedHandler, +} from './domain/managers/user.handler'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; +import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'; +import { UserModel } from 'src/modules/user-related/user/data/models/user.model'; +import { UserDataService } from 'src/modules/user-related/user/data/services/user-data.service'; +import { ItemDataService } from 'src/modules/item-related/item/data/services/item-data.service'; @Module({ - imports: [ConfigModule.forRoot(), CqrsModule], + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forFeature([ItemModel, UserModel], CONNECTION_NAME.DEFAULT), + CqrsModule, + ], controllers: [CouchDataController], providers: [ PaymentMethodDeletedHandler, @@ -26,7 +44,13 @@ import { VipCategoryUpdatedHandler, SeasonPeriodDeletedHandler, SeasonPeriodUpdatedHandler, + ItemUpdatedHandler, + ItemDeletedHandler, + UserDeletedHandler, + UserUpdatedHandler, + UserDataService, + ItemDataService, CouchService, ], })