mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
refactor: items services to Nestjs
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"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": {
|
"dependencies": {
|
||||||
"@nestjs/bull": "^10.2.1",
|
"@nestjs/bull": "^10.2.1",
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
"@nestjs/throttler": "^6.2.1",
|
"@nestjs/throttler": "^6.2.1",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
"@types/ramda": "^0.30.2",
|
"@types/ramda": "^0.30.2",
|
||||||
|
"js-money": "^0.6.3",
|
||||||
|
"accounting": "^0.4.1",
|
||||||
"bull": "^4.16.3",
|
"bull": "^4.16.3",
|
||||||
"bullmq": "^5.21.1",
|
"bullmq": "^5.21.1",
|
||||||
"cache-manager": "^6.1.1",
|
"cache-manager": "^6.1.1",
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
|
|||||||
import { JwtAuthGuard } from '../Auth/Jwt.guard';
|
import { JwtAuthGuard } from '../Auth/Jwt.guard';
|
||||||
import { UserIpInterceptor } from '@/interceptors/user-ip.interceptor';
|
import { UserIpInterceptor } from '@/interceptors/user-ip.interceptor';
|
||||||
import { TenancyGlobalMiddleware } from '../Tenancy/TenancyGlobal.middleware';
|
import { TenancyGlobalMiddleware } from '../Tenancy/TenancyGlobal.middleware';
|
||||||
|
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||||
|
import { TransformerModule } from '../Transformer/Transformer.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -100,6 +102,7 @@ import { TenancyGlobalMiddleware } from '../Tenancy/TenancyGlobal.middleware';
|
|||||||
},
|
},
|
||||||
AppService,
|
AppService,
|
||||||
JwtStrategy,
|
JwtStrategy,
|
||||||
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ItemTransformer } from './Item.transformer';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class GetItemService {
|
export class GetItemService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(Item)
|
@Inject(Item.name)
|
||||||
private itemModel: typeof Item,
|
private itemModel: typeof Item,
|
||||||
private eventEmitter2: EventEmitter2,
|
private eventEmitter2: EventEmitter2,
|
||||||
private transformerInjectable: TransformerInjectable,
|
private transformerInjectable: TransformerInjectable,
|
||||||
|
|||||||
@@ -98,4 +98,48 @@ export class ItemsController extends TenantController {
|
|||||||
const itemId = parseInt(id, 10);
|
const itemId = parseInt(id, 10);
|
||||||
return this.itemsApplication.getItem(itemId);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@ import { EditItemService } from './EditItem.service';
|
|||||||
import { InactivateItem } from './InactivateItem.service';
|
import { InactivateItem } from './InactivateItem.service';
|
||||||
import { ActivateItemService } from './ActivateItem.service';
|
import { ActivateItemService } from './ActivateItem.service';
|
||||||
import { ItemsApplicationService } from './ItemsApplication.service';
|
import { ItemsApplicationService } from './ItemsApplication.service';
|
||||||
|
import { ItemTransactionsService } from './ItemTransactions.service';
|
||||||
|
import { GetItemService } from './GetItem.service';
|
||||||
|
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TenancyDatabaseModule],
|
imports: [TenancyDatabaseModule],
|
||||||
@@ -21,7 +24,10 @@ import { ItemsApplicationService } from './ItemsApplication.service';
|
|||||||
ActivateItemService,
|
ActivateItemService,
|
||||||
DeleteItemService,
|
DeleteItemService,
|
||||||
ItemsApplicationService,
|
ItemsApplicationService,
|
||||||
|
GetItemService,
|
||||||
|
ItemTransactionsService,
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
|
TransformerInjectable,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ItemsModule {}
|
export class ItemsModule {}
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import { Knex } from 'knex';
|
|||||||
import { InactivateItem } from './InactivateItem.service';
|
import { InactivateItem } from './InactivateItem.service';
|
||||||
import { ActivateItemService } from './ActivateItem.service';
|
import { ActivateItemService } from './ActivateItem.service';
|
||||||
import { GetItemService } from './GetItem.service';
|
import { GetItemService } from './GetItem.service';
|
||||||
|
import { ItemTransactionsService } from './ItemTransactions.service';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
export class ItemsApplicationService {
|
export class ItemsApplicationService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly createItemService: CreateItemService,
|
private readonly createItemService: CreateItemService,
|
||||||
@@ -16,6 +19,7 @@ export class ItemsApplicationService {
|
|||||||
private readonly activateItemService: ActivateItemService,
|
private readonly activateItemService: ActivateItemService,
|
||||||
private readonly inactivateItemService: InactivateItem,
|
private readonly inactivateItemService: InactivateItem,
|
||||||
private readonly getItemService: GetItemService,
|
private readonly getItemService: GetItemService,
|
||||||
|
private readonly itemTransactionsService: ItemTransactionsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,4 +85,40 @@ export class ItemsApplicationService {
|
|||||||
async getItem(itemId: number): Promise<any> {
|
async getItem(itemId: number): Promise<any> {
|
||||||
return this.getItemService.getItem(itemId);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import * as F from 'fp-ts/function';
|
import * as F from 'fp-ts/function';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { SearchableModel } from '@/modules/Search/SearchableMdel';
|
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 quantityOnHand: number;
|
||||||
public readonly name: string;
|
public readonly name: string;
|
||||||
public readonly active: boolean;
|
public readonly active: boolean;
|
||||||
|
|||||||
231
packages/server-nest/src/modules/Items/models/ItemEntry.ts
Normal file
231
packages/server-nest/src/modules/Items/models/ItemEntry.ts
Normal 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',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -6,9 +6,12 @@ import { TenantModel } from '@/modules/System/models/TenantModel';
|
|||||||
import { SystemKnexConnection } from '../SystemDB/SystemDB.constants';
|
import { SystemKnexConnection } from '../SystemDB/SystemDB.constants';
|
||||||
import { SystemModelsConnection } from './SystemModels.constants';
|
import { SystemModelsConnection } from './SystemModels.constants';
|
||||||
import { SystemUser } from '../models/SystemUser';
|
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) => {
|
const modelProviders = models.map((model) => {
|
||||||
|
console.log(model.name, model, 'model.name');
|
||||||
return {
|
return {
|
||||||
provide: model.name,
|
provide: model.name,
|
||||||
useValue: model,
|
useValue: model,
|
||||||
@@ -23,7 +26,7 @@ const providers = [
|
|||||||
useFactory: async (systemKnex: Knex) => {
|
useFactory: async (systemKnex: Knex) => {
|
||||||
Model.knex(systemKnex);
|
Model.knex(systemKnex);
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ export class TenantMetadata extends BaseModel {
|
|||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
*/
|
*/
|
||||||
static get tableName() {
|
static tableName = 'tenants_metadata';
|
||||||
return 'tenants_metadata';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Virtual attributes.
|
* Virtual attributes.
|
||||||
|
|||||||
@@ -2,19 +2,18 @@ import { BaseModel } from '@/models/Model';
|
|||||||
import { Model } from 'objection';
|
import { Model } from 'objection';
|
||||||
import { TenantMetadata } from './TenantMetadataModel';
|
import { TenantMetadata } from './TenantMetadataModel';
|
||||||
|
|
||||||
|
|
||||||
export class TenantModel extends BaseModel {
|
export class TenantModel extends BaseModel {
|
||||||
public readonly organizationId: string;
|
public readonly organizationId: string;
|
||||||
public readonly initializedAt: string;
|
public readonly initializedAt: string;
|
||||||
public readonly seededAt: boolean;
|
public readonly seededAt: boolean;
|
||||||
public readonly builtAt: string;
|
public readonly builtAt: string;
|
||||||
public readonly metadata: TenantMetadata;
|
public readonly metadata: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
*/
|
*/
|
||||||
static get tableName() {
|
static tableName = 'tenants';
|
||||||
return 'tenants';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relations mappings.
|
* Relations mappings.
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ export class TenancyContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the current system user.
|
||||||
* @returns
|
* @returns {Promise<SystemUser>}
|
||||||
*/
|
*/
|
||||||
getSystemUser() {
|
getSystemUser() {
|
||||||
// Get the user from the request headers.
|
// Get the user from the request headers.
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import { TENANCY_DB_CONNECTION } from '../TenancyDB/TenancyDB.constants';
|
|||||||
|
|
||||||
import { Item } from '../../../modules/Items/models/Item';
|
import { Item } from '../../../modules/Items/models/Item';
|
||||||
import { Account } from '@/modules/Accounts/models/Account';
|
import { Account } from '@/modules/Accounts/models/Account';
|
||||||
import { TenantModel } from '@/modules/System/models/TenantModel';
|
import { ItemEntry } from '@/modules/Items/models/ItemEntry';
|
||||||
import { TenantMetadata } from '@/modules/System/models/TenantMetadataModel';
|
|
||||||
|
|
||||||
const models = [Item, Account, TenantModel, TenantMetadata];
|
const models = [Item, Account, ItemEntry];
|
||||||
|
|
||||||
const modelProviders = models.map((model) => {
|
const modelProviders = models.map((model) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -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 {}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { I18nService } from 'nestjs-i18n';
|
import { I18nService } from 'nestjs-i18n';
|
||||||
import { Transformer } from './Transformer';
|
import { Transformer } from './Transformer';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Global, Injectable } from '@nestjs/common';
|
||||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
import { TransformerContext } from './Transformer.types';
|
import { TransformerContext } from './Transformer.types';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user