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,