diff --git a/packages/server-nest/package.json b/packages/server-nest/package.json index d364dd61c..cd08509d3 100644 --- a/packages/server-nest/package.json +++ b/packages/server-nest/package.json @@ -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", diff --git a/packages/server-nest/src/modules/App/App.module.ts b/packages/server-nest/src/modules/App/App.module.ts index 9123140eb..058f5edaa 100644 --- a/packages/server-nest/src/modules/App/App.module.ts +++ b/packages/server-nest/src/modules/App/App.module.ts @@ -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 { diff --git a/packages/server-nest/src/modules/Items/GetItem.service.ts b/packages/server-nest/src/modules/Items/GetItem.service.ts index b990ef0eb..4ebb69ccb 100644 --- a/packages/server-nest/src/modules/Items/GetItem.service.ts +++ b/packages/server-nest/src/modules/Items/GetItem.service.ts @@ -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, diff --git a/packages/server-nest/src/modules/Items/Item.controller.ts b/packages/server-nest/src/modules/Items/Item.controller.ts index 4f9324f22..6abc6a214 100644 --- a/packages/server-nest/src/modules/Items/Item.controller.ts +++ b/packages/server-nest/src/modules/Items/Item.controller.ts @@ -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} + */ + @Get(':id/invoices') + async getItemInvoicesTransactions(@Param('id') id: string): Promise { + const itemId = parseInt(id, 10); + return this.itemsApplication.getItemInvoicesTransactions(itemId); + } + + /** + * Retrieves the item associated bills transactions. + * @param {string} id + * @returns {Promise} + */ + @Get(':id/bills') + async getItemBillTransactions(@Param('id') id: string): Promise { + const itemId = parseInt(id, 10); + return this.itemsApplication.getItemBillTransactions(itemId); + } + + /** + * Retrieves the item associated estimates transactions. + * @param {string} id + * @returns {Promise} + */ + @Get(':id/estimates') + async getItemEstimatesTransactions(@Param('id') id: string): Promise { + const itemId = parseInt(id, 10); + return this.itemsApplication.getItemEstimatesTransactions(itemId); + } + + /** + * Retrieves the item associated receipts transactions. + * @param {string} id + * @returns {Promise} + */ + @Get(':id/receipts') + async getItemReceiptTransactions(@Param('id') id: string): Promise { + const itemId = parseInt(id, 10); + return this.itemsApplication.getItemReceiptsTransactions(itemId); + } } diff --git a/packages/server-nest/src/modules/Items/ItemBillsTransactions.transformer.ts b/packages/server-nest/src/modules/Items/ItemBillsTransactions.transformer.ts new file mode 100644 index 000000000..b4d40229d --- /dev/null +++ b/packages/server-nest/src/modules/Items/ItemBillsTransactions.transformer.ts @@ -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, + }; + }; +} diff --git a/packages/server-nest/src/modules/Items/ItemEstimatesTransaction.transformer.ts b/packages/server-nest/src/modules/Items/ItemEstimatesTransaction.transformer.ts new file mode 100644 index 000000000..e9009a8e6 --- /dev/null +++ b/packages/server-nest/src/modules/Items/ItemEstimatesTransaction.transformer.ts @@ -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, + }; + }; +} diff --git a/packages/server-nest/src/modules/Items/ItemInvoicesTransactions.transformer.ts b/packages/server-nest/src/modules/Items/ItemInvoicesTransactions.transformer.ts new file mode 100644 index 000000000..b0758fcbf --- /dev/null +++ b/packages/server-nest/src/modules/Items/ItemInvoicesTransactions.transformer.ts @@ -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, + }; + }; +} diff --git a/packages/server-nest/src/modules/Items/ItemReceiptsTransactions.transformer.ts b/packages/server-nest/src/modules/Items/ItemReceiptsTransactions.transformer.ts new file mode 100644 index 000000000..6d8608534 --- /dev/null +++ b/packages/server-nest/src/modules/Items/ItemReceiptsTransactions.transformer.ts @@ -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, + }; + }; +} diff --git a/packages/server-nest/src/modules/Items/ItemTransactions.service.ts b/packages/server-nest/src/modules/Items/ItemTransactions.service.ts new file mode 100644 index 000000000..306c0caca --- /dev/null +++ b/packages/server-nest/src/modules/Items/ItemTransactions.service.ts @@ -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(), + ); + } +} diff --git a/packages/server-nest/src/modules/Items/Items.module.ts b/packages/server-nest/src/modules/Items/Items.module.ts index ebbf3dc64..d85f6bf81 100644 --- a/packages/server-nest/src/modules/Items/Items.module.ts +++ b/packages/server-nest/src/modules/Items/Items.module.ts @@ -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 {} diff --git a/packages/server-nest/src/modules/Items/ItemsApplication.service.ts b/packages/server-nest/src/modules/Items/ItemsApplication.service.ts index 5509cb7b9..d88d54d04 100644 --- a/packages/server-nest/src/modules/Items/ItemsApplication.service.ts +++ b/packages/server-nest/src/modules/Items/ItemsApplication.service.ts @@ -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 { return this.getItemService.getItem(itemId); } + + /** + * Retrieves the item associated invoices transactions. + * @param {number} itemId + * @returns {Promise} + */ + async getItemInvoicesTransactions(itemId: number): Promise { + return this.itemTransactionsService.getItemInvoicesTransactions(itemId); + } + + /** + * Retrieves the item associated bills transactions. + * @param {number} itemId + * @returns {Promise} + */ + async getItemBillTransactions(itemId: number): Promise { + return this.itemTransactionsService.getItemBillTransactions(itemId); + } + + /** + * Retrieves the item associated estimates transactions. + * @param {number} itemId + * @returns {Promise} + */ + async getItemEstimatesTransactions(itemId: number): Promise { + return this.itemTransactionsService.getItemEstimateTransactions(itemId); + } + + /** + * Retrieves the item associated receipts transactions. + * @param {number} itemId + * @returns {Promise} + */ + async getItemReceiptsTransactions(itemId: number): Promise { + return this.itemTransactionsService.getItemReceiptTransactions(itemId); + } } diff --git a/packages/server-nest/src/modules/Items/ItemsEntriesService.ts b/packages/server-nest/src/modules/Items/ItemsEntriesService.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/server-nest/src/modules/Items/models/Item.ts b/packages/server-nest/src/modules/Items/models/Item.ts index 226c13dc9..045d613a7 100644 --- a/packages/server-nest/src/modules/Items/models/Item.ts +++ b/packages/server-nest/src/modules/Items/models/Item.ts @@ -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; diff --git a/packages/server-nest/src/modules/Items/models/ItemEntry.ts b/packages/server-nest/src/modules/Items/models/ItemEntry.ts new file mode 100644 index 000000000..e33100dd0 --- /dev/null +++ b/packages/server-nest/src/modules/Items/models/ItemEntry.ts @@ -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', + // }, + // }, + // }; + // } +} diff --git a/packages/server-nest/src/modules/System/SystemModels/SystemModels.module.ts b/packages/server-nest/src/modules/System/SystemModels/SystemModels.module.ts index 02f5742f8..aad867cd5 100644 --- a/packages/server-nest/src/modules/System/SystemModels/SystemModels.module.ts +++ b/packages/server-nest/src/modules/System/SystemModels/SystemModels.module.ts @@ -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() diff --git a/packages/server-nest/src/modules/System/models/TenantMetadataModel.ts b/packages/server-nest/src/modules/System/models/TenantMetadataModel.ts index 190e3d29c..11f299baf 100644 --- a/packages/server-nest/src/modules/System/models/TenantMetadataModel.ts +++ b/packages/server-nest/src/modules/System/models/TenantMetadataModel.ts @@ -47,9 +47,7 @@ export class TenantMetadata extends BaseModel { /** * Table name. */ - static get tableName() { - return 'tenants_metadata'; - } + static tableName = 'tenants_metadata'; /** * Virtual attributes. diff --git a/packages/server-nest/src/modules/System/models/TenantModel.ts b/packages/server-nest/src/modules/System/models/TenantModel.ts index 5483b01f1..2b89bff2c 100644 --- a/packages/server-nest/src/modules/System/models/TenantModel.ts +++ b/packages/server-nest/src/modules/System/models/TenantModel.ts @@ -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. */ diff --git a/packages/server-nest/src/modules/Tenancy/TenancyContext.service.ts b/packages/server-nest/src/modules/Tenancy/TenancyContext.service.ts index f2890b6b8..f80ca7503 100644 --- a/packages/server-nest/src/modules/Tenancy/TenancyContext.service.ts +++ b/packages/server-nest/src/modules/Tenancy/TenancyContext.service.ts @@ -36,8 +36,8 @@ export class TenancyContext { } /** - * - * @returns + * Retrieves the current system user. + * @returns {Promise} */ getSystemUser() { // Get the user from the request headers. diff --git a/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts b/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts index 97711d63b..2647d154e 100644 --- a/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts +++ b/packages/server-nest/src/modules/Tenancy/TenancyModels/Tenancy.module.ts @@ -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 { diff --git a/packages/server-nest/src/modules/Transformer/Transformer.module.ts b/packages/server-nest/src/modules/Transformer/Transformer.module.ts new file mode 100644 index 000000000..457c7d5f0 --- /dev/null +++ b/packages/server-nest/src/modules/Transformer/Transformer.module.ts @@ -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 {} diff --git a/packages/server-nest/src/modules/Transformer/TransformerInjectable.service.ts b/packages/server-nest/src/modules/Transformer/TransformerInjectable.service.ts index 2fa649dbc..3975818f5 100644 --- a/packages/server-nest/src/modules/Transformer/TransformerInjectable.service.ts +++ b/packages/server-nest/src/modules/Transformer/TransformerInjectable.service.ts @@ -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';