refactor: items services to Nestjs

This commit is contained in:
Ahmed Bouhuolia
2024-12-15 15:23:46 +02:00
parent 0a112c5655
commit 87e9cd64e8
21 changed files with 812 additions and 21 deletions

View File

@@ -17,7 +17,7 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json --watchAll"
},
"dependencies": {
"@nestjs/bull": "^10.2.1",
@@ -34,6 +34,8 @@
"@nestjs/throttler": "^6.2.1",
"@types/passport-local": "^1.0.38",
"@types/ramda": "^0.30.2",
"js-money": "^0.6.3",
"accounting": "^0.4.1",
"bull": "^4.16.3",
"bullmq": "^5.21.1",
"cache-manager": "^6.1.1",

View File

@@ -29,6 +29,8 @@ import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { JwtAuthGuard } from '../Auth/Jwt.guard';
import { UserIpInterceptor } from '@/interceptors/user-ip.interceptor';
import { TenancyGlobalMiddleware } from '../Tenancy/TenancyGlobal.middleware';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
import { TransformerModule } from '../Transformer/Transformer.module';
@Module({
imports: [
@@ -100,6 +102,7 @@ import { TenancyGlobalMiddleware } from '../Tenancy/TenancyGlobal.middleware';
},
AppService,
JwtStrategy,
],
})
export class AppModule {

View File

@@ -8,7 +8,7 @@ import { ItemTransformer } from './Item.transformer';
@Injectable()
export class GetItemService {
constructor(
@Inject(Item)
@Inject(Item.name)
private itemModel: typeof Item,
private eventEmitter2: EventEmitter2,
private transformerInjectable: TransformerInjectable,

View File

@@ -98,4 +98,48 @@ export class ItemsController extends TenantController {
const itemId = parseInt(id, 10);
return this.itemsApplication.getItem(itemId);
}
/**
* Retrieves the item associated invoices transactions.
* @param {string} id
* @returns {Promise<any>}
*/
@Get(':id/invoices')
async getItemInvoicesTransactions(@Param('id') id: string): Promise<any> {
const itemId = parseInt(id, 10);
return this.itemsApplication.getItemInvoicesTransactions(itemId);
}
/**
* Retrieves the item associated bills transactions.
* @param {string} id
* @returns {Promise<any>}
*/
@Get(':id/bills')
async getItemBillTransactions(@Param('id') id: string): Promise<any> {
const itemId = parseInt(id, 10);
return this.itemsApplication.getItemBillTransactions(itemId);
}
/**
* Retrieves the item associated estimates transactions.
* @param {string} id
* @returns {Promise<any>}
*/
@Get(':id/estimates')
async getItemEstimatesTransactions(@Param('id') id: string): Promise<any> {
const itemId = parseInt(id, 10);
return this.itemsApplication.getItemEstimatesTransactions(itemId);
}
/**
* Retrieves the item associated receipts transactions.
* @param {string} id
* @returns {Promise<any>}
*/
@Get(':id/receipts')
async getItemReceiptTransactions(@Param('id') id: string): Promise<any> {
const itemId = parseInt(id, 10);
return this.itemsApplication.getItemReceiptsTransactions(itemId);
}
}

View File

@@ -0,0 +1,96 @@
import { Transformer } from '../Transformer/Transformer';
export class ItemBillTransactionTransformer extends Transformer {
/**
* Include these attributes to sale invoice object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'formattedAmount',
'formattedBillDate',
'formattedRate',
'formattedCost',
];
};
/**
* Formatted sell price.
* @param item
* @returns {string}
*/
public formattedAmount(item): string {
return this.formatNumber(item.amount, {
currencyCode: item.bill.currencyCode,
});
}
/**
* Formatted bill date.
* @param item
* @returns {string}
*/
public formattedBillDate = (entry): string => {
return this.formatDate(entry.bill.billDate);
};
/**
* Formatted quantity.
* @returns {string}
*/
public formattedQuantity = (entry): string => {
return entry.quantity;
};
/**
* Formatted rate.
* @param entry
* @returns {string}
*/
public formattedRate = (entry): string => {
return this.formatNumber(entry.rate, {
currencyCode: entry.bill.currencyCode,
});
};
/**
* Formatted bill due date.
* @param entry
* @returns
*/
public formattedBillDueDate = (entry): string => {
return this.formatDate(entry.bill.dueDate);
};
/**
*
* @param entry
* @returns
*/
public transform = (entry) => {
return {
billId: entry.bill.id,
billNumber: entry.bill.billNumber,
referenceNumber: entry.bill.referenceNo,
billDate: entry.bill.billDate,
formattedBillDate: entry.formattedBillDate,
billDueDate: entry.bill.dueDate,
formattedBillDueDate: entry.formattedBillDueDate,
amount: entry.amount,
formattedAmount: entry.formattedAmount,
quantity: entry.quantity,
formattedQuantity: entry.formattedQuantity,
rate: entry.rate,
formattedRate: entry.formattedRate,
vendorDisplayName: entry.bill.vendor.displayName,
vendorCurrencyCode: entry.bill.vendor.currencyCode,
};
};
}

View File

@@ -0,0 +1,81 @@
import { Transformer } from '../Transformer/Transformer';
export class ItemEstimateTransactionTransformer extends Transformer {
/**
* Include these attributes to sale invoice object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'formattedAmount',
'formattedEstimateDate',
'formattedRate',
'formattedCost',
];
};
/**
* Formatted sell price.
* @returns {string}
*/
public formattedAmount(item): string {
return this.formatNumber(item.amount, {
currencyCode: item.estimate.currencyCode,
});
}
/**
* Formatted estimate date.
* @returns {string}
*/
public formattedEstimateDate = (entry): string => {
return this.formatDate(entry.estimate.estimateDate);
};
/**
* Formatted quantity.
* @returns {string}
*/
public formattedQuantity = (entry): string => {
return entry.quantity;
};
/**
* Formatted rate.
* @returns {string}
*/
public formattedRate = (entry): string => {
return this.formatNumber(entry.rate, {
currencyCode: entry.estimate.currencyCode,
});
};
/**
* Transform the entry.
* @param {any} entry
* @returns {any}
*/
public transform = (entry) => {
return {
estimateId: entry.estimate.id,
estimateNumber: entry.estimate.estimateNumber,
referenceNumber: entry.estimate.referenceNo,
estimateDate: entry.estimate.estimateDate,
formattedEstimateDate: entry.formattedEstimateDate,
amount: entry.amount,
formattedAmount: entry.formattedAmount,
quantity: entry.quantity,
formattedQuantity: entry.formattedQuantity,
rate: entry.rate,
formattedRate: entry.formattedRate,
customerDisplayName: entry.estimate.customer.displayName,
customerCurrencyCode: entry.estimate.customer.currencyCode,
};
};
}

View File

@@ -0,0 +1,84 @@
import { Transformer } from '../Transformer/Transformer';
export class ItemInvoicesTransactionsTransformer extends Transformer {
/**
* Include these attributes to sale invoice object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'formattedAmount',
'formattedInvoiceDate',
'formattedRate',
'formattedCost',
];
};
/**
* Formatted sell price.
* @param item
* @returns {string}
*/
public formattedAmount(item): string {
return this.formatNumber(item.amount, {
currencyCode: item.invoice.currencyCode,
});
}
/**
* Formatted invoice date.
* @param item
* @returns
*/
public formattedInvoiceDate = (entry): string => {
return this.formatDate(entry.invoice.invoiceDate);
};
/**
* Formatted item quantity.
* @returns {string}
*/
public formattedQuantity = (entry): string => {
return entry.quantity;
};
/**
* Formatted date.
* @param entry
* @returns {string}
*/
public formattedRate = (entry): string => {
return this.formatNumber(entry.rate, {
currencyCode: entry.invoice.currencyCode,
});
};
/**
*
* @param {any} entry
* @returns {any}
*/
public transform = (entry) => {
return {
invoiceId: entry.invoice.id,
invoiceNumber: entry.invoice.invoiceNo,
referenceNumber: entry.invoice.referenceNo,
invoiceDate: entry.invoice.invoiceDate,
formattedInvoiceDate: entry.formattedInvoiceDate,
amount: entry.amount,
formattedAmount: entry.formattedAmount,
quantity: entry.quantity,
formattedQuantity: entry.formattedQuantity,
rate: entry.rate,
formattedRate: entry.formattedRate,
customerDisplayName: entry.invoice.customer.displayName,
customerCurrencyCode: entry.invoice.customer.currencyCode,
};
};
}

View File

@@ -0,0 +1,85 @@
import { Transformer } from '../Transformer/Transformer';
export class ItemReceiptTransactionTransformer extends Transformer {
/**
* Include these attributes to sale invoice object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'formattedAmount',
'formattedReceiptDate',
'formattedRate',
'formattedCost',
];
};
/**
* Formatted sell price.
* @param item
* @returns {string}
*/
public formattedAmount(item): string {
return this.formatNumber(item.amount, {
currencyCode: item.receipt.currencyCode,
});
}
/**
* Formatted receipt date.
* @param {any} entry
* @returns {string}
*/
public formattedReceiptDate = (entry): string => {
return this.formatDate(entry.receipt.receiptDate);
};
/**
* Formatted quantity.
* @param {any} entry
* @returns {string}
*/
public formattedQuantity = (entry): string => {
return entry.quantity;
};
/**
* Formatted rate.
* @param {any} entry
* @returns {string}
*/
public formattedRate = (entry): string => {
return this.formatNumber(entry.rate, {
currencyCode: entry.receipt.currencyCode,
});
};
/**
* Transform the entry.
* @param {any} entry
* @returns {any}
*/
public transform = (entry) => {
return {
receiptId: entry.receipt.id,
receipNumber: entry.receipt.receiptNumber,
referenceNumber: entry.receipt.referenceNo,
receiptDate: entry.receipt.receiptDate,
formattedReceiptDate: entry.formattedReceiptDate,
amount: entry.amount,
formattedAmount: entry.formattedAmount,
quantity: entry.quantity,
formattedQuantity: entry.formattedQuantity,
rate: entry.rate,
formattedRate: entry.formattedRate,
customerDisplayName: entry.receipt.customer.displayName,
customerCurrencyCode: entry.receipt.customer.currencyCode,
};
};
}

View File

@@ -0,0 +1,108 @@
import { Inject, Injectable } from '@nestjs/common';
import { ItemInvoicesTransactionsTransformer } from './ItemInvoicesTransactions.transformer';
import { ItemEstimateTransactionTransformer } from './ItemEstimatesTransaction.transformer';
import { ItemBillTransactionTransformer } from './ItemBillsTransactions.transformer';
import { ItemReceiptTransactionTransformer } from './ItemReceiptsTransactions.transformer';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
import { ItemEntry } from './models/ItemEntry';
@Injectable()
export class ItemTransactionsService {
constructor(
private transformer: TransformerInjectable,
@Inject(ItemEntry.name)
private readonly itemEntry: typeof ItemEntry,
) {}
/**
* Retrieves the item associated invoices transactions.
* @param {number} itemId -
*/
public async getItemInvoicesTransactions(itemId: number) {
const invoiceEntries = await this.itemEntry.query()
.where('itemId', itemId)
.where('referenceType', 'SaleInvoice')
.withGraphJoined('invoice.customer(selectCustomerColumns)')
.orderBy('invoice:invoiceDate', 'ASC')
.modifiers({
selectCustomerColumns: (builder) => {
builder.select('displayName', 'currencyCode', 'id');
},
});
// Retrieves the transformed invoice entries.
return this.transformer.transform(
invoiceEntries,
new ItemInvoicesTransactionsTransformer(),
);
}
/**
* Retrieve the item associated invoices transactions.
* @param {number} itemId
* @returns
*/
public async getItemBillTransactions(itemId: number) {
const billEntries = await this.itemEntry.query()
.where('itemId', itemId)
.where('referenceType', 'Bill')
.withGraphJoined('bill.vendor(selectVendorColumns)')
.orderBy('bill:billDate', 'ASC')
.modifiers({
selectVendorColumns: (builder) => {
builder.select('displayName', 'currencyCode', 'id');
},
});
// Retrieves the transformed bill entries.
return this.transformer.transform(
billEntries,
new ItemBillTransactionTransformer(),
);
}
/**
* Retrieves the item associated estimates transactions.
* @param {number} itemId
* @returns
*/
public async getItemEstimateTransactions(itemId: number) {
const estimatesEntries = await this.itemEntry.query()
.where('itemId', itemId)
.where('referenceType', 'SaleEstimate')
.withGraphJoined('estimate.customer(selectCustomerColumns)')
.orderBy('estimate:estimateDate', 'ASC')
.modifiers({
selectCustomerColumns: (builder) => {
builder.select('displayName', 'currencyCode', 'id');
},
});
// Retrieves the transformed estimates entries.
return this.transformer.transform(
estimatesEntries,
new ItemEstimateTransactionTransformer(),
);
}
/**
* Retrieves the item associated receipts transactions.
* @param {number} itemId
* @returns
*/
public async getItemReceiptTransactions(itemId: number) {
const receiptsEntries = await this.itemEntry.query()
.where('itemId', itemId)
.where('referenceType', 'SaleReceipt')
.withGraphJoined('receipt.customer(selectCustomerColumns)')
.orderBy('receipt:receiptDate', 'ASC')
.modifiers({
selectCustomerColumns: (builder) => {
builder.select('displayName', 'currencyCode', 'id');
},
});
// Retrieves the transformed receipts entries.
return this.transformer.transform(
receiptsEntries,
new ItemReceiptTransactionTransformer(),
);
}
}

View File

@@ -9,6 +9,9 @@ import { EditItemService } from './EditItem.service';
import { InactivateItem } from './InactivateItem.service';
import { ActivateItemService } from './ActivateItem.service';
import { ItemsApplicationService } from './ItemsApplication.service';
import { ItemTransactionsService } from './ItemTransactions.service';
import { GetItemService } from './GetItem.service';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
@Module({
imports: [TenancyDatabaseModule],
@@ -21,7 +24,10 @@ import { ItemsApplicationService } from './ItemsApplication.service';
ActivateItemService,
DeleteItemService,
ItemsApplicationService,
GetItemService,
ItemTransactionsService,
TenancyContext,
TransformerInjectable,
],
})
export class ItemsModule {}

View File

@@ -7,7 +7,10 @@ import { Knex } from 'knex';
import { InactivateItem } from './InactivateItem.service';
import { ActivateItemService } from './ActivateItem.service';
import { GetItemService } from './GetItem.service';
import { ItemTransactionsService } from './ItemTransactions.service';
import { Injectable } from '@nestjs/common';
@Injectable()
export class ItemsApplicationService {
constructor(
private readonly createItemService: CreateItemService,
@@ -16,6 +19,7 @@ export class ItemsApplicationService {
private readonly activateItemService: ActivateItemService,
private readonly inactivateItemService: InactivateItem,
private readonly getItemService: GetItemService,
private readonly itemTransactionsService: ItemTransactionsService,
) {}
/**
@@ -81,4 +85,40 @@ export class ItemsApplicationService {
async getItem(itemId: number): Promise<any> {
return this.getItemService.getItem(itemId);
}
/**
* Retrieves the item associated invoices transactions.
* @param {number} itemId
* @returns {Promise<any>}
*/
async getItemInvoicesTransactions(itemId: number): Promise<any> {
return this.itemTransactionsService.getItemInvoicesTransactions(itemId);
}
/**
* Retrieves the item associated bills transactions.
* @param {number} itemId
* @returns {Promise<any>}
*/
async getItemBillTransactions(itemId: number): Promise<any> {
return this.itemTransactionsService.getItemBillTransactions(itemId);
}
/**
* Retrieves the item associated estimates transactions.
* @param {number} itemId
* @returns {Promise<any>}
*/
async getItemEstimatesTransactions(itemId: number): Promise<any> {
return this.itemTransactionsService.getItemEstimateTransactions(itemId);
}
/**
* Retrieves the item associated receipts transactions.
* @param {number} itemId
* @returns {Promise<any>}
*/
async getItemReceiptsTransactions(itemId: number): Promise<any> {
return this.itemTransactionsService.getItemReceiptTransactions(itemId);
}
}

View File

@@ -1,11 +1,12 @@
import * as F from 'fp-ts/function';
import * as R from 'ramda';
import { SearchableModel } from '@/modules/Search/SearchableMdel';
import { TenantModel } from '@/modules/System/models/TenantModel';
import { BaseModel } from '@/models/Model';
// import { TenantModel } from '@/modules/System/models/TenantModel';
const Extend = R.compose(SearchableModel)(TenantModel);
// const Extend = R.compose(SearchableModel)(TenantModel);
export class Item extends Extend {
export class Item extends BaseModel {
public readonly quantityOnHand: number;
public readonly name: string;
public readonly active: boolean;

View File

@@ -0,0 +1,231 @@
import { Model } from 'objection';
// import TenantModel from 'models/TenantModel';
// import { getExlusiveTaxAmount, getInclusiveTaxAmount } from '@/utils/taxRate';
import { BaseModel } from '@/models/Model';
export class ItemEntry extends BaseModel {
public taxRate: number;
public discount: number;
public quantity: number;
public rate: number;
public isInclusiveTax: number;
/**
* Table name.
* @returns {string}
*/
static get tableName() {
return 'items_entries';
}
/**
* Timestamps columns.
* @returns {string[]}
*/
get timestamps() {
return ['created_at', 'updated_at'];
}
/**
* Virtual attributes.
* @returns {string[]}
*/
static get virtualAttributes() {
return [
'amount',
'taxAmount',
'amountExludingTax',
'amountInclusingTax',
'total',
];
}
/**
* Item entry total.
* Amount of item entry includes tax and subtracted discount amount.
* @returns {number}
*/
get total() {
return this.amountInclusingTax;
}
/**
* Item entry amount.
* Amount of item entry that may include or exclude tax.
* @returns {number}
*/
get amount() {
return this.quantity * this.rate;
}
/**
* Item entry amount including tax.
* @returns {number}
*/
get amountInclusingTax() {
return this.isInclusiveTax ? this.amount : this.amount + this.taxAmount;
}
/**
* Item entry amount excluding tax.
* @returns {number}
*/
get amountExludingTax() {
return this.isInclusiveTax ? this.amount - this.taxAmount : this.amount;
}
/**
* Discount amount.
* @returns {number}
*/
get discountAmount() {
return this.amount * (this.discount / 100);
}
/**
* Tag rate fraction.
* @returns {number}
*/
get tagRateFraction() {
return this.taxRate / 100;
}
/**
* Tax amount withheld.
* @returns {number}
*/
get taxAmount() {
return 0;
// return this.isInclusiveTax
// ? getInclusiveTaxAmount(this.amount, this.taxRate)
// : getExlusiveTaxAmount(this.amount, this.taxRate);
}
static calcAmount(itemEntry) {
const { discount, quantity, rate } = itemEntry;
const total = quantity * rate;
return discount ? total - total * discount * 0.01 : total;
}
/**
* Item entry relations.
*/
// static get relationMappings() {
// const Item = require('models/Item');
// const BillLandedCostEntry = require('models/BillLandedCostEntry');
// const SaleInvoice = require('models/SaleInvoice');
// const Bill = require('models/Bill');
// const SaleReceipt = require('models/SaleReceipt');
// const SaleEstimate = require('models/SaleEstimate');
// const ProjectTask = require('models/Task');
// const Expense = require('models/Expense');
// const TaxRate = require('models/TaxRate');
// return {
// item: {
// relation: Model.BelongsToOneRelation,
// modelClass: Item.default,
// join: {
// from: 'items_entries.itemId',
// to: 'items.id',
// },
// },
// allocatedCostEntries: {
// relation: Model.HasManyRelation,
// modelClass: BillLandedCostEntry.default,
// join: {
// from: 'items_entries.referenceId',
// to: 'bill_located_cost_entries.entryId',
// },
// },
// invoice: {
// relation: Model.BelongsToOneRelation,
// modelClass: SaleInvoice.default,
// join: {
// from: 'items_entries.referenceId',
// to: 'sales_invoices.id',
// },
// },
// bill: {
// relation: Model.BelongsToOneRelation,
// modelClass: Bill.default,
// join: {
// from: 'items_entries.referenceId',
// to: 'bills.id',
// },
// },
// estimate: {
// relation: Model.BelongsToOneRelation,
// modelClass: SaleEstimate.default,
// join: {
// from: 'items_entries.referenceId',
// to: 'sales_estimates.id',
// },
// },
// /**
// * Sale receipt reference.
// */
// receipt: {
// relation: Model.BelongsToOneRelation,
// modelClass: SaleReceipt.default,
// join: {
// from: 'items_entries.referenceId',
// to: 'sales_receipts.id',
// },
// },
// /**
// * Project task reference.
// */
// projectTaskRef: {
// relation: Model.HasManyRelation,
// modelClass: ProjectTask.default,
// join: {
// from: 'items_entries.projectRefId',
// to: 'tasks.id',
// },
// },
// /**
// * Project expense reference.
// */
// projectExpenseRef: {
// relation: Model.HasManyRelation,
// modelClass: Expense.default,
// join: {
// from: 'items_entries.projectRefId',
// to: 'expenses_transactions.id',
// },
// },
// /**
// * Project bill reference.
// */
// projectBillRef: {
// relation: Model.HasManyRelation,
// modelClass: Bill.default,
// join: {
// from: 'items_entries.projectRefId',
// to: 'bills.id',
// },
// },
// /**
// * Tax rate reference.
// */
// tax: {
// relation: Model.HasOneRelation,
// modelClass: TaxRate.default,
// join: {
// from: 'items_entries.taxRateId',
// to: 'tax_rates.id',
// },
// },
// };
// }
}

View File

@@ -6,9 +6,12 @@ import { TenantModel } from '@/modules/System/models/TenantModel';
import { SystemKnexConnection } from '../SystemDB/SystemDB.constants';
import { SystemModelsConnection } from './SystemModels.constants';
import { SystemUser } from '../models/SystemUser';
import { TenantMetadata } from '../models/TenantMetadataModel';
const models = [SystemUser, PlanSubscription, TenantModel, TenantMetadata];
const models = [SystemUser, PlanSubscription, TenantModel];
const modelProviders = models.map((model) => {
console.log(model.name, model, 'model.name');
return {
provide: model.name,
useValue: model,
@@ -23,7 +26,7 @@ const providers = [
useFactory: async (systemKnex: Knex) => {
Model.knex(systemKnex);
},
},
}
];
@Global()

View File

@@ -47,9 +47,7 @@ export class TenantMetadata extends BaseModel {
/**
* Table name.
*/
static get tableName() {
return 'tenants_metadata';
}
static tableName = 'tenants_metadata';
/**
* Virtual attributes.

View File

@@ -2,20 +2,19 @@ import { BaseModel } from '@/models/Model';
import { Model } from 'objection';
import { TenantMetadata } from './TenantMetadataModel';
export class TenantModel extends BaseModel {
public readonly organizationId: string;
public readonly initializedAt: string;
public readonly seededAt: boolean;
public readonly builtAt: string;
public readonly metadata: TenantMetadata;
public readonly metadata: any;
/**
* Table name.
*/
static get tableName() {
return 'tenants';
}
static tableName = 'tenants';
/**
* Relations mappings.
*/

View File

@@ -36,8 +36,8 @@ export class TenancyContext {
}
/**
*
* @returns
* Retrieves the current system user.
* @returns {Promise<SystemUser>}
*/
getSystemUser() {
// Get the user from the request headers.

View File

@@ -4,10 +4,9 @@ import { TENANCY_DB_CONNECTION } from '../TenancyDB/TenancyDB.constants';
import { Item } from '../../../modules/Items/models/Item';
import { Account } from '@/modules/Accounts/models/Account';
import { TenantModel } from '@/modules/System/models/TenantModel';
import { TenantMetadata } from '@/modules/System/models/TenantMetadataModel';
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
const models = [Item, Account, TenantModel, TenantMetadata];
const models = [Item, Account, ItemEntry];
const modelProviders = models.map((model) => {
return {

View File

@@ -0,0 +1,11 @@
import { Global, Module } from '@nestjs/common';
import { TransformerInjectable } from './TransformerInjectable.service';
import { TenancyContext } from '../Tenancy/TenancyContext.service';
@Global()
@Module({
providers: [TransformerInjectable],
exports: [TransformerInjectable],
imports: [TenancyContext],
})
export class TransformerModule {}

View File

@@ -1,6 +1,6 @@
import { I18nService } from 'nestjs-i18n';
import { Transformer } from './Transformer';
import { Injectable } from '@nestjs/common';
import { Global, Injectable } from '@nestjs/common';
import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { TransformerContext } from './Transformer.types';