Merge pull request 'development' (#108) from development into production
Reviewed-on: #108pull/113/head 1.2.0-production.1
commit
95ee8dce8d
|
@ -0,0 +1,25 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddDiscountValueToVoucher1728377112337
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'AddDiscountValueToVoucher1728377112337';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
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<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "vip_codes" ALTER COLUMN "discount" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "vip_codes" DROP COLUMN "discount_value"`,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -33,8 +33,16 @@ export default <ReportConfigEntity>{
|
|||
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,
|
||||
},
|
||||
|
|
|
@ -32,8 +32,15 @@ export default <ReportConfigEntity>{
|
|||
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,
|
||||
},
|
||||
|
|
|
@ -36,6 +36,20 @@ export default <ReportConfigEntity>{
|
|||
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 <ReportConfigEntity>{
|
|||
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 <ReportConfigEntity>{
|
|||
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',
|
||||
|
|
|
@ -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 <ReportConfigEntity>{
|
||||
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',
|
||||
},
|
||||
],
|
||||
};
|
|
@ -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,
|
||||
];
|
||||
|
|
|
@ -51,12 +51,6 @@ export class PosTransactionHandler implements IEventHandler<ChangeDocEvent> {
|
|||
},
|
||||
});
|
||||
|
||||
const taxes = await this.taxService.getManyByOptions({
|
||||
where: {
|
||||
status: STATUS.ACTIVE,
|
||||
},
|
||||
});
|
||||
|
||||
const queryRunner = this.dataService
|
||||
.getRepository()
|
||||
.manager.connection.createQueryRunner();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue