refactor: reports to nestjs

This commit is contained in:
Ahmed Bouhuolia
2025-01-21 23:29:31 +02:00
parent 2e1c57438c
commit 9a5110aa38
20 changed files with 141 additions and 68 deletions

View File

@@ -8,7 +8,7 @@ import { TransactionsByVendorModule } from './modules/TransactionsByVendor/Trans
import { TransactionsByCustomerModule } from './modules/TransactionsByCustomer/TransactionsByCustomer.module';
import { TransactionsByReferenceModule } from './modules/TransactionsByReference/TransactionByReference.module';
import { ARAgingSummaryModule } from './modules/ARAgingSummary/ARAgingSummary.module';
import { APAgingSummaryModule } from './modules/APAgingSummary/APAgingSummary.module';
// import { APAgingSummaryModule } from './modules/APAgingSummary/APAgingSummary.module';
import { InventoryItemDetailsModule } from './modules/InventoryItemDetails/InventoryItemDetails.module';
import { InventoryValuationSheetModule } from './modules/InventoryValuationSheet/InventoryValuationSheet.module';
@@ -24,7 +24,7 @@ import { InventoryValuationSheetModule } from './modules/InventoryValuationSheet
TransactionsByCustomerModule,
TransactionsByReferenceModule,
ARAgingSummaryModule,
APAgingSummaryModule,
// APAgingSummaryModule,
InventoryItemDetailsModule,
InventoryValuationSheetModule,
],

View File

