Compare commits
9 Commits
1.5.1-alph
...
developmen
Author | SHA1 | Date |
---|---|---|
|
94e769795a | |
|
968697ee17 | |
|
2dd0bd45a8 | |
|
8afbe33c01 | |
|
928e2e7648 | |
|
94baf956dd | |
|
e92f325807 | |
|
66d76634b7 | |
|
b91080906e |
|
@ -96,7 +96,9 @@ import {
|
|||
import { ItemQueueModule } from './modules/item-related/item-queue/item-queue.module';
|
||||
import { ItemQueueModel } from './modules/item-related/item-queue/data/models/item-queue.model';
|
||||
import { QueueBucketModel } from './modules/queue/data/models/queue-bucket.model';
|
||||
|
||||
import { VerificationModel } from './modules/booking-online/authentication/data/models/verification.model';
|
||||
import { BookingOnlineAuthModule } from './modules/booking-online/authentication/auth.module';
|
||||
import { BookingOrderModule } from './modules/booking-online/order/order.module';
|
||||
@Module({
|
||||
imports: [
|
||||
ApmModule.register(),
|
||||
|
@ -157,6 +159,9 @@ import { QueueBucketModel } from './modules/queue/data/models/queue-bucket.model
|
|||
QueueItemModel,
|
||||
QueueModel,
|
||||
QueueBucketModel,
|
||||
|
||||
// Booking Online
|
||||
VerificationModel,
|
||||
],
|
||||
synchronize: false,
|
||||
}),
|
||||
|
@ -218,6 +223,9 @@ import { QueueBucketModel } from './modules/queue/data/models/queue-bucket.model
|
|||
GateScanModule,
|
||||
|
||||
QueueModule,
|
||||
|
||||
BookingOnlineAuthModule,
|
||||
BookingOrderModule,
|
||||
],
|
||||
controllers: [],
|
||||
providers: [
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class BookingAuthentication1748313715598 implements MigrationInterface {
|
||||
name = 'BookingAuthentication1748313715598';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "booking_verification" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "phone_number" character varying NOT NULL, "code" character varying, "tried" integer NOT NULL DEFAULT '0', "created_at" bigint NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000, "updated_at" bigint NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000, CONSTRAINT "PK_046e9288c7dd05c7259275d9fc0" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE "booking_verification"`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { VerificationModel } from './data/models/verification.model';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { BookingAuthenticationController } from './infrastructure/controllers/booking-authentication.controller';
|
||||
import { VerificationService } from './data/services/verification.service';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
import { JWT_EXPIRED } from 'src/core/sessions/constants';
|
||||
import { JWT_SECRET } from 'src/core/sessions/constants';
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature([VerificationModel], CONNECTION_NAME.DEFAULT),
|
||||
|
||||
JwtModule.register({
|
||||
secret: JWT_SECRET,
|
||||
signOptions: { expiresIn: JWT_EXPIRED },
|
||||
}),
|
||||
],
|
||||
controllers: [BookingAuthenticationController],
|
||||
providers: [VerificationService],
|
||||
})
|
||||
export class BookingOnlineAuthModule {}
|
|
@ -0,0 +1,29 @@
|
|||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { BookingVerification } from '../../domain/entities/booking-verification.entity';
|
||||
@Entity('booking_verification')
|
||||
export class VerificationModel implements BookingVerification {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
phone_number: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
code?: string;
|
||||
|
||||
@Column({ default: 0 })
|
||||
tried: number;
|
||||
|
||||
@Column({ type: 'bigint', default: () => 'EXTRACT(EPOCH FROM NOW()) * 1000' })
|
||||
created_at: number;
|
||||
|
||||
@Column({
|
||||
type: 'bigint',
|
||||
default: () => 'EXTRACT(EPOCH FROM NOW()) * 1000',
|
||||
onUpdate: 'EXTRACT(EPOCH FROM NOW()) * 1000',
|
||||
})
|
||||
updated_at: number;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { VerificationModel } from '../models/verification.model';
|
||||
import { BookingVerification } from '../../domain/entities/booking-verification.entity';
|
||||
import { UnprocessableEntityException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
export class VerificationService {
|
||||
constructor(
|
||||
@InjectRepository(VerificationModel)
|
||||
private readonly verificationRepository: Repository<VerificationModel>,
|
||||
private readonly jwtService: JwtService,
|
||||
) {}
|
||||
|
||||
maxAttempts = 3;
|
||||
expiredTime = 5 * 60 * 1000;
|
||||
expiredTimeRegister = 1 * 60 * 1000;
|
||||
|
||||
async generateToken(payload: BookingVerification) {
|
||||
return this.jwtService.sign({
|
||||
phone_number: payload.phone_number,
|
||||
name: payload.name,
|
||||
created_at: payload.created_at,
|
||||
});
|
||||
}
|
||||
|
||||
async register(data: BookingVerification) {
|
||||
const currentTime = Math.floor(Date.now()); // current time in seconds
|
||||
if (
|
||||
data.created_at &&
|
||||
currentTime - data.created_at > this.expiredTimeRegister
|
||||
) {
|
||||
throw new UnprocessableEntityException('Please try again in 1 minute');
|
||||
}
|
||||
// Generate a 4 digit OTP code
|
||||
data.code = Math.floor(1000 + Math.random() * 9000).toString();
|
||||
data.tried = 0;
|
||||
data.updated_at = currentTime;
|
||||
|
||||
let verification = await this.verificationRepository.findOne({
|
||||
where: { phone_number: data.phone_number },
|
||||
});
|
||||
|
||||
if (verification) {
|
||||
// Update existing record
|
||||
verification = this.verificationRepository.merge(verification, data);
|
||||
} else {
|
||||
// Create new record
|
||||
verification = this.verificationRepository.create(data);
|
||||
}
|
||||
return this.verificationRepository.save(verification);
|
||||
}
|
||||
|
||||
async findByPhoneNumber(phoneNumber: string) {
|
||||
return this.verificationRepository.findOne({
|
||||
where: { phone_number: phoneNumber },
|
||||
});
|
||||
}
|
||||
|
||||
async verify(data: BookingVerification): Promise<BookingVerification> {
|
||||
const verification = await this.findByPhoneNumber(data.phone_number);
|
||||
if (!verification) {
|
||||
throw new UnprocessableEntityException('Phone number not found');
|
||||
}
|
||||
|
||||
if (verification.tried >= this.maxAttempts) {
|
||||
throw new UnprocessableEntityException(
|
||||
'Too many attempts, please resend OTP Code',
|
||||
);
|
||||
}
|
||||
|
||||
if (verification.code != data.code) {
|
||||
verification.tried++;
|
||||
await this.verificationRepository.save(verification);
|
||||
throw new UnprocessableEntityException('Invalid verification code');
|
||||
}
|
||||
|
||||
const currentTime = Math.floor(Date.now());
|
||||
if (
|
||||
verification.updated_at &&
|
||||
currentTime - verification.updated_at > this.expiredTime
|
||||
) {
|
||||
throw new UnprocessableEntityException('Verification code expired');
|
||||
}
|
||||
|
||||
return verification;
|
||||
}
|
||||
|
||||
async update(id: string, data: BookingVerification) {
|
||||
return this.verificationRepository.update(id, data);
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
return this.verificationRepository.delete(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export interface BookingVerification {
|
||||
id: string;
|
||||
name: string;
|
||||
phone_number: string;
|
||||
code?: string;
|
||||
tried?: number;
|
||||
created_at?: number;
|
||||
updated_at?: number;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import { Controller, Post, Body, Get, Param } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
BookingVerificationDto,
|
||||
VerificationCodeDto,
|
||||
} from '../dto/booking-verification.dto';
|
||||
import { VerificationService } from '../../data/services/verification.service';
|
||||
import { Public } from 'src/core/guards/domain/decorators/unprotected.guard';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@ApiTags('Booking Authentication')
|
||||
@Public()
|
||||
@Controller('v1/booking-authentication')
|
||||
export class BookingAuthenticationController {
|
||||
constructor(
|
||||
private readonly bookingAuthenticationService: VerificationService,
|
||||
) {}
|
||||
|
||||
@Post('verify')
|
||||
async verify(@Body() body: VerificationCodeDto) {
|
||||
const verification = await this.bookingAuthenticationService.verify(body);
|
||||
const token = await this.bookingAuthenticationService.generateToken(
|
||||
verification,
|
||||
);
|
||||
return {
|
||||
message: `Verification successful for ${verification.phone_number}`,
|
||||
token,
|
||||
};
|
||||
}
|
||||
|
||||
@Post('register')
|
||||
async register(@Body() body: BookingVerificationDto) {
|
||||
const verification = await this.bookingAuthenticationService.register(body);
|
||||
return {
|
||||
message: `Verification code sent to ${verification.phone_number}`,
|
||||
};
|
||||
}
|
||||
|
||||
@Get('get-by-phone/:phone_number')
|
||||
async getByPhoneNumber(@Param('phone_number') phone_number: string) {
|
||||
return this.bookingAuthenticationService.findByPhoneNumber(phone_number);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import { BookingVerification } from '../../domain/entities/booking-verification.entity';
|
||||
import { IsString, IsNotEmpty, Matches } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class BookingVerificationDto implements BookingVerification {
|
||||
id: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
example: 'John Doe',
|
||||
description: 'Name of the person booking',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
example: '628123456789',
|
||||
description: 'Phone number containing only numeric characters',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Matches(/^\d+$/, {
|
||||
message: 'phone_number must contain only numeric characters',
|
||||
})
|
||||
phone_number: string;
|
||||
}
|
||||
|
||||
export class VerificationCodeDto implements BookingVerification {
|
||||
id: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
example: 'John Doe',
|
||||
description: 'Name of the person booking',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
example: '628123456789',
|
||||
description: 'Phone number containing only numeric characters',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Matches(/^\d+$/, {
|
||||
message: 'phone_number must contain only numeric characters',
|
||||
})
|
||||
phone_number: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
required: true,
|
||||
example: '1234',
|
||||
description: 'Verification code',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
code?: string;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { Controller, Get, Query } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||
import { Public } from 'src/core/guards';
|
||||
import { PaginationResponse } from 'src/core/response/domain/ok-response.interface';
|
||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||
import { ItemReadService } from 'src/modules/item-related/item/data/services/item-read.service';
|
||||
import { ItemEntity } from 'src/modules/item-related/item/domain/entities/item.entity';
|
||||
import { IndexItemManager } from 'src/modules/item-related/item/domain/usecases/managers/index-item.manager';
|
||||
import { FilterItemDto } from 'src/modules/item-related/item/infrastructure/dto/filter-item.dto';
|
||||
|
||||
@ApiTags('Booking Item')
|
||||
@Controller('v1/booking-item')
|
||||
@Public(true)
|
||||
export class ItemController {
|
||||
constructor(
|
||||
private indexManager: IndexItemManager,
|
||||
private serviceData: ItemReadService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
async index(
|
||||
@Query() params: FilterItemDto,
|
||||
): Promise<PaginationResponse<ItemEntity>> {
|
||||
try {
|
||||
params.show_to_booking = true;
|
||||
this.indexManager.setFilterParam(params);
|
||||
this.indexManager.setService(this.serviceData, TABLE_NAME.ITEM);
|
||||
await this.indexManager.execute();
|
||||
return this.indexManager.getResult();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||
import { ItemModule } from 'src/modules/item-related/item/item.module';
|
||||
import { ItemController } from './infrastructure/item.controller';
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature([ItemModel], CONNECTION_NAME.DEFAULT),
|
||||
ItemModule,
|
||||
],
|
||||
controllers: [ItemController],
|
||||
providers: [],
|
||||
})
|
||||
export class BookingOrderModule {}
|
|
@ -97,6 +97,40 @@ export class CouchService {
|
|||
}
|
||||
}
|
||||
|
||||
public async totalTodayTransactions(database = 'transaction') {
|
||||
try {
|
||||
const nano = this.nanoInstance;
|
||||
const db = nano.use<any>(database);
|
||||
|
||||
// Get today's start timestamp (midnight)
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const todayTimestamp = today.getTime();
|
||||
|
||||
// Query for documents created today
|
||||
const selector = {
|
||||
created_at: {
|
||||
$gte: todayTimestamp,
|
||||
},
|
||||
};
|
||||
|
||||
const result = await db.find({
|
||||
selector: selector,
|
||||
fields: ['_id', 'payment_total_pay'],
|
||||
limit: 10000,
|
||||
});
|
||||
|
||||
return result.docs.reduce(
|
||||
(sum, doc) => sum + (doc.payment_total_pay || 0),
|
||||
0,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
apm.captureError(error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
getUnixTimestampLast7Days() {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 4);
|
||||
|
|
|
@ -98,6 +98,10 @@ export class IndexItemManager extends BaseIndexManager<ItemEntity> {
|
|||
queryBuilder.andWhere(`${this.tableName}.tenant_id Is Null`);
|
||||
}
|
||||
|
||||
if (this.filterParam.show_to_booking) {
|
||||
queryBuilder.andWhere(`${this.tableName}.show_to_booking = true`);
|
||||
}
|
||||
|
||||
return queryBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,4 +40,6 @@ export class FilterItemDto extends BaseFilterDto implements FilterItemEntity {
|
|||
})
|
||||
@Transform((body) => body.value == 'true')
|
||||
all_item: boolean;
|
||||
|
||||
show_to_booking: boolean;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ export class SeasonPeriodReadController {
|
|||
return await this.orchestrator.index(params);
|
||||
}
|
||||
|
||||
@Public(true)
|
||||
@Get('current-period')
|
||||
async currentPeriod(
|
||||
@Query() params: FilterCurrentSeasonDto,
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
|
||||
import {
|
||||
Injectable,
|
||||
Logger,
|
||||
UnprocessableEntityException,
|
||||
} from '@nestjs/common';
|
||||
import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
|
||||
import {
|
||||
SalesPriceFormulaEntity,
|
||||
|
@ -14,6 +18,9 @@ import { Repository } from 'typeorm';
|
|||
import { FormulaType } from '../../constants';
|
||||
import { TaxModel } from 'src/modules/transaction/tax/data/models/tax.model';
|
||||
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||
import { TransactionModel } from 'src/modules/transaction/transaction/data/models/transaction.model';
|
||||
import { CouchService } from 'src/modules/configuration/couch/data/services/couch.service';
|
||||
import { TransactionType } from 'src/modules/transaction/transaction/constants';
|
||||
|
||||
@Injectable()
|
||||
export class SalesPriceFormulaDataService extends BaseDataService<SalesPriceFormulaEntity> {
|
||||
|
@ -24,6 +31,11 @@ export class SalesPriceFormulaDataService extends BaseDataService<SalesPriceForm
|
|||
private tax: Repository<TaxModel>,
|
||||
@InjectRepository(ItemModel, CONNECTION_NAME.DEFAULT)
|
||||
private item: Repository<ItemModel>,
|
||||
@InjectRepository(TransactionSettingModel, CONNECTION_NAME.DEFAULT)
|
||||
private transactionSetting: Repository<TransactionSettingModel>,
|
||||
@InjectRepository(TransactionModel, CONNECTION_NAME.DEFAULT)
|
||||
private transaction: Repository<TransactionModel>,
|
||||
private couchService: CouchService,
|
||||
) {
|
||||
super(repo);
|
||||
}
|
||||
|
@ -37,11 +49,44 @@ export class SalesPriceFormulaDataService extends BaseDataService<SalesPriceForm
|
|||
}
|
||||
|
||||
async sentToBlackHole() {
|
||||
const percentage = 80;
|
||||
const transactionSettingData = await this.transactionSetting.findOne({
|
||||
where: {},
|
||||
});
|
||||
const percentage = transactionSettingData?.value ?? 100;
|
||||
|
||||
const randomValue = Math.floor(Math.random() * 100) + 1;
|
||||
// const transactionPercentage = Math.floor(Math.random() * 100) + 1;
|
||||
const transactionPercentage = await this.dataSaveFactor();
|
||||
|
||||
return randomValue > percentage;
|
||||
Logger.log(`Factor ${transactionPercentage} from ${percentage}`);
|
||||
|
||||
return transactionPercentage > percentage;
|
||||
}
|
||||
|
||||
async dataSaveFactor() {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const todayTimestamp = today.getTime();
|
||||
|
||||
const totalTransactions = parseInt(
|
||||
await this.transaction
|
||||
.createQueryBuilder('transaction')
|
||||
.select('SUM(transaction.payment_total_pay)', 'sum')
|
||||
.where('transaction.created_at > :timestamp', {
|
||||
timestamp: todayTimestamp,
|
||||
})
|
||||
.andWhere('transaction.type = :type', { type: TransactionType.COUNTER })
|
||||
.getRawOne()
|
||||
.then((result) => result.sum || 0),
|
||||
);
|
||||
|
||||
const couchTransaction = await this.couchService.totalTodayTransactions();
|
||||
|
||||
if (couchTransaction == 0) return 0;
|
||||
|
||||
const factor = (totalTransactions / couchTransaction) * 100;
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
async itemTax(id: string) {
|
||||
|
|
|
@ -25,6 +25,7 @@ export class SalesPriceFormulaDataController {
|
|||
return await this.orchestrator.update(data);
|
||||
}
|
||||
|
||||
@Public(true)
|
||||
@Put()
|
||||
async updateTransactionSetting(
|
||||
@Body() data: TransactionSettingDto,
|
||||
|
|
|
@ -16,6 +16,7 @@ export class SalesPriceFormulaReadController {
|
|||
return await this.orchestrator.detail();
|
||||
}
|
||||
|
||||
@Public(true)
|
||||
@Get('detail')
|
||||
async getTransactionSetting(): Promise<any> {
|
||||
return await this.orchestrator.getTransactionSetting();
|
||||
|
|
|
@ -22,16 +22,25 @@ import { TaxDataService } from '../tax/data/services/tax-data.service';
|
|||
import { TaxModel } from '../tax/data/models/tax.model';
|
||||
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||
import { UpdateTransactionSettingManager } from './domain/usecases/managers/update-transaction-setting.manager';
|
||||
import { TransactionModel } from '../transaction/data/models/transaction.model';
|
||||
import { CouchModule } from 'src/modules/configuration/couch/couch.module';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot(),
|
||||
TypeOrmModule.forFeature(
|
||||
[SalesPriceFormulaModel, TransactionSettingModel, TaxModel, ItemModel],
|
||||
[
|
||||
SalesPriceFormulaModel,
|
||||
TransactionSettingModel,
|
||||
TransactionModel,
|
||||
TaxModel,
|
||||
ItemModel,
|
||||
],
|
||||
CONNECTION_NAME.DEFAULT,
|
||||
),
|
||||
CqrsModule,
|
||||
CouchModule,
|
||||
],
|
||||
controllers: [
|
||||
SalesPriceFormulaDataController,
|
||||
|
|
|
@ -31,6 +31,9 @@ export class PosTransactionHandler implements IEventHandler<ChangeDocEvent> {
|
|||
) {}
|
||||
|
||||
async handle(event: ChangeDocEvent) {
|
||||
const envSkipTransaction = process.env.SKIP_TRANSACTION_FEATURE ?? 'false';
|
||||
const activeSkipTransaction = envSkipTransaction == 'true';
|
||||
|
||||
const apmTransactions = apm.startTransaction(
|
||||
`ChangeDocEvent ${event?.data?.database}`,
|
||||
'handler',
|
||||
|
@ -107,6 +110,7 @@ export class PosTransactionHandler implements IEventHandler<ChangeDocEvent> {
|
|||
// Check if this transaction should be sent to the "black hole" (not saved)
|
||||
// This is only applicable for SETTLED transactions
|
||||
const shouldSkipSaving =
|
||||
activeSkipTransaction &&
|
||||
data.status === STATUS.SETTLED &&
|
||||
(await this.formulaService.sentToBlackHole());
|
||||
|
||||
|
|
|
@ -32,7 +32,10 @@ import { BatchConfirmDataTransactionManager } from './domain/usecases/managers/b
|
|||
import { PosTransactionHandler } from './domain/usecases/handlers/pos-transaction.handler';
|
||||
import { TaxDataService } from '../tax/data/services/tax-data.service';
|
||||
import { SalesPriceFormulaDataService } from '../sales-price-formula/data/services/sales-price-formula-data.service';
|
||||
import { SalesPriceFormulaModel } from '../sales-price-formula/data/models/sales-price-formula.model';
|
||||
import {
|
||||
SalesPriceFormulaModel,
|
||||
TransactionSettingModel,
|
||||
} from '../sales-price-formula/data/models/sales-price-formula.model';
|
||||
import { TaxModel } from '../tax/data/models/tax.model';
|
||||
import { SettledTransactionHandler } from './domain/usecases/handlers/settled-transaction.handler';
|
||||
import { RefundUpdatedHandler } from './domain/usecases/handlers/refund-update.handler';
|
||||
|
@ -43,6 +46,7 @@ import { PaymentMethodModel } from '../payment-method/data/models/payment-method
|
|||
import { TransactionDemographyModel } from './data/models/transaction-demography.model';
|
||||
import { PriceCalculator } from './domain/usecases/calculator/price.calculator';
|
||||
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||
import { CouchModule } from 'src/modules/configuration/couch/couch.module';
|
||||
|
||||
@Module({
|
||||
exports: [TransactionReadService],
|
||||
|
@ -57,6 +61,7 @@ import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'
|
|||
TransactionTaxModel,
|
||||
TransactionItemTaxModel,
|
||||
TransactionBreakdownTaxModel,
|
||||
TransactionSettingModel,
|
||||
TaxModel,
|
||||
SalesPriceFormulaModel,
|
||||
PaymentMethodModel,
|
||||
|
@ -65,6 +70,7 @@ import { ItemModel } from 'src/modules/item-related/item/data/models/item.model'
|
|||
CONNECTION_NAME.DEFAULT,
|
||||
),
|
||||
CqrsModule,
|
||||
CouchModule,
|
||||
],
|
||||
controllers: [TransactionDataController, TransactionReadController],
|
||||
providers: [
|
||||
|
|
Loading…
Reference in New Issue