diff --git a/src/database/migrations/1728377112337-add-discount-value-to-voucher.ts b/src/database/migrations/1728377112337-add-discount-value-to-voucher.ts new file mode 100644 index 0000000..8fe627a --- /dev/null +++ b/src/database/migrations/1728377112337-add-discount-value-to-voucher.ts @@ -0,0 +1,25 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddDiscountValueToVoucher1728377112337 + implements MigrationInterface +{ + name = 'AddDiscountValueToVoucher1728377112337'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "vip_codes" ADD "discount_value" numeric`, + ); + await queryRunner.query( + `ALTER TABLE "vip_codes" ALTER COLUMN "discount" DROP NOT NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "vip_codes" ALTER COLUMN "discount" SET NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE "vip_codes" DROP COLUMN "discount_value"`, + ); + } +} diff --git a/src/modules/reports/shared/configs/transaction-report/configs/income-per-item-master.ts b/src/modules/reports/shared/configs/transaction-report/configs/income-per-item-master.ts index a78f42d..201bb1e 100644 --- a/src/modules/reports/shared/configs/transaction-report/configs/income-per-item-master.ts +++ b/src/modules/reports/shared/configs/transaction-report/configs/income-per-item-master.ts @@ -33,8 +33,16 @@ export default { values: [false], }, ], - defaultOrderBy: [], - lowLevelOrderBy: [], + defaultOrderBy: [ + `main.updated_at DESC`, + `to_char(main.payment_date, 'DD-MM-YYYY') DESC`, + ], + lowLevelOrderBy: [ + `main.updated_at DESC`, + `to_char(main.payment_date, 'DD-MM-YYYY') DESC`, + `tr_item.id DESC`, + `tr_item_bundling.id DESC`, + ], filter_period_config: { hidden: true, }, diff --git a/src/modules/reports/shared/configs/transaction-report/configs/income-per-item.ts b/src/modules/reports/shared/configs/transaction-report/configs/income-per-item.ts index cc61dd3..45c6ff7 100644 --- a/src/modules/reports/shared/configs/transaction-report/configs/income-per-item.ts +++ b/src/modules/reports/shared/configs/transaction-report/configs/income-per-item.ts @@ -32,8 +32,15 @@ export default { values: [false], }, ], - defaultOrderBy: [], - lowLevelOrderBy: [], + defaultOrderBy: [ + `main.updated_at DESC`, + `to_char(main.payment_date, 'DD-MM-YYYY') DESC`, + ], + lowLevelOrderBy: [ + `main.updated_at DESC`, + `to_char(main.payment_date, 'DD-MM-YYYY') DESC`, + `tr_item.id DESC`, + ], filter_period_config: { hidden: true, }, diff --git a/src/modules/reports/shared/configs/transaction-report/configs/reconciliation.ts b/src/modules/reports/shared/configs/transaction-report/configs/reconciliation.ts index 188fc72..2baef43 100644 --- a/src/modules/reports/shared/configs/transaction-report/configs/reconciliation.ts +++ b/src/modules/reports/shared/configs/transaction-report/configs/reconciliation.ts @@ -36,6 +36,20 @@ export default { type: DATA_TYPE.DIMENSION, format: DATA_FORMAT.TEXT, }, + { + column: 'main__creator_counter_no', + query: 'main.creator_counter_no', + label: 'No.PoS', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__creator_counter_name', + query: 'main.creator_counter_name', + label: 'Nama PoS', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, { column: 'main__payment_date', query: `CASE WHEN main.payment_date is not null THEN to_char(main.payment_date, 'DD-MM-YYYY') ELSE null END`, @@ -106,6 +120,27 @@ export default { type: DATA_TYPE.MEASURE, format: DATA_FORMAT.CURRENCY, }, + { + column: 'main__total_cash', + query: `CASE WHEN main.payment_type ='cash' and main.reconciliation_status in('confirmed','pending') THEN main.payment_total ELSE 0 END`, + label: 'Total Tunai', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.CURRENCY, + }, + { + column: 'main__total_transaction_bank', + query: `CASE WHEN main.payment_type !='cash' and main.reconciliation_status ='confirmed' THEN main.payment_total ELSE 0 END`, + label: 'Total Transaksi Bank', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.CURRENCY, + }, + { + column: 'main__total_outstanding', + query: `CASE WHEN main.payment_type !='cash' and main.reconciliation_status ='pending' THEN main.payment_total ELSE 0 END`, + label: 'Total Outstanding', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.CURRENCY, + }, { column: 'cashier', query: `CASE WHEN main.type = 'counter' THEN main.creator_name END`, @@ -140,6 +175,18 @@ export default { filter_type: FILTER_TYPE.TEXT_IN_MEMBER, select_custom_options: [...Object.values(TransactionType)], }, + { + filed_label: 'No. PoS', + filter_column: 'main__creator_counter_no', + field_type: FILTER_FIELD_TYPE.input_number, + filter_type: FILTER_TYPE.NUMBER_EQUAL, + }, + { + filed_label: 'Nama PoS', + filter_column: 'main__creator_counter_name', + field_type: FILTER_FIELD_TYPE.input_tag, + filter_type: FILTER_TYPE.TEXT_MULTIPLE_CONTAINS, + }, { filed_label: 'Tgl. Transaksi', filter_column: 'main__payment_date', diff --git a/src/modules/reports/shared/configs/transaction-report/configs/vip_code.ts b/src/modules/reports/shared/configs/transaction-report/configs/vip_code.ts new file mode 100644 index 0000000..a23ece7 --- /dev/null +++ b/src/modules/reports/shared/configs/transaction-report/configs/vip_code.ts @@ -0,0 +1,97 @@ +import { + DATA_FORMAT, + DATA_TYPE, + FILTER_FIELD_TYPE, + FILTER_TYPE, + REPORT_GROUP, +} from '../../../constant'; +import { ReportConfigEntity } from '../../../entities/report-config.entity'; + +export default { + group_name: REPORT_GROUP.transaction_report, + unique_name: `${REPORT_GROUP.transaction_report}__vid_code`, + label: 'Kode VIP', + table_schema: `vip_codes main + LEFT JOIN ( + select + tr.discount_code_id AS vip_code_id, + COUNT(tr.discount_code_id) AS total_transaction + from transactions tr + where tr.discount_code_id is not null + group by tr.discount_code_id + ) voucher_used ON voucher_used.vip_code_id::uuid = main.id`, + main_table_alias: 'main', + whereDefaultConditions: [], + defaultOrderBy: [], + lowLevelOrderBy: [`main.created_at DESC`], + filter_period_config: { + hidden: true, + }, + column_configs: [ + { + column: 'main__code', + query: 'main.code', + label: 'Kode Voucher', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__discount', + query: 'CASE WHEN main.discount > 0 THEN main.discount ELSE null END', + label: 'Diskon (%)', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__discount_value', + query: + 'CASE WHEN main.discount_value > 0 THEN main.discount_value ELSE null END', + label: 'Diskon (Rp)', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.CURRENCY, + }, + { + column: 'voucher_used__total_transaction', + query: 'voucher_used.total_transaction', + label: 'Jumlah Transaksi', + type: DATA_TYPE.MEASURE, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__created_at', + query: `to_char(cast(to_timestamp(main.created_at/1000) as date),'DD-MM-YYYY')`, + label: 'Tgl. Dibuat', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + { + column: 'main__creator_name', + query: 'main.creator_name', + label: 'Dibuat Oleh', + type: DATA_TYPE.DIMENSION, + format: DATA_FORMAT.TEXT, + }, + ], + filter_configs: [ + { + filed_label: 'Kode Voucher', + filter_column: 'main__code', + field_type: FILTER_FIELD_TYPE.input_tag, + filter_type: FILTER_TYPE.TEXT_MULTIPLE_CONTAINS, + }, + { + filed_label: 'Dibuat Oleh', + filter_column: 'main__creator_name', + field_type: FILTER_FIELD_TYPE.input_tag, + filter_type: FILTER_TYPE.TEXT_MULTIPLE_CONTAINS, + }, + + { + filed_label: 'Tgl. Dibuat', + filter_column: 'main__date', + field_type: FILTER_FIELD_TYPE.date_range_picker, + filter_type: FILTER_TYPE.DATE_IN_RANGE_TIMESTAMP, + date_format: 'DD-MM-YYYY', + }, + ], +}; diff --git a/src/modules/reports/shared/configs/transaction-report/index.ts b/src/modules/reports/shared/configs/transaction-report/index.ts index 454a22a..e996100 100644 --- a/src/modules/reports/shared/configs/transaction-report/index.ts +++ b/src/modules/reports/shared/configs/transaction-report/index.ts @@ -5,8 +5,6 @@ import CancelReport from './configs/cancel-transaction'; import IncomeReportPerItem from './configs/income-per-item'; import IncomeReportPerItemMaster from './configs/income-per-item-master'; import GivingDiscount from './configs/giving-discounts'; -import VisitorsPerRideReport from './configs/visitors-per-ride'; -import TimePerRideReport from './configs/time-per-ride'; import BookingReport from './configs/booking'; import RefundsReport from './configs/refunds'; import CashierLogReport from './configs/cashier-log'; @@ -14,6 +12,7 @@ import CashWithdrawalsReport from './configs/cash-withdrawals'; import ReconciliationReport from './configs/reconciliation'; import TaxReport from './configs/tax'; import DemographyReport from './configs/demography'; +import VipCodeReport from './configs/vip_code'; export const TransactionReportConfig: ReportConfigEntity[] = [ IncomeReport, @@ -21,8 +20,6 @@ export const TransactionReportConfig: ReportConfigEntity[] = [ IncomeReportPerItemMaster, CancelReport, GivingDiscount, - // VisitorsPerRideReport, - // TimePerRideReport, BookingReport, RefundsReport, CashierLogReport, @@ -30,4 +27,5 @@ export const TransactionReportConfig: ReportConfigEntity[] = [ ReconciliationReport, TaxReport, DemographyReport, + VipCodeReport, ]; diff --git a/src/modules/transaction/transaction/domain/usecases/handlers/pos-transaction.handler.ts b/src/modules/transaction/transaction/domain/usecases/handlers/pos-transaction.handler.ts index b1915e4..1207198 100644 --- a/src/modules/transaction/transaction/domain/usecases/handlers/pos-transaction.handler.ts +++ b/src/modules/transaction/transaction/domain/usecases/handlers/pos-transaction.handler.ts @@ -51,12 +51,6 @@ export class PosTransactionHandler implements IEventHandler { }, }); - const taxes = await this.taxService.getManyByOptions({ - where: { - status: STATUS.ACTIVE, - }, - }); - const queryRunner = this.dataService .getRepository() .manager.connection.createQueryRunner(); diff --git a/src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper.ts b/src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper.ts index 6940c52..3a6ab2e 100644 --- a/src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper.ts +++ b/src/modules/transaction/transaction/domain/usecases/managers/helpers/mapping-transaction.helper.ts @@ -189,11 +189,19 @@ export function mappingRevertTransaction(data, type) { const total_share_tenant = share_margin > 0 ? (Number(share_margin) / 100) * total_price : 0; + const bundlingTotalPrice = + (item.item?.bundling_items?.reduce( + (a, b) => a + Number(b.item_rates ?? b.base_price), + 0, + ) ?? 0) * +item.qty; + const totalAndBundlingRatio = total_price / bundlingTotalPrice; item.bundling_items = item.item.bundling_items?.map((bundling) => { - if (bundling.item_id) return bundling; + if (bundling.total_net_price) return bundling; const basePrice = - (bundling.item_rates ?? bundling.base_price) * +item.qty; + (bundling.item_rates ?? bundling.base_price) * + +item.qty * + totalAndBundlingRatio; const discount = discountPercent * basePrice; const total = basePrice - discount; diff --git a/src/modules/transaction/vip-code/data/models/vip-code.model.ts b/src/modules/transaction/vip-code/data/models/vip-code.model.ts index 1b22d91..314b047 100644 --- a/src/modules/transaction/vip-code/data/models/vip-code.model.ts +++ b/src/modules/transaction/vip-code/data/models/vip-code.model.ts @@ -12,11 +12,15 @@ export class VipCodeModel @Column('varchar', { name: 'code' }) code: string; - @Column('integer', { name: 'discount' }) + @Column('integer', { name: 'discount', nullable: true }) discount: number; + @Column('decimal', { nullable: true }) + discount_value: number; + @Column('varchar', { name: 'vip_category_id' }) vip_category_id: string; + @ManyToOne(() => VipCategoryModel, (model) => model.vip_codes, { onDelete: 'CASCADE', onUpdate: 'CASCADE', diff --git a/src/modules/transaction/vip-code/domain/entities/vip-code.entity.ts b/src/modules/transaction/vip-code/domain/entities/vip-code.entity.ts index a713c58..ceabcf8 100644 --- a/src/modules/transaction/vip-code/domain/entities/vip-code.entity.ts +++ b/src/modules/transaction/vip-code/domain/entities/vip-code.entity.ts @@ -3,4 +3,5 @@ import { BaseEntity } from 'src/core/modules/domain/entities/base.entity'; export interface VipCodeEntity extends BaseEntity { code: string; discount: number; + discount_value?: number; } diff --git a/src/modules/transaction/vip-code/infrastructure/dto/vip-code.dto.ts b/src/modules/transaction/vip-code/infrastructure/dto/vip-code.dto.ts index 9903730..1666c7f 100644 --- a/src/modules/transaction/vip-code/infrastructure/dto/vip-code.dto.ts +++ b/src/modules/transaction/vip-code/infrastructure/dto/vip-code.dto.ts @@ -16,12 +16,21 @@ export class VipCodeDto extends BaseDto implements VipCodeEntity { @ApiProperty({ name: 'discount', type: Number, - required: true, + required: false, example: 85, }) @IsNumber() discount: number; + @ApiProperty({ + name: 'discount_value', + type: Number, + required: false, + example: 25000, + }) + @IsNumber() + discount_value: number; + @ApiProperty({ name: 'vip_category', type: Object,