@@ -3,12 +3,14 @@ import { APAgingSummaryApplication } from './APAgingSummaryApplication';
import { IAPAgingSummaryQuery } from './APAgingSummary.types';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { ApiOperation } from '@nestjs/swagger';
@Controller('reports/payable-aging-summary')
export class APAgingSummaryController {
constructor(private readonly APAgingSummaryApp: APAgingSummaryApplication) {}
@Get()
@ApiOperation({ summary: 'Get payable aging summary' })
public async get(
@Query() filter: IAPAgingSummaryQuery,
@Res() res: Response,

View File

@@ -5,13 +5,16 @@ import { ARAgingSummaryApplication } from './ARAgingSummaryApplication';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
@Controller('reports/receivable-aging-summary')
@ApiTags('reports')
@PublicRoute()
export class ARAgingSummaryController {
constructor(private readonly ARAgingSummaryApp: ARAgingSummaryApplication) {}
@Get()
@ApiOperation({ summary: 'Get receivable aging summary' })
public async get(
@Query() filter: IARAgingSummaryQuery,
@Res() res: Response,

View File

@@ -3,7 +3,7 @@ import { ICustomerBalanceSummaryQuery } from './CustomerBalanceSummary.types';
import { CustomerBalanceSummaryApplication } from './CustomerBalanceSummaryApplication';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/customer-balance-summary')
@ApiTags('reports')
@@ -14,6 +14,7 @@ export class CustomerBalanceSummaryController {
@Get()
@ApiResponse({ status: 200, description: 'Customer balance summary report' })
@ApiOperation({ summary: 'Get customer balance summary report' })
async customerBalanceSummary(
@Query() filter: ICustomerBalanceSummaryQuery,
@Res() res: Response,

View File

@@ -4,7 +4,7 @@ import { IGeneralLedgerSheetQuery } from './GeneralLedger.types';
import { GeneralLedgerApplication } from './GeneralLedgerApplication';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/general-ledger')
@ApiTags('reports')
@@ -15,6 +15,7 @@ export class GeneralLedgerController {
@Get()
@ApiResponse({ status: 200, description: 'General ledger report' })
@ApiOperation({ summary: 'Get general ledger report' })
public async getGeneralLedger(
@Query() query: IGeneralLedgerSheetQuery,
@Res() res: Response,

View File

@@ -1,15 +1,21 @@
import { Controller, Headers, Query, Res } from '@nestjs/common';
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
import { InventoryItemDetailsApplication } from './InventoryItemDetailsApplication';
import { IInventoryDetailsQuery } from './InventoryItemDetails.types';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
@Controller('reports/inventory-item-details')
@PublicRoute()
@ApiTags('reports')
export class InventoryItemDetailsController {
constructor(
private readonly inventoryItemDetailsApp: InventoryItemDetailsApplication,
) {}
@Get('/')
@ApiOperation({ summary: 'Get inventory item details' })
async inventoryItemDetails(
@Query() query: IInventoryDetailsQuery,
@Res() res: Response,

View File

@@ -5,14 +5,23 @@ import { InventoryDetailsService } from './InventoryItemDetails.service';
import { InventoryDetailsTableInjectable } from './InventoryItemDetailsTableInjectable';
import { InventoryItemDetailsExportInjectable } from './InventoryItemDetailsExportInjectable';
import { InventoryItemDetailsApplication } from './InventoryItemDetailsApplication';
import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository';
import { InventoryDetailsMetaInjectable } from './InventoryItemDetailsMeta';
import { FinancialSheetCommonModule } from '../../common/FinancialSheetCommon.module';
import { InventoryCostModule } from '@/modules/InventoryCost/InventoryCost.module';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
@Module({
imports: [FinancialSheetCommonModule, InventoryCostModule],
providers: [
InventoryItemDetailsApplication,
InventoryItemDetailsExportInjectable,
InventoryDetailsTableInjectable,
InventoryDetailsService,
InventoryDetailsTablePdf,
InventoryItemDetailsRepository,
InventoryDetailsMetaInjectable,
TenancyContext,
],
controllers: [InventoryItemDetailsController],
})

View File

@@ -29,6 +29,11 @@ export class InventoryDetailsService {
...getInventoryItemDetailsDefaultQuery(),
...query,
};
// Initialize the inventory item details repository.
this.inventoryItemDetailsRepository.setFilter(filter);
await this.inventoryItemDetailsRepository.asyncInit();
// Inventory details report mapper.
const inventoryDetailsInstance = new InventoryDetails(
filter,

View File

@@ -29,7 +29,6 @@ export class InventoryDetails extends FinancialSheet {
readonly repository: InventoryItemDetailsRepository;
readonly query: IInventoryDetailsQuery;
readonly numberFormat: INumberFormatQuery;
readonly items: ModelObject<Item>[];
readonly i18n: I18nService;
/**
@@ -112,9 +111,9 @@ export class InventoryDetails extends FinancialSheet {
* @param {IInventoryDetailsItemTransaction[]} transactions
* @returns {IInventoryDetailsItemTransaction[]}
*/
public mapAccumTransactionsRunningQuantity(
public mapAccumTransactionsRunningQuantity = (
transactions: IInventoryDetailsItemTransaction[],
): IInventoryDetailsItemTransaction[] {
): IInventoryDetailsItemTransaction[] => {
const initial = this.getNumberMeta(0);
const mapAccumAppender = (a, b) => {
@@ -125,20 +124,21 @@ export class InventoryDetails extends FinancialSheet {
return [accum, accum];
};
return R.mapAccum(
// @ts-ignore
mapAccumAppender,
{ runningQuantity: initial },
transactions,
)[1];
}
};
/**
* Accumulate and mapping running valuation on transactions.
* @param {IInventoryDetailsItemTransaction[]} transactions
* @returns {IInventoryDetailsItemTransaction}
*/
public mapAccumTransactionsRunningValuation(
public mapAccumTransactionsRunningValuation = (
transactions: IInventoryDetailsItemTransaction[],
): IInventoryDetailsItemTransaction[] {
): IInventoryDetailsItemTransaction[] => {
const initial = this.getNumberMeta(0);
const mapAccumAppender = (a, b) => {
@@ -150,11 +150,12 @@ export class InventoryDetails extends FinancialSheet {
return [accum, accum];
};
return R.mapAccum(
// @ts-ignore
mapAccumAppender,
{ runningValuation: initial },
transactions,
)[1];
}
};
/**
* Retrieve the inventory transaction total.
@@ -170,15 +171,13 @@ export class InventoryDetails extends FinancialSheet {
};
/**
* Mappes the item transaction to inventory item transaction node.
* @param {IItem} item
* @param {IInvetoryTransaction} transaction
* Maps the item transaction to inventory item transaction node.
* @param {IInvetoryTransaction} transaction - The inventory transaction.
* @returns {IInventoryDetailsItemTransaction}
*/
public itemTransactionMapper(
item: ModelObject<Item>,
public itemTransactionMapper = (
transaction: ModelObject<InventoryTransaction>,
): IInventoryDetailsItemTransaction {
): IInventoryDetailsItemTransaction => {
const total = this.getTransactionTotal(transaction);
const amountMovement = this.adjustAmountMovement(transaction.direction);
@@ -217,7 +216,7 @@ export class InventoryDetails extends FinancialSheet {
runningQuantity: this.getNumberMeta(0),
runningValuation: this.getNumberMeta(0),
};
}
};
/**
* Retrieve the inventory transcations by item id.
@@ -228,7 +227,7 @@ export class InventoryDetails extends FinancialSheet {
itemId: number,
): ModelObject<InventoryTransaction>[] {
return defaultTo(
this.repository.inventoryTransactionsByItemId.get(itemId),
this.repository.inventoryTransactionsByItemId.get(itemId.toString()),
[],
);
}
@@ -240,13 +239,13 @@ export class InventoryDetails extends FinancialSheet {
*/
public getItemTransactions(
item: ModelObject<Item>,
): ModelObject<InventoryTransaction>[] {
): IInventoryDetailsItemTransaction[] {
const transactions = this.getInventoryTransactionsByItemId(item.id);
return R.compose(
this.mapAccumTransactionsRunningQuantity.bind(this),
this.mapAccumTransactionsRunningValuation.bind(this),
R.map(R.curry(this.itemTransactionMapper.bind(this))(item)),
return R.pipe(
R.map(this.itemTransactionMapper),
this.mapAccumTransactionsRunningValuation,
this.mapAccumTransactionsRunningQuantity,
)(transactions);
}
@@ -261,11 +260,11 @@ export class InventoryDetails extends FinancialSheet {
*/
public itemTransactionsMapper(
item: ModelObject<Item>,
): (
): Array<
| IInventoryDetailsItemTransaction
| IInventoryDetailsOpening
| IInventoryDetailsClosing
)[] {
> {
const transactions = this.getItemTransactions(item);
const openingValuation = this.getItemOpeingValuation(item);
const closingValuation = this.getItemClosingValuation(
@@ -280,7 +279,11 @@ export class InventoryDetails extends FinancialSheet {
R.concat(transactions),
R.when(R.always(isItemHasOpeningBalance), R.prepend(openingValuation)),
R.when(R.always(hasTransactions), R.append(closingValuation)),
)([]);
)([]) as Array<
| IInventoryDetailsItemTransaction
| IInventoryDetailsOpening
| IInventoryDetailsClosing
>;
}
/**
@@ -300,9 +303,8 @@ export class InventoryDetails extends FinancialSheet {
public getItemOpeingValuation(
item: ModelObject<Item>,
): IInventoryDetailsOpening {
const openingBalance = this.repository.openingBalanceTransactionsByItemId.get(
item.id,
);
const openingBalance =
this.repository.openingBalanceTransactionsByItemId.get(item.id);
const quantity = defaultTo(get(openingBalance, 'quantity'), 0);
const value = defaultTo(get(openingBalance, 'value'), 0);
@@ -321,9 +323,9 @@ export class InventoryDetails extends FinancialSheet {
*/
public getItemClosingValuation(
item: ModelObject<Item>,
transactions: ModelObject<InventoryTransaction>[],
transactions: IInventoryDetailsItemTransaction[],
openingValuation: IInventoryDetailsOpening,
): IInventoryDetailsOpening {
): IInventoryDetailsClosing {
const value = sumBy(transactions, 'valueMovement.number');
const quantity = sumBy(transactions, 'quantityMovement.number');
const profitMargin = sumBy(transactions, 'profitMargin.number');
@@ -374,7 +376,9 @@ export class InventoryDetails extends FinancialSheet {
* @returns {boolean}
*/
public isItemNodeHasTransactions(item: IInventoryDetailsItem) {
return !!this.repository.inventoryTransactionsByItemId.get(item.id);
return !!this.repository.inventoryTransactionsByItemId.get(
item.id?.toString(),
);
}
/**
@@ -383,7 +387,9 @@ export class InventoryDetails extends FinancialSheet {
* @return {boolean}
*/
public isFilterNode(item: IInventoryDetailsItem): boolean {
// @ts-ignore
return R.ifElse(
// @ts-ignore
R.curry(this.isNodeTypeEquals)(INodeTypes.ITEM),
this.isItemNodeHasTransactions.bind(this),
R.always(true),
@@ -410,6 +416,7 @@ export class InventoryDetails extends FinancialSheet {
* @returns {IInventoryDetailsItem[]}
*/
public itemsNodes(items: ModelObject<Item>[]): IInventoryDetailsItem[] {
// @ts-ignore
return R.compose(
this.filterItemsNodes.bind(this),
R.map(this.itemsNodeMapper.bind(this)),
@@ -421,6 +428,6 @@ export class InventoryDetails extends FinancialSheet {
* @returns {IInventoryDetailsData}
*/
public reportData(): IInventoryDetailsData {
return this.itemsNodes(this.items);
return this.itemsNodes(this.repository.items);
}
}

View File

@@ -41,6 +41,7 @@ export interface IInventoryDetailsOpening {
export interface IInventoryDetailsClosing
extends Omit<IInventoryDetailsOpening, 'nodeType'> {
nodeType: 'CLOSING_ENTRY';
profitMargin: IInventoryDetailsNumber;
}
export interface IInventoryDetailsItem {

View File

@@ -31,12 +31,15 @@ export class InventoryItemDetailsRepository {
* @param {ModelObject<InventoryTransaction>[]} openingBalanceTransactions - The opening balance transactions.
*/
openingBalanceTransactions: ModelObject<InventoryTransaction>[];
/**
* The opening balance transactions by item id.
* @param {Map<number, ModelObject<InventoryTransaction>>} openingBalanceTransactionsByItemId - The opening balance transactions by item id.
*/
openingBalanceTransactionsByItemId: Map<number, ModelObject<InventoryTransaction>>;
openingBalanceTransactionsByItemId: Map<
number,
ModelObject<InventoryTransaction>
>;
/**
* The inventory transactions.
@@ -46,9 +49,12 @@ export class InventoryItemDetailsRepository {
/**
* The inventory transactions by item id.
* @param {Map<number, ModelObject<InventoryTransaction>>} inventoryTransactionsByItemId - The inventory transactions by item id.
* @param {Map<string, ModelObject<InventoryTransaction>>} inventoryTransactionsByItemId - The inventory transactions by item id.
*/
inventoryTransactionsByItemId: Map<number, ModelObject<InventoryTransaction>[]>;
inventoryTransactionsByItemId: Map<
string,
ModelObject<InventoryTransaction>[]
>;
/**
* The filter.
@@ -100,7 +106,7 @@ export class InventoryItemDetailsRepository {
this.openingBalanceTransactions = openingBalanceTransactions;
this.openingBalanceTransactionsByItemId = transformToMapKeyValue(
openingBalanceTransactions,
'itemId'
'itemId',
);
}
@@ -115,7 +121,7 @@ export class InventoryItemDetailsRepository {
this.inventoryTransactions = inventoryTransactions;
this.inventoryTransactionsByItemId = transformToMapBy(
inventoryTransactions,
'itemId'
'itemId',
);
}

View File

@@ -9,8 +9,12 @@ import {
import { I18nService } from 'nestjs-i18n';
import { IInventoryDetailsData } from './InventoryItemDetails.types';
import { tableRowMapper } from '../../utils/Table.utils';
import { ITableColumn, ITableRow } from '../../types/Table.types';
import mapValuesDeep from 'deepdash/es/mapValuesDeep';
import {
IColumnMapperMeta,
ITableColumn,
ITableRow,
} from '../../types/Table.types';
import { mapValuesDeep } from '@/utils/deepdash';
enum IROW_TYPE {
ITEM = 'ITEM',
@@ -53,7 +57,7 @@ export class InventoryItemDetailsTable {
* @returns {ITableRow}
*/
private itemTransactionNodeMapper = (
transaction: IInventoryDetailsItemTransaction
transaction: IInventoryDetailsItemTransaction,
) => {
const columns = [
{ key: 'date', accessor: 'date.formattedDate' },
@@ -84,15 +88,15 @@ export class InventoryItemDetailsTable {
* @returns {ITableRow}
*/
private openingNodeMapper = (
transaction: IInventoryDetailsOpening
transaction: IInventoryDetailsOpening,
): ITableRow => {
const columns = [
const columns: Array<IColumnMapperMeta> = [
{ key: 'date', accessor: 'date.formattedDate' },
{ key: 'closing', value: this.i18n.t('Opening balance') },
{ key: 'empty' },
{ key: 'empty', value: '' },
{ key: 'quantity', accessor: 'quantity.formattedNumber' },
{ key: 'empty' },
{ key: 'empty' },
{ key: 'empty', value: '' },
{ key: 'empty', value: '' },
{ key: 'value', accessor: 'value.formattedNumber' },
];
return tableRowMapper(transaction, columns, {
@@ -106,19 +110,18 @@ export class InventoryItemDetailsTable {
* @returns {ITableRow}
*/
private closingNodeMapper = (
transaction: IInventoryDetailsClosing
transaction: IInventoryDetailsClosing,
): ITableRow => {
const columns = [
const columns: Array<IColumnMapperMeta> = [
{ key: 'date', accessor: 'date.formattedDate' },
{ key: 'closing', value: this.i18n.t('Closing balance') },
{ key: 'empty' },
{ key: 'empty', value: '' },
{ key: 'quantity', accessor: 'quantity.formattedNumber' },
{ key: 'empty' },
{ key: 'empty' },
{ key: 'empty', value: '' },
{ key: 'empty', value: '' },
{ key: 'value', accessor: 'value.formattedNumber' },
{ key: 'profitMargin', accessor: 'profitMargin.formattedNumber' },
];
return tableRowMapper(transaction, columns, {
rowTypes: [IROW_TYPE.CLOSING_ENTRY],
});
@@ -132,7 +135,7 @@ export class InventoryItemDetailsTable {
*/
private isNodeTypeEquals = (
type: string,
node: IInventoryDetailsNode
node: IInventoryDetailsNode,
): boolean => {
return node.nodeType === type;
};
@@ -143,20 +146,23 @@ export class InventoryItemDetailsTable {
* @return {ITableRow}
*/
private itemMapper = (node: IInventoryDetailsNode): ITableRow => {
// @ts-ignore
return R.compose(
R.when(
// @ts-ignore
R.curry(this.isNodeTypeEquals)('OPENING_ENTRY'),
this.openingNodeMapper
this.openingNodeMapper,
),
R.when(
// @ts-ignore
R.curry(this.isNodeTypeEquals)('CLOSING_ENTRY'),
this.closingNodeMapper
this.closingNodeMapper,
),
R.when(R.curry(this.isNodeTypeEquals)('item'), this.itemNodeMapper),
R.when(
R.curry(this.isNodeTypeEquals)('transaction'),
this.itemTransactionNodeMapper
)
this.itemTransactionNodeMapper,
),
)(node);
};
@@ -166,6 +172,7 @@ export class InventoryItemDetailsTable {
* @returns {ITableRow[]}
*/
private itemsMapper = (items: IInventoryDetailsItem[]): ITableRow[] => {
// @ts-ignore
return mapValuesDeep(items, this.itemMapper, MAP_CONFIG);
};

View File

@@ -1,4 +1,5 @@
import { IInventoryDetailsQuery } from "./InventoryItemDetails.types";
import * as moment from 'moment';
import { IInventoryDetailsQuery } from './InventoryItemDetails.types';
export const HtmlTableCustomCss = `
table tr.row-type--item td,
@@ -27,7 +28,6 @@ export const getInventoryItemDetailsDefaultQuery =
};
};
export const MAP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
export enum INodeTypes {

View File

@@ -4,7 +4,12 @@ import { PurchasesByItemsApplication } from './PurchasesByItemsApplication';
import { IPurchasesByItemsReportQuery } from './types/PurchasesByItems.types';
import { AcceptType } from '@/constants/accept-type';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import {
ApiOperation,
ApiResponse,
ApiResponseProperty,
ApiTags,
} from '@nestjs/swagger';
@Controller('/reports/purchases-by-items')
@PublicRoute()
@@ -16,6 +21,7 @@ export class PurchasesByItemReportController {
@Get()
@ApiResponse({ status: 200, description: 'Purchases by items report' })
@ApiOperation({ summary: 'Get purchases by items report' })
async purchasesByItems(
@Query() filter: IPurchasesByItemsReportQuery,
@Res() res: Response,

View File

@@ -1,9 +1,17 @@
import { Body, Controller, Get, Headers, Query, Req, Res } from '@nestjs/common';
import {
Body,
Controller,
Get,
Headers,
Query,
Req,
Res,
} from '@nestjs/common';
import { ISalesByItemsReportQuery } from './SalesByItems.types';
import { AcceptType } from '@/constants/accept-type';
import { SalesByItemsApplication } from './SalesByItemsApplication';
import { Response } from 'express';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/sales-by-items')
@ApiTags('reports')
@@ -12,6 +20,7 @@ export class SalesByItemsController {
@Get()
@ApiResponse({ status: 200, description: 'Sales by items report' })
@ApiOperation({ summary: 'Get sales by items report' })
public async salesByitems(
@Query() filter: ISalesByItemsReportQuery,
@Res() res: Response,

View File

@@ -1,5 +1,5 @@
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { ITransactionsByCustomersFilter } from './TransactionsByCustomer.types';
import { TransactionsByCustomerApplication } from './TransactionsByCustomersApplication';
import { AcceptType } from '@/constants/accept-type';
@@ -7,6 +7,7 @@ import { Response } from 'express';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
@Controller('/reports/transactions-by-customers')
@ApiTags('reports')
@PublicRoute()
export class TransactionsByCustomerController {
constructor(

View File

@@ -2,8 +2,10 @@ import { Controller, Get, Query } from '@nestjs/common';
import { TransactionsByReferenceApplication } from './TransactionsByReferenceApplication';
import { ITransactionsByReferenceQuery } from './TransactionsByReference.types';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('reports/transactions-by-reference')
@ApiTags('reports')
@PublicRoute()
export class TransactionsByReferenceController {
constructor(
@@ -11,6 +13,8 @@ export class TransactionsByReferenceController {
) {}
@Get()
@ApiResponse({ status: 200, description: 'Transactions by reference' })
@ApiOperation({ summary: 'Get transactions by reference' })
async getTransactionsByReference(
@Query() query: ITransactionsByReferenceQuery,
) {

View File

@@ -3,10 +3,11 @@ import { ITransactionsByVendorsFilter } from './TransactionsByVendor.types';
import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express';
import { TransactionsByVendorApplication } from './TransactionsByVendorApplication';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
@Controller('/reports/transactions-by-vendors')
@ApiTags('reports')
@PublicRoute()
export class TransactionsByVendorController {
constructor(

View File

@@ -0,0 +1 @@
export class TrialBalanceSheetResponse {}