Merge pull request 'fix/price-calculator' (#93) from fix/price-calculator into development
Reviewed-on: #93pull/94/head^2 20.1.67-alpha.1
commit
93c822f34e
|
@ -45,8 +45,10 @@ import { GoogleCalendarModule } from './modules/configuration/google-calendar/go
|
||||||
import { TransactionModule } from './modules/transaction/transaction/transaction.module';
|
import { TransactionModule } from './modules/transaction/transaction/transaction.module';
|
||||||
import { TransactionModel } from './modules/transaction/transaction/data/models/transaction.model';
|
import { TransactionModel } from './modules/transaction/transaction/data/models/transaction.model';
|
||||||
import {
|
import {
|
||||||
|
TransactionBreakdownTaxModel,
|
||||||
TransactionItemBreakdownModel,
|
TransactionItemBreakdownModel,
|
||||||
TransactionItemModel,
|
TransactionItemModel,
|
||||||
|
TransactionItemTaxModel,
|
||||||
} from './modules/transaction/transaction/data/models/transaction-item.model';
|
} from './modules/transaction/transaction/data/models/transaction-item.model';
|
||||||
import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model';
|
import { TransactionTaxModel } from './modules/transaction/transaction/data/models/transaction-tax.model';
|
||||||
import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module';
|
import { ReconciliationModule } from './modules/transaction/reconciliation/reconciliation.module';
|
||||||
|
@ -121,6 +123,8 @@ import { AuthService } from './core/guards/domain/services/auth.service';
|
||||||
TransactionTaxModel,
|
TransactionTaxModel,
|
||||||
TransactionDemographyModel,
|
TransactionDemographyModel,
|
||||||
TransactionItemBreakdownModel,
|
TransactionItemBreakdownModel,
|
||||||
|
TransactionItemTaxModel,
|
||||||
|
TransactionBreakdownTaxModel,
|
||||||
UserModel,
|
UserModel,
|
||||||
UserLoginModel,
|
UserLoginModel,
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ export enum TABLE_NAME {
|
||||||
TRANSACTION_ITEM = 'transaction_items',
|
TRANSACTION_ITEM = 'transaction_items',
|
||||||
TRANSACTION_ITEM_BREAKDOWN = 'transaction_item_breakdowns',
|
TRANSACTION_ITEM_BREAKDOWN = 'transaction_item_breakdowns',
|
||||||
TRANSACTION_TAX = 'transaction_taxes',
|
TRANSACTION_TAX = 'transaction_taxes',
|
||||||
|
TRANSACTION_ITEM_TAX = 'transaction_item_taxes',
|
||||||
|
TRANSACTION_ITEM_BREAKDOWN_TAX = 't_breakdown_item_taxes',
|
||||||
TRANSACTION_DEMOGRAPHY = 'transaction_demographies',
|
TRANSACTION_DEMOGRAPHY = 'transaction_demographies',
|
||||||
USER = 'users',
|
USER = 'users',
|
||||||
USER_LOGIN = 'users_login',
|
USER_LOGIN = 'users_login',
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddTaxItemTransaction1726045820711 implements MigrationInterface {
|
||||||
|
name = 'AddTaxItemTransaction1726045820711';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "transaction_item_taxes" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "tax_id" character varying, "tax_name" character varying, "taxt_value" numeric, "tax_total_value" numeric, "transaction_id" uuid, CONSTRAINT "PK_fc5f6da61b24eb5bfdd503b0a0d" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "t_breakdown_item_taxes" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "tax_id" character varying, "tax_name" character varying, "taxt_value" numeric, "tax_total_value" numeric, "transaction_id" uuid, CONSTRAINT "PK_a1ef08d2c68169a50102aa70eca" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "total_profit_share" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" ADD "total_profit_share" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_taxes" ADD CONSTRAINT "FK_f5c4966a381d903899cafb4b5ba" FOREIGN KEY ("transaction_id") REFERENCES "transaction_items"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "t_breakdown_item_taxes" ADD CONSTRAINT "FK_74bedce7e94f6707ddf26ef0c0f" FOREIGN KEY ("transaction_id") REFERENCES "transaction_item_breakdowns"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "payment_total_dpp" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" ADD "payment_total_dpp" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" ADD "payment_total_tax" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" ADD "payment_total_tax" numeric`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" ADD "total_share_tenant" numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "t_breakdown_item_taxes" DROP CONSTRAINT "FK_74bedce7e94f6707ddf26ef0c0f"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_taxes" DROP CONSTRAINT "FK_f5c4966a381d903899cafb4b5ba"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" DROP COLUMN "total_profit_share"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "total_profit_share"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(`DROP TABLE "t_breakdown_item_taxes"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "transaction_item_taxes"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" DROP COLUMN "payment_total_dpp"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "payment_total_dpp"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" DROP COLUMN "payment_total_tax"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_items" DROP COLUMN "payment_total_tax"`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "transaction_item_breakdowns" DROP COLUMN "total_share_tenant"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddFormulaToTax1726365023179 implements MigrationInterface {
|
||||||
|
name = 'AddFormulaToTax1726365023179';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "taxes" ADD "formula_render" json`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "taxes" ADD "formula_string" character varying`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "taxes" DROP COLUMN "formula_string"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "taxes" DROP COLUMN "formula_render"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ import {
|
||||||
Param,
|
Param,
|
||||||
RelationParam,
|
RelationParam,
|
||||||
} from 'src/core/modules/domain/entities/base-filter.entity';
|
} from 'src/core/modules/domain/entities/base-filter.entity';
|
||||||
import { FormulaType } from 'src/modules/transaction/sales-price-formula/constants';
|
|
||||||
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
||||||
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
|
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
|
||||||
import { SelectQueryBuilder } from 'typeorm';
|
import { SelectQueryBuilder } from 'typeorm';
|
||||||
|
@ -17,12 +16,7 @@ export class IndexProfitShareFormulaManager extends BaseIndexManager<SalesPriceF
|
||||||
}
|
}
|
||||||
|
|
||||||
get specificFilter(): Param[] {
|
get specificFilter(): Param[] {
|
||||||
return [
|
return [];
|
||||||
{
|
|
||||||
cols: `${this.tableName}.type::text`,
|
|
||||||
data: [FormulaType.PROFIT_SHARE],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareData(): Promise<void> {
|
async prepareData(): Promise<void> {
|
||||||
|
@ -51,6 +45,12 @@ export class IndexProfitShareFormulaManager extends BaseIndexManager<SalesPriceF
|
||||||
}
|
}
|
||||||
|
|
||||||
get selects(): string[] {
|
get selects(): string[] {
|
||||||
return [];
|
// return [];
|
||||||
|
return [
|
||||||
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.formula_render`,
|
||||||
|
`${this.tableName}.formula_string`,
|
||||||
|
`${this.tableName}.value_for`,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
Param,
|
||||||
|
RelationParam,
|
||||||
|
} from 'src/core/modules/domain/entities/base-filter.entity';
|
||||||
|
import { BaseIndexManager } from 'src/core/modules/domain/usecase/managers/base-index.manager';
|
||||||
|
import { SelectQueryBuilder } from 'typeorm';
|
||||||
|
import { TaxEntity } from 'src/modules/transaction/tax/domain/entities/tax.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class IndexTaxFormulaManager extends BaseIndexManager<TaxEntity> {
|
||||||
|
setQueryFilter(
|
||||||
|
queryBuilder: SelectQueryBuilder<TaxEntity>,
|
||||||
|
): SelectQueryBuilder<TaxEntity> {
|
||||||
|
return queryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
get specificFilter(): Param[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
cols: `${this.tableName}.status::text`,
|
||||||
|
isStatus: true,
|
||||||
|
data: [`'active'`],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareData(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeProcess(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterProcess(): Promise<void> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
get relations(): RelationParam {
|
||||||
|
return {
|
||||||
|
// relation only join (for query purpose)
|
||||||
|
joinRelations: [],
|
||||||
|
|
||||||
|
// relation join and select (relasi yang ingin ditampilkan),
|
||||||
|
selectRelations: [],
|
||||||
|
|
||||||
|
// relation yang hanya ingin dihitung (akan return number)
|
||||||
|
countRelations: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get selects(): string[] {
|
||||||
|
// return [];
|
||||||
|
return [
|
||||||
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.formula_render`,
|
||||||
|
`${this.tableName}.formula_string`,
|
||||||
|
`${this.tableName}.name`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,21 +8,21 @@ import {
|
||||||
import { SalesPriceFormulaModel } from 'src/modules/transaction/sales-price-formula/data/models/sales-price-formula.model';
|
import { SalesPriceFormulaModel } from 'src/modules/transaction/sales-price-formula/data/models/sales-price-formula.model';
|
||||||
import { ProfitShareFormulaUpdatedEvent } from '../../entities/event/profit-share-formula-updated.event';
|
import { ProfitShareFormulaUpdatedEvent } from '../../entities/event/profit-share-formula-updated.event';
|
||||||
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
||||||
import { In } from 'typeorm';
|
// import { In } from 'typeorm';
|
||||||
import { STATUS } from 'src/core/strings/constants/base.constants';
|
// import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
import { calculateProfitFormula } from 'src/modules/transaction/sales-price-formula/domain/usecases/managers/helpers/calculation-formula.helper';
|
// import { calculateProfitFormula } from 'src/modules/transaction/sales-price-formula/domain/usecases/managers/helpers/calculation-formula.helper';
|
||||||
import { FormulaType } from 'src/modules/transaction/sales-price-formula/constants';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UpdateProfitShareFormulaManager extends BaseUpdateManager<SalesPriceFormulaEntity> {
|
export class UpdateProfitShareFormulaManager extends BaseUpdateManager<SalesPriceFormulaEntity> {
|
||||||
async validateProcess(): Promise<void> {
|
async validateProcess(): Promise<void> {
|
||||||
const taxes = await this.dataServiceFirstOpt.getManyByOptions({
|
// const taxes = await this.dataServiceFirstOpt.getManyByOptions({
|
||||||
where: {
|
// where: {
|
||||||
status: In([STATUS.ACTIVE]),
|
// status: In([STATUS.ACTIVE]),
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
|
|
||||||
calculateProfitFormula(this.data.formula_string, taxes, 10000, 50, true);
|
// TODO: Save Validation
|
||||||
|
// calculateProfitFormula(this.data.formula_string, taxes, 10000, 50, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,34 +32,9 @@ export class UpdateProfitShareFormulaManager extends BaseUpdateManager<SalesPric
|
||||||
|
|
||||||
async afterProcess(): Promise<void> {
|
async afterProcess(): Promise<void> {
|
||||||
const additionalFormula = this.data.additional;
|
const additionalFormula = this.data.additional;
|
||||||
for (const additional of additionalFormula) {
|
const taxFormula = this.data.taxes;
|
||||||
/**
|
this.dataService.create(null, null, additionalFormula);
|
||||||
* Find formula for variable
|
this.dataServiceFirstOpt.create(null, null, taxFormula);
|
||||||
* If the formula doesn't exist, then create data for save
|
|
||||||
*/
|
|
||||||
const formula = (await this.dataService.getOneByOptions({
|
|
||||||
where: {
|
|
||||||
value_for: additional.value_for,
|
|
||||||
},
|
|
||||||
})) ?? {
|
|
||||||
editor_id: this.user.id,
|
|
||||||
editor_name: this.user.name,
|
|
||||||
updated_at: new Date().getTime(),
|
|
||||||
created_at: new Date().getTime(),
|
|
||||||
type: FormulaType.PROFIT_SHARE,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update formula value to exist formula or new formula
|
|
||||||
formula.formula_render = additional.formula_render;
|
|
||||||
formula.formula_string = additional.formula_string;
|
|
||||||
formula.value_for = additional.value_for;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is create, but inside function is save
|
|
||||||
* So, if the id is provide, the data will be update instead create new data
|
|
||||||
*/
|
|
||||||
this.dataService.create(null, null, formula);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class ProfitShareFormulaDataOrchestrator {
|
||||||
async update(data): Promise<SalesPriceFormulaEntity> {
|
async update(data): Promise<SalesPriceFormulaEntity> {
|
||||||
const formula = await this.serviceData.getOneByOptions({
|
const formula = await this.serviceData.getOneByOptions({
|
||||||
where: {
|
where: {
|
||||||
type: FormulaType.PROFIT_SHARE,
|
type: FormulaType.SALES_PRICE,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,17 @@ import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||||
import { SalesPriceFormulaReadService } from 'src/modules/transaction/sales-price-formula/data/services/sales-price-formula-read.service';
|
import { SalesPriceFormulaReadService } from 'src/modules/transaction/sales-price-formula/data/services/sales-price-formula-read.service';
|
||||||
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
import { SalesPriceFormulaEntity } from 'src/modules/transaction/sales-price-formula/domain/entities/sales-price-formula.entity';
|
||||||
import { IndexProfitShareFormulaManager } from './managers/index-profit-share-formula.manager';
|
import { IndexProfitShareFormulaManager } from './managers/index-profit-share-formula.manager';
|
||||||
|
import { IndexTaxFormulaManager } from './managers/tax-formula.manager';
|
||||||
|
import { TaxReadService } from 'src/modules/transaction/tax/data/services/tax-read.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProfitShareFormulaReadOrchestrator {
|
export class ProfitShareFormulaReadOrchestrator {
|
||||||
constructor(
|
constructor(
|
||||||
private detailManager: DetailProfitShareFormulaManager,
|
private detailManager: DetailProfitShareFormulaManager,
|
||||||
private indexManager: IndexProfitShareFormulaManager,
|
private indexManager: IndexProfitShareFormulaManager,
|
||||||
|
private taxManager: IndexTaxFormulaManager,
|
||||||
private serviceData: SalesPriceFormulaReadService,
|
private serviceData: SalesPriceFormulaReadService,
|
||||||
|
private taxServiceData: TaxReadService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async index(): Promise<SalesPriceFormulaEntity[]> {
|
async index(): Promise<SalesPriceFormulaEntity[]> {
|
||||||
|
@ -21,6 +25,19 @@ export class ProfitShareFormulaReadOrchestrator {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tax(): Promise<Partial<SalesPriceFormulaEntity>[]> {
|
||||||
|
this.taxManager.setFilterParam({});
|
||||||
|
this.taxManager.setService(this.taxServiceData, TABLE_NAME.TAX);
|
||||||
|
await this.taxManager.execute();
|
||||||
|
const { data } = this.taxManager.getResult();
|
||||||
|
return data.map((tax) => {
|
||||||
|
return {
|
||||||
|
...tax,
|
||||||
|
value_for: tax.name,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async detail(): Promise<SalesPriceFormulaEntity> {
|
async detail(): Promise<SalesPriceFormulaEntity> {
|
||||||
this.detailManager.setData('');
|
this.detailManager.setData('');
|
||||||
this.detailManager.setService(this.serviceData, TABLE_NAME.PRICE_FORMULA);
|
this.detailManager.setService(this.serviceData, TABLE_NAME.PRICE_FORMULA);
|
||||||
|
|
|
@ -20,4 +20,9 @@ export class ProfitShareFormulaReadController {
|
||||||
async breakdown(): Promise<SalesPriceFormulaEntity[]> {
|
async breakdown(): Promise<SalesPriceFormulaEntity[]> {
|
||||||
return await this.orchestrator.index();
|
return await this.orchestrator.index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('tax')
|
||||||
|
async tax(): Promise<Partial<SalesPriceFormulaEntity>[]> {
|
||||||
|
return await this.orchestrator.tax();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import { SalesPriceFormulaModel } from '../sales-price-formula/data/models/sales
|
||||||
import { TaxDataService } from '../tax/data/services/tax-data.service';
|
import { TaxDataService } from '../tax/data/services/tax-data.service';
|
||||||
import { TaxModel } from '../tax/data/models/tax.model';
|
import { TaxModel } from '../tax/data/models/tax.model';
|
||||||
import { IndexProfitShareFormulaManager } from './domain/usecases/managers/index-profit-share-formula.manager';
|
import { IndexProfitShareFormulaManager } from './domain/usecases/managers/index-profit-share-formula.manager';
|
||||||
|
import { IndexTaxFormulaManager } from './domain/usecases/managers/tax-formula.manager';
|
||||||
|
import { TaxReadService } from '../tax/data/services/tax-read.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -31,11 +33,13 @@ import { IndexProfitShareFormulaManager } from './domain/usecases/managers/index
|
||||||
DetailProfitShareFormulaManager,
|
DetailProfitShareFormulaManager,
|
||||||
UpdateProfitShareFormulaManager,
|
UpdateProfitShareFormulaManager,
|
||||||
IndexProfitShareFormulaManager,
|
IndexProfitShareFormulaManager,
|
||||||
|
IndexTaxFormulaManager,
|
||||||
|
|
||||||
ProfitShareFormulaDataOrchestrator,
|
ProfitShareFormulaDataOrchestrator,
|
||||||
ProfitShareFormulaReadOrchestrator,
|
ProfitShareFormulaReadOrchestrator,
|
||||||
|
|
||||||
TaxDataService,
|
TaxDataService,
|
||||||
|
TaxReadService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ProfitShareFormulaModule {}
|
export class ProfitShareFormulaModule {}
|
||||||
|
|
|
@ -1,17 +1,91 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
|
||||||
import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
|
import { BaseDataService } from 'src/core/modules/data/service/base-data.service';
|
||||||
import { SalesPriceFormulaEntity } from '../../domain/entities/sales-price-formula.entity';
|
import { SalesPriceFormulaEntity } from '../../domain/entities/sales-price-formula.entity';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { SalesPriceFormulaModel } from '../models/sales-price-formula.model';
|
import { SalesPriceFormulaModel } from '../models/sales-price-formula.model';
|
||||||
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
import { Repository } from 'typeorm';
|
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';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SalesPriceFormulaDataService extends BaseDataService<SalesPriceFormulaEntity> {
|
export class SalesPriceFormulaDataService extends BaseDataService<SalesPriceFormulaEntity> {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(SalesPriceFormulaModel, CONNECTION_NAME.DEFAULT)
|
@InjectRepository(SalesPriceFormulaModel, CONNECTION_NAME.DEFAULT)
|
||||||
private repo: Repository<SalesPriceFormulaModel>,
|
private repo: Repository<SalesPriceFormulaModel>,
|
||||||
|
@InjectRepository(TaxModel, CONNECTION_NAME.DEFAULT)
|
||||||
|
private tax: Repository<TaxModel>,
|
||||||
|
@InjectRepository(ItemModel, CONNECTION_NAME.DEFAULT)
|
||||||
|
private item: Repository<ItemModel>,
|
||||||
) {
|
) {
|
||||||
super(repo);
|
super(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profitShareFormula() {
|
||||||
|
return this.repo.find({
|
||||||
|
where: {
|
||||||
|
type: FormulaType.PROFIT_SHARE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async itemTax(id: string) {
|
||||||
|
const item = await this.item.findOne({
|
||||||
|
relations: ['tenant'],
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const profitShare = (item?.share_profit ?? 0) / 100;
|
||||||
|
const tenantShare = (item?.tenant?.share_margin ?? 0) / 100;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,46 @@
|
||||||
import * as math from 'mathjs';
|
import * as math from 'mathjs';
|
||||||
import { Equation, parse } from 'algebra.js';
|
import { Equation, parse } from 'algebra.js';
|
||||||
import { HttpStatus, UnprocessableEntityException } from '@nestjs/common';
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
HttpStatus,
|
||||||
|
UnprocessableEntityException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { apm } from 'src/core/apm';
|
||||||
|
|
||||||
|
export function calculateFormula(
|
||||||
|
formula: string,
|
||||||
|
variable: object,
|
||||||
|
total: number,
|
||||||
|
solveFor = 'dpp',
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const x1 = math.simplify(formula, variable).toString();
|
||||||
|
// console.log('Formula ', x1);
|
||||||
|
const dppFormula = parse(x1);
|
||||||
|
const totalFormula = parse(total.toString());
|
||||||
|
const equation = new Equation(totalFormula, dppFormula);
|
||||||
|
|
||||||
|
// console.log(equation.toString());
|
||||||
|
const result = equation.solveFor(solveFor).toString();
|
||||||
|
// console.log(result, 'formula');
|
||||||
|
|
||||||
|
const value = math.evaluate(result);
|
||||||
|
// console.log(value, 'value');
|
||||||
|
|
||||||
|
return value;
|
||||||
|
} catch (e) {
|
||||||
|
apm.captureError(e);
|
||||||
|
throw new BadRequestException({
|
||||||
|
message: 'Wrong value',
|
||||||
|
meta: {
|
||||||
|
formula,
|
||||||
|
variable,
|
||||||
|
total,
|
||||||
|
solveFor,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function calculateSalesFormula(
|
export function calculateSalesFormula(
|
||||||
formula: string,
|
formula: string,
|
||||||
|
|
|
@ -14,13 +14,14 @@ import { DetailSalesPriceFormulaManager } from './domain/usecases/managers/detai
|
||||||
import { SalesPriceFormulaModel } from './data/models/sales-price-formula.model';
|
import { SalesPriceFormulaModel } from './data/models/sales-price-formula.model';
|
||||||
import { TaxDataService } from '../tax/data/services/tax-data.service';
|
import { TaxDataService } from '../tax/data/services/tax-data.service';
|
||||||
import { TaxModel } from '../tax/data/models/tax.model';
|
import { TaxModel } from '../tax/data/models/tax.model';
|
||||||
|
import { ItemModel } from 'src/modules/item-related/item/data/models/item.model';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot(),
|
ConfigModule.forRoot(),
|
||||||
TypeOrmModule.forFeature(
|
TypeOrmModule.forFeature(
|
||||||
[SalesPriceFormulaModel, TaxModel],
|
[SalesPriceFormulaModel, TaxModel, ItemModel],
|
||||||
CONNECTION_NAME.DEFAULT,
|
CONNECTION_NAME.DEFAULT,
|
||||||
),
|
),
|
||||||
CqrsModule,
|
CqrsModule,
|
||||||
|
|
|
@ -10,4 +10,10 @@ export class TaxModel extends BaseStatusModel<TaxEntity> implements TaxEntity {
|
||||||
|
|
||||||
@Column('float', { name: 'value', default: 0 })
|
@Column('float', { name: 'value', default: 0 })
|
||||||
value: number;
|
value: number;
|
||||||
|
|
||||||
|
@Column('json', { name: 'formula_render', nullable: true })
|
||||||
|
formula_render: any;
|
||||||
|
|
||||||
|
@Column('varchar', { name: 'formula_string', nullable: true })
|
||||||
|
formula_string: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,10 @@ import { BaseDataService } from 'src/core/modules/data/service/base-data.service
|
||||||
import { TaxEntity } from '../../domain/entities/tax.entity';
|
import { TaxEntity } from '../../domain/entities/tax.entity';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { TaxModel } from '../models/tax.model';
|
import { TaxModel } from '../models/tax.model';
|
||||||
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
import {
|
||||||
|
CONNECTION_NAME,
|
||||||
|
STATUS,
|
||||||
|
} from 'src/core/strings/constants/base.constants';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -14,4 +17,21 @@ export class TaxDataService extends BaseDataService<TaxEntity> {
|
||||||
) {
|
) {
|
||||||
super(repo);
|
super(repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async taxKeyValue(): Promise<any> {
|
||||||
|
const taxes = await this.getManyByOptions({
|
||||||
|
where: {
|
||||||
|
status: STATUS.ACTIVE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const keyVal = {};
|
||||||
|
|
||||||
|
for (const tax of taxes) {
|
||||||
|
const { name, value } = tax;
|
||||||
|
keyVal[name] = value / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyVal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,5 @@ import { BaseStatusEntity } from 'src/core/modules/domain/entities/base-status.e
|
||||||
export interface TaxEntity extends BaseStatusEntity {
|
export interface TaxEntity extends BaseStatusEntity {
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
|
formula_string?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { IndexTaxManager } from './index-tax.manager';
|
||||||
|
import { Param } from 'src/core/modules/domain/entities/base-filter.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class IndexTaxFormulaManager extends IndexTaxManager {
|
||||||
|
get selects(): string[] {
|
||||||
|
return [
|
||||||
|
`${this.tableName}.id`,
|
||||||
|
`${this.tableName}.name`,
|
||||||
|
`${this.tableName}.value`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
get specificFilter(): Param[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
cols: `${this.tableName}.status::text`,
|
||||||
|
data: [`'active'`],
|
||||||
|
isStatus: true,
|
||||||
|
},
|
||||||
|
...super.specificFilter,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,13 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interfa
|
||||||
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
|
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
|
||||||
import { DetailTaxManager } from './managers/detail-tax.manager';
|
import { DetailTaxManager } from './managers/detail-tax.manager';
|
||||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||||
|
import { IndexTaxFormulaManager } from './managers/index-tax-formula.manager';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TaxReadOrchestrator extends BaseReadOrchestrator<TaxEntity> {
|
export class TaxReadOrchestrator extends BaseReadOrchestrator<TaxEntity> {
|
||||||
constructor(
|
constructor(
|
||||||
private indexManager: IndexTaxManager,
|
private indexManager: IndexTaxManager,
|
||||||
|
private formulaManager: IndexTaxFormulaManager,
|
||||||
private detailManager: DetailTaxManager,
|
private detailManager: DetailTaxManager,
|
||||||
private serviceData: TaxReadService,
|
private serviceData: TaxReadService,
|
||||||
) {
|
) {
|
||||||
|
@ -24,6 +26,13 @@ export class TaxReadOrchestrator extends BaseReadOrchestrator<TaxEntity> {
|
||||||
return this.indexManager.getResult();
|
return this.indexManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async formula(params): Promise<PaginationResponse<TaxEntity>> {
|
||||||
|
this.formulaManager.setFilterParam(params);
|
||||||
|
this.formulaManager.setService(this.serviceData, TABLE_NAME.TAX);
|
||||||
|
await this.formulaManager.execute();
|
||||||
|
return this.formulaManager.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
async detail(dataId: string): Promise<TaxEntity> {
|
async detail(dataId: string): Promise<TaxEntity> {
|
||||||
this.detailManager.setData(dataId);
|
this.detailManager.setData(dataId);
|
||||||
this.detailManager.setService(this.serviceData, TABLE_NAME.TAX);
|
this.detailManager.setService(this.serviceData, TABLE_NAME.TAX);
|
||||||
|
|
|
@ -23,6 +23,14 @@ export class TaxReadController {
|
||||||
return await this.orchestrator.index(params);
|
return await this.orchestrator.index(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('formula')
|
||||||
|
@Pagination()
|
||||||
|
async formula(
|
||||||
|
@Query() params: FilterTaxDto,
|
||||||
|
): Promise<PaginationResponse<TaxEntity>> {
|
||||||
|
return await this.orchestrator.formula(params);
|
||||||
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
async detail(@Param('id') id: string): Promise<TaxEntity> {
|
async detail(@Param('id') id: string): Promise<TaxEntity> {
|
||||||
return await this.orchestrator.detail(id);
|
return await this.orchestrator.detail(id);
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { BatchInactiveTaxManager } from './domain/usecases/managers/batch-inacti
|
||||||
import { TaxModel } from './data/models/tax.model';
|
import { TaxModel } from './data/models/tax.model';
|
||||||
import { SalesPriceFormulaReadService } from '../sales-price-formula/data/services/sales-price-formula-read.service';
|
import { SalesPriceFormulaReadService } from '../sales-price-formula/data/services/sales-price-formula-read.service';
|
||||||
import { SalesPriceFormulaModel } from '../sales-price-formula/data/models/sales-price-formula.model';
|
import { SalesPriceFormulaModel } from '../sales-price-formula/data/models/sales-price-formula.model';
|
||||||
|
import { IndexTaxFormulaManager } from './domain/usecases/managers/index-tax-formula.manager';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -37,6 +38,7 @@ import { SalesPriceFormulaModel } from '../sales-price-formula/data/models/sales
|
||||||
controllers: [TaxDataController, TaxReadController],
|
controllers: [TaxDataController, TaxReadController],
|
||||||
providers: [
|
providers: [
|
||||||
IndexTaxManager,
|
IndexTaxManager,
|
||||||
|
IndexTaxFormulaManager,
|
||||||
DetailTaxManager,
|
DetailTaxManager,
|
||||||
CreateTaxManager,
|
CreateTaxManager,
|
||||||
DeleteTaxManager,
|
DeleteTaxManager,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
} from '../../domain/entities/transaction-item.entity';
|
} from '../../domain/entities/transaction-item.entity';
|
||||||
import { TransactionModel } from './transaction.model';
|
import { TransactionModel } from './transaction.model';
|
||||||
import { RefundItemModel } from 'src/modules/transaction/refund/data/models/refund-item.model';
|
import { RefundItemModel } from 'src/modules/transaction/refund/data/models/refund-item.model';
|
||||||
|
import { TransactionTaxEntity } from '../../domain/entities/transaction-tax.entity';
|
||||||
|
|
||||||
@Entity(TABLE_NAME.TRANSACTION_ITEM)
|
@Entity(TABLE_NAME.TRANSACTION_ITEM)
|
||||||
export class TransactionItemModel
|
export class TransactionItemModel
|
||||||
|
@ -64,6 +65,15 @@ export class TransactionItemModel
|
||||||
@Column('decimal', { name: 'total_share_tenant', nullable: true })
|
@Column('decimal', { name: 'total_share_tenant', nullable: true })
|
||||||
total_share_tenant: number;
|
total_share_tenant: number;
|
||||||
|
|
||||||
|
@Column('decimal', { name: 'total_profit_share', nullable: true })
|
||||||
|
total_profit_share: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
payment_total_dpp: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
payment_total_tax: number;
|
||||||
|
|
||||||
@Column('int', { name: 'qty', nullable: true })
|
@Column('int', { name: 'qty', nullable: true })
|
||||||
qty: number;
|
qty: number;
|
||||||
|
|
||||||
|
@ -103,6 +113,13 @@ export class TransactionItemModel
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bundling_items: TransactionItemBreakdownModel[];
|
bundling_items: TransactionItemBreakdownModel[];
|
||||||
|
|
||||||
|
@OneToMany(() => TransactionItemTaxModel, (model) => model.transaction, {
|
||||||
|
cascade: true,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
})
|
||||||
|
item_taxes: TransactionItemTaxModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(TABLE_NAME.TRANSACTION_ITEM_BREAKDOWN)
|
@Entity(TABLE_NAME.TRANSACTION_ITEM_BREAKDOWN)
|
||||||
|
@ -122,10 +139,83 @@ export class TransactionItemBreakdownModel extends BaseCoreModel<TransactionBund
|
||||||
@Column('bigint', { nullable: true })
|
@Column('bigint', { nullable: true })
|
||||||
item_rates: number;
|
item_rates: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
total_profit_share: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
total_share_tenant: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
payment_total_dpp: number;
|
||||||
|
|
||||||
|
@Column('decimal', { nullable: true })
|
||||||
|
payment_total_tax: number;
|
||||||
|
|
||||||
@ManyToOne(() => TransactionItemModel, (model) => model.bundling_items, {
|
@ManyToOne(() => TransactionItemModel, (model) => model.bundling_items, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'transaction_item_id' })
|
@JoinColumn({ name: 'transaction_item_id' })
|
||||||
transaction_item: TransactionItemModel;
|
transaction_item: TransactionItemModel;
|
||||||
|
|
||||||
|
@OneToMany(() => TransactionBreakdownTaxModel, (model) => model.transaction, {
|
||||||
|
cascade: true,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
})
|
||||||
|
item_taxes: TransactionBreakdownTaxModel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(TABLE_NAME.TRANSACTION_ITEM_TAX)
|
||||||
|
export class TransactionItemTaxModel
|
||||||
|
extends BaseCoreModel<TransactionTaxEntity>
|
||||||
|
implements TransactionTaxEntity
|
||||||
|
{
|
||||||
|
@Column('varchar', { name: 'tax_id', nullable: true })
|
||||||
|
tax_id: string;
|
||||||
|
|
||||||
|
@Column('varchar', { name: 'tax_name', nullable: true })
|
||||||
|
tax_name: string;
|
||||||
|
|
||||||
|
@Column('decimal', { name: 'taxt_value', nullable: true })
|
||||||
|
taxt_value: number;
|
||||||
|
|
||||||
|
@Column('decimal', { name: 'tax_total_value', nullable: true })
|
||||||
|
tax_total_value: number;
|
||||||
|
|
||||||
|
@Column('varchar', { name: 'transaction_id', nullable: true })
|
||||||
|
transaction_id: string;
|
||||||
|
@ManyToOne(() => TransactionItemModel, (model) => model.taxes, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'transaction_id' })
|
||||||
|
transaction: TransactionItemModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(TABLE_NAME.TRANSACTION_ITEM_BREAKDOWN_TAX)
|
||||||
|
export class TransactionBreakdownTaxModel
|
||||||
|
extends BaseCoreModel<TransactionTaxEntity>
|
||||||
|
implements TransactionTaxEntity
|
||||||
|
{
|
||||||
|
@Column('varchar', { name: 'tax_id', nullable: true })
|
||||||
|
tax_id: string;
|
||||||
|
|
||||||
|
@Column('varchar', { name: 'tax_name', nullable: true })
|
||||||
|
tax_name: string;
|
||||||
|
|
||||||
|
@Column('decimal', { name: 'taxt_value', nullable: true })
|
||||||
|
taxt_value: number;
|
||||||
|
|
||||||
|
@Column('decimal', { name: 'tax_total_value', nullable: true })
|
||||||
|
tax_total_value: number;
|
||||||
|
|
||||||
|
@Column('varchar', { name: 'transaction_id', nullable: true })
|
||||||
|
transaction_id: string;
|
||||||
|
@ManyToOne(() => TransactionItemBreakdownModel, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'transaction_id' })
|
||||||
|
transaction: TransactionItemBreakdownModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,5 @@ export interface TransactionBundlingItemEntity extends BaseCoreEntity {
|
||||||
hpp: number;
|
hpp: number;
|
||||||
base_price: number;
|
base_price: number;
|
||||||
item_rates: number;
|
item_rates: number;
|
||||||
|
total_price?: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { STATUS } from 'src/core/strings/constants/base.constants';
|
import { STATUS } from 'src/core/strings/constants/base.constants';
|
||||||
import { TransactionItemEntity } from './transaction-item.entity';
|
import { TransactionItemEntity } from './transaction-item.entity';
|
||||||
|
import { TransactionTaxEntity } from './transaction-tax.entity';
|
||||||
|
|
||||||
export interface TransactionEntity extends BaseStatusEntity {
|
export interface TransactionEntity extends BaseStatusEntity {
|
||||||
// general info
|
// general info
|
||||||
|
@ -89,4 +90,5 @@ export interface TransactionEntity extends BaseStatusEntity {
|
||||||
calendar_link?: string;
|
calendar_link?: string;
|
||||||
|
|
||||||
items: TransactionItemEntity[];
|
items: TransactionItemEntity[];
|
||||||
|
taxes?: TransactionTaxEntity[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { SalesPriceFormulaDataService } from 'src/modules/transaction/sales-price-formula/data/services/sales-price-formula-data.service';
|
||||||
|
import { TaxDataService } from 'src/modules/transaction/tax/data/services/tax-data.service';
|
||||||
|
import { TransactionEntity } from '../../entities/transaction.entity';
|
||||||
|
import { calculateFormula } from 'src/modules/transaction/sales-price-formula/domain/usecases/managers/helpers/calculation-formula.helper';
|
||||||
|
import * as math from 'mathjs';
|
||||||
|
import {
|
||||||
|
TransactionBundlingItemEntity,
|
||||||
|
TransactionItemEntity,
|
||||||
|
} from '../../entities/transaction-item.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PriceCalculator {
|
||||||
|
constructor(
|
||||||
|
private formulaService: SalesPriceFormulaDataService,
|
||||||
|
private taxService: TaxDataService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private initialValue(formulas: any[]) {
|
||||||
|
const tax = {};
|
||||||
|
for (const formula of formulas) {
|
||||||
|
tax[`${formula.name}_value`] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tax;
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculate(transaction: TransactionEntity) {
|
||||||
|
const prices = [];
|
||||||
|
const transaction_taxes = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < transaction.items.length; i++) {
|
||||||
|
const item = transaction.items[i];
|
||||||
|
const price = await this.calculateItem(item);
|
||||||
|
const priceValues = this.calculatePrice(price);
|
||||||
|
prices.push(priceValues);
|
||||||
|
transaction_taxes.push(price.taxesValue);
|
||||||
|
|
||||||
|
if (item.bundling_items) {
|
||||||
|
for (let b = 0; b < item.bundling_items.length; b++) {
|
||||||
|
const bundling = item.bundling_items[b];
|
||||||
|
bundling.total_price = bundling.item_rates ?? bundling.base_price;
|
||||||
|
|
||||||
|
const bundlingPrice = await this.calculateItem(bundling);
|
||||||
|
const bundlingValues = this.calculatePrice(bundlingPrice);
|
||||||
|
|
||||||
|
const item_taxes = { item_taxes: bundlingPrice.taxesValue };
|
||||||
|
Object.assign(bundling, bundlingValues, item_taxes);
|
||||||
|
item.bundling_items[b] = bundling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const item_taxes = { item_taxes: price.taxesValue };
|
||||||
|
Object.assign(item, priceValues, item_taxes);
|
||||||
|
transaction.items[i] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tatal_taxes = this.mergeAndSumArrays(transaction_taxes);
|
||||||
|
transaction.taxes = tatal_taxes;
|
||||||
|
const { payment_total_dpp, ...otherValue } =
|
||||||
|
this.sumArrayBasedOnObjectKey(prices);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dpp_value: payment_total_dpp,
|
||||||
|
other: otherValue,
|
||||||
|
tax_datas: tatal_taxes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculateItem(
|
||||||
|
transaction: TransactionItemEntity | TransactionBundlingItemEntity,
|
||||||
|
) {
|
||||||
|
// const itemShare = 20 / 100;
|
||||||
|
// const profitShare = 10 / 100;
|
||||||
|
|
||||||
|
const { profitShare, tenantShare } = await this.formulaService.itemTax(
|
||||||
|
transaction.item_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
const tax = await this.taxService.taxKeyValue();
|
||||||
|
/* Update constant from
|
||||||
|
- profit_share -> tenant_share
|
||||||
|
- item_share -> profit_share
|
||||||
|
*/
|
||||||
|
const taxes = {
|
||||||
|
...tax,
|
||||||
|
tenant_share: tenantShare,
|
||||||
|
profit_share: profitShare,
|
||||||
|
};
|
||||||
|
const dpp = await this.formulaService.salesPriceFormula();
|
||||||
|
const taxFormula = await this.taxService.getManyByOptions({});
|
||||||
|
const shareFormulas = await this.formulaService.profitShareFormula();
|
||||||
|
const taxShareFormulas = shareFormulas.map((formula) => {
|
||||||
|
return {
|
||||||
|
...formula,
|
||||||
|
name: formula.value_for,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const formulas = [...taxFormula, ...taxShareFormulas];
|
||||||
|
const values = {
|
||||||
|
total: transaction.total_price,
|
||||||
|
...this.initialValue(formulas),
|
||||||
|
...taxes,
|
||||||
|
};
|
||||||
|
|
||||||
|
// const dpp = formulas.find((formula) => formula.value_for == 'dpp');
|
||||||
|
|
||||||
|
const dppValue = calculateFormula(
|
||||||
|
dpp.formula_string,
|
||||||
|
taxes,
|
||||||
|
transaction.total_price,
|
||||||
|
);
|
||||||
|
|
||||||
|
values['dpp'] = dppValue;
|
||||||
|
values['dpp_value'] = dppValue;
|
||||||
|
|
||||||
|
let calledVariable = [];
|
||||||
|
const taxesValue = [];
|
||||||
|
do {
|
||||||
|
const valueFor = this.withNullValue(values, calledVariable);
|
||||||
|
|
||||||
|
const formula = formulas.find((formula) => {
|
||||||
|
const name = formula['name'] ?? formula['value_for'];
|
||||||
|
return `${name}_value` == valueFor;
|
||||||
|
});
|
||||||
|
let result = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = math.evaluate(formula.formula_string, values);
|
||||||
|
calledVariable = [];
|
||||||
|
} catch (error) {
|
||||||
|
calledVariable.push(valueFor);
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
values[valueFor] = result;
|
||||||
|
if (result != null) {
|
||||||
|
const tax = taxFormula.find(({ id }) => id == formula.id);
|
||||||
|
if (tax != null) {
|
||||||
|
taxesValue.push({
|
||||||
|
tax_id: tax?.id,
|
||||||
|
tax_name: tax?.name,
|
||||||
|
taxt_value: result,
|
||||||
|
tax_total_value: result,
|
||||||
|
transaction_id: transaction.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// values[`${valueFor}_value`] = result;
|
||||||
|
} while (this.containsNullValue(values));
|
||||||
|
|
||||||
|
// const itemShareFormula = shareFormulas.find(
|
||||||
|
// (f) => f.value_for == 'tenant_share',
|
||||||
|
// );
|
||||||
|
// values['tenant_share_value'] = math.evaluate(
|
||||||
|
// itemShareFormula.formula_string,
|
||||||
|
// values,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const profitShareFormula = shareFormulas.find(
|
||||||
|
// (f) => f.value_for == 'profit_share',
|
||||||
|
// );
|
||||||
|
// values['profit_share_value'] = math.evaluate(
|
||||||
|
// profitShareFormula.formula_string,
|
||||||
|
// values,
|
||||||
|
// );
|
||||||
|
|
||||||
|
return { dpp_value: dppValue, tax_datas: values, taxesValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatePrice(prices: any) {
|
||||||
|
const data = prices.tax_datas;
|
||||||
|
const filteredObject: any = Object.keys(data)
|
||||||
|
.filter((key) => key.endsWith('_value'))
|
||||||
|
.reduce((acc, key) => ({ ...acc, [key]: data[key] }), {});
|
||||||
|
|
||||||
|
const { dpp_value, tenant_share_value, profit_share_value, ...tax } =
|
||||||
|
filteredObject;
|
||||||
|
const taxes = this.sumPriceObject(tax);
|
||||||
|
return {
|
||||||
|
total_profit_share: profit_share_value,
|
||||||
|
total_share_tenant: tenant_share_value,
|
||||||
|
payment_total_tax: taxes,
|
||||||
|
payment_total_dpp: dpp_value,
|
||||||
|
tax,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sumArrayBasedOnObjectKey(arr) {
|
||||||
|
return arr.reduce((acc, cur) => {
|
||||||
|
Object.keys(cur).forEach((key) => {
|
||||||
|
if (!acc[key]) {
|
||||||
|
acc[key] = 0;
|
||||||
|
}
|
||||||
|
acc[key] += cur[key];
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
sumPriceObject(taxes: any): number {
|
||||||
|
let total = 0;
|
||||||
|
for (const tax in taxes) {
|
||||||
|
total += taxes[tax] ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
containsNullValue(obj) {
|
||||||
|
if (typeof obj !== 'object' || obj === null) {
|
||||||
|
return obj === null; // Return true if the value itself is null
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (obj.hasOwnProperty(key)) {
|
||||||
|
if (this.containsNullValue(obj[key])) {
|
||||||
|
return true; // If any nested value is null, return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // If no null values are found, return false
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeAndSumArrays(arrays): any {
|
||||||
|
const mergedData = {};
|
||||||
|
|
||||||
|
arrays.forEach((arr) => {
|
||||||
|
arr.forEach((item) => {
|
||||||
|
if (!mergedData[item.tax_id]) {
|
||||||
|
mergedData[item.tax_id] = {
|
||||||
|
tax_name: item.tax_name,
|
||||||
|
taxt_value: 0,
|
||||||
|
tax_total_value: 0,
|
||||||
|
transaction_id: item.transaction_id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedData[item.tax_id].taxt_value += item.taxt_value;
|
||||||
|
mergedData[item.tax_id].tax_total_value += item.tax_total_value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.values(mergedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
withNullValue(mainObj, called = []) {
|
||||||
|
const obj = { ...mainObj };
|
||||||
|
for (const variable of called) {
|
||||||
|
delete obj[variable];
|
||||||
|
}
|
||||||
|
if (typeof obj !== 'object' || obj === null) {
|
||||||
|
return null; // Return null for non-object values
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (obj.hasOwnProperty(key)) {
|
||||||
|
if (obj[key] === null) {
|
||||||
|
return key; // Found a null value, return the key
|
||||||
|
} else if (typeof obj[key] === 'object') {
|
||||||
|
const nestedKey = this.withNullValue(obj[key]);
|
||||||
|
if (nestedKey !== null) {
|
||||||
|
return `${key}.${nestedKey}`; // Found null in nested object, return nested key path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // No null values found, return null
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import { TransactionModel } from '../../../data/models/transaction.model';
|
||||||
import { calculateSalesFormula } from 'src/modules/transaction/sales-price-formula/domain/usecases/managers/helpers/calculation-formula.helper';
|
import { calculateSalesFormula } from 'src/modules/transaction/sales-price-formula/domain/usecases/managers/helpers/calculation-formula.helper';
|
||||||
import { CreateEventCalendarHelper } from 'src/modules/configuration/google-calendar/domain/usecases/managers/helpers/create-event-calanedar.helper';
|
import { CreateEventCalendarHelper } from 'src/modules/configuration/google-calendar/domain/usecases/managers/helpers/create-event-calanedar.helper';
|
||||||
import { TransactionUpdatedEvent } from '../../entities/event/transaction-updated.event';
|
import { TransactionUpdatedEvent } from '../../entities/event/transaction-updated.event';
|
||||||
|
import { PriceCalculator } from '../calculator/price.calculator';
|
||||||
|
|
||||||
@EventsHandler(TransactionChangeStatusEvent, TransactionUpdatedEvent)
|
@EventsHandler(TransactionChangeStatusEvent, TransactionUpdatedEvent)
|
||||||
export class SettledTransactionHandler
|
export class SettledTransactionHandler
|
||||||
|
@ -18,6 +19,7 @@ export class SettledTransactionHandler
|
||||||
private formulaService: SalesPriceFormulaDataService,
|
private formulaService: SalesPriceFormulaDataService,
|
||||||
private taxService: TaxDataService,
|
private taxService: TaxDataService,
|
||||||
private dataService: TransactionDataService,
|
private dataService: TransactionDataService,
|
||||||
|
private calculator: PriceCalculator,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: TransactionChangeStatusEvent) {
|
async handle(event: TransactionChangeStatusEvent) {
|
||||||
|
@ -62,12 +64,16 @@ export class SettledTransactionHandler
|
||||||
});
|
});
|
||||||
|
|
||||||
// const profit_share_value = this.calculateFormula(profit_formula.formula_string, taxes, data.payment_total_net_profit ?? 0);
|
// const profit_share_value = this.calculateFormula(profit_formula.formula_string, taxes, data.payment_total_net_profit ?? 0);
|
||||||
const { dpp_value, tax_datas } = calculateSalesFormula(
|
const { dpp_value, tax_datas, other } = await this.calculator.calculate(
|
||||||
sales_price.formula_string,
|
data,
|
||||||
taxes,
|
|
||||||
data.payment_total_net_profit ?? 0,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// calculateSalesFormula(
|
||||||
|
// sales_price.formula_string,
|
||||||
|
// taxes,
|
||||||
|
// data.payment_total_net_profit ?? 0,
|
||||||
|
// );
|
||||||
|
|
||||||
// console.log(data, 'dsa');
|
// console.log(data, 'dsa');
|
||||||
const google_calendar = await CreateEventCalendarHelper(data);
|
const google_calendar = await CreateEventCalendarHelper(data);
|
||||||
|
|
||||||
|
@ -78,6 +84,8 @@ export class SettledTransactionHandler
|
||||||
taxes: tax_datas,
|
taxes: tax_datas,
|
||||||
calendar_id: google_calendar?.id,
|
calendar_id: google_calendar?.id,
|
||||||
calendar_link: google_calendar?.htmlLink,
|
calendar_link: google_calendar?.htmlLink,
|
||||||
|
payment_total_share: other.total_profit_share,
|
||||||
|
payment_total_tax: other.payment_total_tax,
|
||||||
});
|
});
|
||||||
} else if (oldSettled) {
|
} else if (oldSettled) {
|
||||||
// console.log(data, 'data oldSettled');
|
// console.log(data, 'data oldSettled');
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { PaginationResponse } from 'src/core/response/domain/ok-response.interfa
|
||||||
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
|
import { BaseReadOrchestrator } from 'src/core/modules/domain/usecase/orchestrators/base-read.orchestrator';
|
||||||
import { DetailTransactionManager } from './managers/detail-transaction.manager';
|
import { DetailTransactionManager } from './managers/detail-transaction.manager';
|
||||||
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
import { TABLE_NAME } from 'src/core/strings/constants/table.constants';
|
||||||
|
import { PriceCalculator } from './calculator/price.calculator';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TransactionReadOrchestrator extends BaseReadOrchestrator<TransactionEntity> {
|
export class TransactionReadOrchestrator extends BaseReadOrchestrator<TransactionEntity> {
|
||||||
|
@ -13,6 +14,7 @@ export class TransactionReadOrchestrator extends BaseReadOrchestrator<Transactio
|
||||||
private indexManager: IndexTransactionManager,
|
private indexManager: IndexTransactionManager,
|
||||||
private detailManager: DetailTransactionManager,
|
private detailManager: DetailTransactionManager,
|
||||||
private serviceData: TransactionReadService,
|
private serviceData: TransactionReadService,
|
||||||
|
private calculator: PriceCalculator,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -30,4 +32,53 @@ export class TransactionReadOrchestrator extends BaseReadOrchestrator<Transactio
|
||||||
await this.detailManager.execute();
|
await this.detailManager.execute();
|
||||||
return this.detailManager.getResult();
|
return this.detailManager.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async dummyCalculate(id: string): Promise<void> {
|
||||||
|
const transaction = await this.serviceData.getOneByOptions({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
relations: ['items', 'items.bundling_items'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const price = await this.calculator.calculate(transaction);
|
||||||
|
transaction.payment_total_profit =
|
||||||
|
transaction.payment_total -
|
||||||
|
price.other.total_profit_share -
|
||||||
|
price.other.payment_total_tax -
|
||||||
|
price.other.total_share_tenant;
|
||||||
|
transaction.payment_total_dpp = price.dpp_value;
|
||||||
|
transaction.payment_total_share = price.other.total_profit_share;
|
||||||
|
transaction.payment_total_tax = price.other.payment_total_tax;
|
||||||
|
console.log({ price }, transaction.payment_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculatePrice(): Promise<void> {
|
||||||
|
const transactions = await this.serviceData.getManyByOptions({
|
||||||
|
where: {
|
||||||
|
is_recap_transaction: false,
|
||||||
|
},
|
||||||
|
relations: ['items', 'items.bundling_items'],
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const transaction of transactions) {
|
||||||
|
try {
|
||||||
|
const price = await this.calculator.calculate(transaction);
|
||||||
|
transaction.payment_total_profit =
|
||||||
|
transaction.payment_total -
|
||||||
|
price.other.total_profit_share -
|
||||||
|
price.other.payment_total_tax -
|
||||||
|
price.other.total_share_tenant;
|
||||||
|
transaction.payment_total_dpp = price.dpp_value;
|
||||||
|
transaction.payment_total_share = price.other.total_profit_share;
|
||||||
|
transaction.payment_total_tax = price.other.payment_total_tax;
|
||||||
|
console.log(transaction.id);
|
||||||
|
await this.serviceData.getRepository().save(transaction);
|
||||||
|
|
||||||
|
// break;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,4 +27,18 @@ export class TransactionReadController {
|
||||||
async detail(@Param('id') id: string): Promise<TransactionEntity> {
|
async detail(@Param('id') id: string): Promise<TransactionEntity> {
|
||||||
return await this.orchestrator.detail(id);
|
return await this.orchestrator.detail(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Public(true)
|
||||||
|
@Get('dummy/:id')
|
||||||
|
async calculate(@Param('id') id: string): Promise<string> {
|
||||||
|
this.orchestrator.dummyCalculate(id);
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Public(true)
|
||||||
|
@Get('dummy2/calculate')
|
||||||
|
async calculateAll(): Promise<string> {
|
||||||
|
this.orchestrator.calculatePrice();
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,10 @@ import { BatchDeleteTransactionManager } from './domain/usecases/managers/batch-
|
||||||
import { BatchConfirmTransactionManager } from './domain/usecases/managers/batch-confirm-transaction.manager';
|
import { BatchConfirmTransactionManager } from './domain/usecases/managers/batch-confirm-transaction.manager';
|
||||||
import { TransactionModel } from './data/models/transaction.model';
|
import { TransactionModel } from './data/models/transaction.model';
|
||||||
import {
|
import {
|
||||||
|
TransactionBreakdownTaxModel,
|
||||||
TransactionItemBreakdownModel,
|
TransactionItemBreakdownModel,
|
||||||
TransactionItemModel,
|
TransactionItemModel,
|
||||||
|
TransactionItemTaxModel,
|
||||||
} from './data/models/transaction-item.model';
|
} from './data/models/transaction-item.model';
|
||||||
import { TransactionTaxModel } from './data/models/transaction-tax.model';
|
import { TransactionTaxModel } from './data/models/transaction-tax.model';
|
||||||
import { CancelTransactionManager } from './domain/usecases/managers/cancel-transaction.manager';
|
import { CancelTransactionManager } from './domain/usecases/managers/cancel-transaction.manager';
|
||||||
|
@ -39,6 +41,8 @@ import { PdfMakeManager } from 'src/modules/configuration/export/domain/managers
|
||||||
import { PaymentMethodDataService } from '../payment-method/data/services/payment-method-data.service';
|
import { PaymentMethodDataService } from '../payment-method/data/services/payment-method-data.service';
|
||||||
import { PaymentMethodModel } from '../payment-method/data/models/payment-method.model';
|
import { PaymentMethodModel } from '../payment-method/data/models/payment-method.model';
|
||||||
import { TransactionDemographyModel } from './data/models/transaction-demography.model';
|
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';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
exports: [TransactionReadService],
|
exports: [TransactionReadService],
|
||||||
|
@ -51,9 +55,12 @@ import { TransactionDemographyModel } from './data/models/transaction-demography
|
||||||
TransactionDemographyModel,
|
TransactionDemographyModel,
|
||||||
TransactionItemBreakdownModel,
|
TransactionItemBreakdownModel,
|
||||||
TransactionTaxModel,
|
TransactionTaxModel,
|
||||||
|
TransactionItemTaxModel,
|
||||||
|
TransactionBreakdownTaxModel,
|
||||||
TaxModel,
|
TaxModel,
|
||||||
SalesPriceFormulaModel,
|
SalesPriceFormulaModel,
|
||||||
PaymentMethodModel,
|
PaymentMethodModel,
|
||||||
|
ItemModel,
|
||||||
],
|
],
|
||||||
CONNECTION_NAME.DEFAULT,
|
CONNECTION_NAME.DEFAULT,
|
||||||
),
|
),
|
||||||
|
@ -61,6 +68,7 @@ import { TransactionDemographyModel } from './data/models/transaction-demography
|
||||||
],
|
],
|
||||||
controllers: [TransactionDataController, TransactionReadController],
|
controllers: [TransactionDataController, TransactionReadController],
|
||||||
providers: [
|
providers: [
|
||||||
|
PriceCalculator,
|
||||||
RefundUpdatedHandler,
|
RefundUpdatedHandler,
|
||||||
PosTransactionHandler,
|
PosTransactionHandler,
|
||||||
MidtransCallbackHandler,
|
MidtransCallbackHandler,
|
||||||
|
|
Loading…
Reference in New Issue