Merge pull request 'development' (#108) from development into production
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details

Reviewed-on: #108
pull/113/head 1.2.0-production.1
irfan 2024-10-09 18:22:03 +00:00
commit 95ee8dce8d
11 changed files with 216 additions and 18 deletions

View File

@ -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"`,
);
}
}

View File

@ -33,8 +33,16 @@ export default <ReportConfigEntity>{
values: [false], values: [false],
}, },
], ],
defaultOrderBy: [], defaultOrderBy: [
lowLevelOrderBy: [], `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: { filter_period_config: {
hidden: true, hidden: true,
}, },

View File

@ -32,8 +32,15 @@ export default <ReportConfigEntity>{
values: [false], values: [false],
}, },
], ],
defaultOrderBy: [], defaultOrderBy: [
lowLevelOrderBy: [], `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: { filter_period_config: {
hidden: true, hidden: true,
}, },

View File

@ -36,6 +36,20 @@ export default <ReportConfigEntity>{
type: DATA_TYPE.DIMENSION, type: DATA_TYPE.DIMENSION,
format: DATA_FORMAT.TEXT, 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', 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`, 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, type: DATA_TYPE.MEASURE,
format: DATA_FORMAT.CURRENCY, 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', column: 'cashier',
query: `CASE WHEN main.type = 'counter' THEN main.creator_name END`, 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, filter_type: FILTER_TYPE.TEXT_IN_MEMBER,
select_custom_options: [...Object.values(TransactionType)], 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', filed_label: 'Tgl. Transaksi',
filter_column: 'main__payment_date', filter_column: 'main__payment_date',

View File

@ -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',
},
],
};

View File

@ -5,8 +5,6 @@ import CancelReport from './configs/cancel-transaction';
import IncomeReportPerItem from './configs/income-per-item'; import IncomeReportPerItem from './configs/income-per-item';
import IncomeReportPerItemMaster from './configs/income-per-item-master'; import IncomeReportPerItemMaster from './configs/income-per-item-master';
import GivingDiscount from './configs/giving-discounts'; 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 BookingReport from './configs/booking';
import RefundsReport from './configs/refunds'; import RefundsReport from './configs/refunds';
import CashierLogReport from './configs/cashier-log'; import CashierLogReport from './configs/cashier-log';
@ -14,6 +12,7 @@ import CashWithdrawalsReport from './configs/cash-withdrawals';
import ReconciliationReport from './configs/reconciliation'; import ReconciliationReport from './configs/reconciliation';
import TaxReport from './configs/tax'; import TaxReport from './configs/tax';
import DemographyReport from './configs/demography'; import DemographyReport from './configs/demography';
import VipCodeReport from './configs/vip_code';
export const TransactionReportConfig: ReportConfigEntity[] = [ export const TransactionReportConfig: ReportConfigEntity[] = [
IncomeReport, IncomeReport,
@ -21,8 +20,6 @@ export const TransactionReportConfig: ReportConfigEntity[] = [
IncomeReportPerItemMaster, IncomeReportPerItemMaster,
CancelReport, CancelReport,
GivingDiscount, GivingDiscount,
// VisitorsPerRideReport,
// TimePerRideReport,
BookingReport, BookingReport,
RefundsReport, RefundsReport,
CashierLogReport, CashierLogReport,
@ -30,4 +27,5 @@ export const TransactionReportConfig: ReportConfigEntity[] = [
ReconciliationReport, ReconciliationReport,
TaxReport, TaxReport,
DemographyReport, DemographyReport,
VipCodeReport,
]; ];

View File

@ -51,12 +51,6 @@ export class PosTransactionHandler implements IEventHandler<ChangeDocEvent> {
}, },
}); });
const taxes = await this.taxService.getManyByOptions({
where: {
status: STATUS.ACTIVE,
},
});
const queryRunner = this.dataService const queryRunner = this.dataService
.getRepository() .getRepository()
.manager.connection.createQueryRunner(); .manager.connection.createQueryRunner();

View File

@ -189,11 +189,19 @@ export function mappingRevertTransaction(data, type) {
const total_share_tenant = const total_share_tenant =
share_margin > 0 ? (Number(share_margin) / 100) * total_price : 0; 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) => { item.bundling_items = item.item.bundling_items?.map((bundling) => {
if (bundling.item_id) return bundling; if (bundling.total_net_price) return bundling;
const basePrice = const basePrice =
(bundling.item_rates ?? bundling.base_price) * +item.qty; (bundling.item_rates ?? bundling.base_price) *
+item.qty *
totalAndBundlingRatio;
const discount = discountPercent * basePrice; const discount = discountPercent * basePrice;
const total = basePrice - discount; const total = basePrice - discount;

View File

@ -12,11 +12,15 @@ export class VipCodeModel
@Column('varchar', { name: 'code' }) @Column('varchar', { name: 'code' })
code: string; code: string;
@Column('integer', { name: 'discount' }) @Column('integer', { name: 'discount', nullable: true })
discount: number; discount: number;
@Column('decimal', { nullable: true })
discount_value: number;
@Column('varchar', { name: 'vip_category_id' }) @Column('varchar', { name: 'vip_category_id' })
vip_category_id: string; vip_category_id: string;
@ManyToOne(() => VipCategoryModel, (model) => model.vip_codes, { @ManyToOne(() => VipCategoryModel, (model) => model.vip_codes, {
onDelete: 'CASCADE', onDelete: 'CASCADE',
onUpdate: 'CASCADE', onUpdate: 'CASCADE',

View File

@ -3,4 +3,5 @@ import { BaseEntity } from 'src/core/modules/domain/entities/base.entity';
export interface VipCodeEntity extends BaseEntity { export interface VipCodeEntity extends BaseEntity {
code: string; code: string;
discount: number; discount: number;
discount_value?: number;
} }

View File

@ -16,12 +16,21 @@ export class VipCodeDto extends BaseDto implements VipCodeEntity {
@ApiProperty({ @ApiProperty({
name: 'discount', name: 'discount',
type: Number, type: Number,
required: true, required: false,
example: 85, example: 85,
}) })
@IsNumber() @IsNumber()
discount: number; discount: number;
@ApiProperty({
name: 'discount_value',
type: Number,
required: false,
example: 25000,
})
@IsNumber()
discount_value: number;
@ApiProperty({ @ApiProperty({
name: 'vip_category', name: 'vip_category',
type: Object, type: Object,