import { Injectable, Logger, UnprocessableEntityException, } from '@nestjs/common'; import { BaseDataService } from 'src/core/modules/data/service/base-data.service'; import { SalesPriceFormulaEntity, TransactionSetting, } from '../../domain/entities/sales-price-formula.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { SalesPriceFormulaModel, TransactionSettingModel, } from '../models/sales-price-formula.model'; import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; 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 { constructor( @InjectRepository(SalesPriceFormulaModel, CONNECTION_NAME.DEFAULT) private repo: Repository, @InjectRepository(TaxModel, CONNECTION_NAME.DEFAULT) private tax: Repository, @InjectRepository(ItemModel, CONNECTION_NAME.DEFAULT) private item: Repository, @InjectRepository(TransactionSettingModel, CONNECTION_NAME.DEFAULT) private transactionSetting: Repository, @InjectRepository(TransactionModel, CONNECTION_NAME.DEFAULT) private transaction: Repository, private couchService: CouchService, ) { super(repo); } profitShareFormula() { return this.repo.find({ where: { type: FormulaType.PROFIT_SHARE, }, }); } async sentToBlackHole() { const transactionSettingData = await this.transactionSetting.findOne({ where: {}, }); const percentage = transactionSettingData?.value ?? 100; // const transactionPercentage = Math.floor(Math.random() * 100) + 1; const transactionPercentage = await this.dataSaveFactor(); 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) { const item = await this.item.findOne({ relations: ['tenant'], where: { id, }, }); const tenantShareMargin = item?.tenant?.share_margin; const profitShare = (item?.share_profit ?? 0) / 100; const tenantShare = tenantShareMargin ? (100 - tenantShareMargin) / 100 : 0; return { profitShare, tenantShare }; } async salesPriceFormula() { const salesFormula = await this.repo.findOne({ where: { type: FormulaType.SALES_PRICE, }, }); const taxes = await this.tax.find(); for (const tax of taxes) { salesFormula.formula_string = salesFormula.formula_string.replace( tax.name, `(${tax.formula_string})`, ); } const counter = {}; do { let isInfinite = false; for (const tax of taxes) { salesFormula.formula_string = salesFormula.formula_string.replace( `${tax.name}_value`, `(${tax.formula_string})`, ); if (salesFormula.formula_string.includes(`${tax.name}_value`)) counter[tax.name] = counter[tax.name] ? counter[tax.name] + 1 : 1; for (const count of Object.keys(counter)) { if (!isInfinite && counter[count] > 50) isInfinite = true; } } if (isInfinite) { throw new UnprocessableEntityException({ message: 'Infinity Loop Formula, please fix formula', error: 'Infinity Loop Formula', meta: counter, }); } } while (salesFormula.formula_string.includes('_value')); return salesFormula; } } @Injectable() export class TransactionSettingDataService extends BaseDataService { constructor( @InjectRepository(TransactionSettingModel, CONNECTION_NAME.DEFAULT) private repo: Repository, ) { super(repo); } }