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 { TransactionsByCustomerModule } from './modules/TransactionsByCustomer/TransactionsByCustomer.module';
import { TransactionsByReferenceModule } from './modules/TransactionsByReference/TransactionByReference.module'; import { TransactionsByReferenceModule } from './modules/TransactionsByReference/TransactionByReference.module';
import { ARAgingSummaryModule } from './modules/ARAgingSummary/ARAgingSummary.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 { InventoryItemDetailsModule } from './modules/InventoryItemDetails/InventoryItemDetails.module';
import { InventoryValuationSheetModule } from './modules/InventoryValuationSheet/InventoryValuationSheet.module'; import { InventoryValuationSheetModule } from './modules/InventoryValuationSheet/InventoryValuationSheet.module';
@@ -24,7 +24,7 @@ import { InventoryValuationSheetModule } from './modules/InventoryValuationSheet
TransactionsByCustomerModule, TransactionsByCustomerModule,
TransactionsByReferenceModule, TransactionsByReferenceModule,
ARAgingSummaryModule, ARAgingSummaryModule,
APAgingSummaryModule, // APAgingSummaryModule,
InventoryItemDetailsModule, InventoryItemDetailsModule,
InventoryValuationSheetModule, InventoryValuationSheetModule,
], ],

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ import { IGeneralLedgerSheetQuery } from './GeneralLedger.types';
import { GeneralLedgerApplication } from './GeneralLedgerApplication'; import { GeneralLedgerApplication } from './GeneralLedgerApplication';
import { AcceptType } from '@/constants/accept-type'; import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express'; import { Response } from 'express';
import { ApiResponse, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/general-ledger') @Controller('/reports/general-ledger')
@ApiTags('reports') @ApiTags('reports')
@@ -15,6 +15,7 @@ export class GeneralLedgerController {
@Get() @Get()
@ApiResponse({ status: 200, description: 'General ledger report' }) @ApiResponse({ status: 200, description: 'General ledger report' })
@ApiOperation({ summary: 'Get general ledger report' })
public async getGeneralLedger( public async getGeneralLedger(
@Query() query: IGeneralLedgerSheetQuery, @Query() query: IGeneralLedgerSheetQuery,
@Res() res: Response, @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 { InventoryItemDetailsApplication } from './InventoryItemDetailsApplication';
import { IInventoryDetailsQuery } from './InventoryItemDetails.types'; import { IInventoryDetailsQuery } from './InventoryItemDetails.types';
import { AcceptType } from '@/constants/accept-type'; import { AcceptType } from '@/constants/accept-type';
import { Response } from 'express'; import { Response } from 'express';
import { PublicRoute } from '@/modules/Auth/Jwt.guard';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
@Controller('reports/inventory-item-details') @Controller('reports/inventory-item-details')
@PublicRoute()
@ApiTags('reports')
export class InventoryItemDetailsController { export class InventoryItemDetailsController {
constructor( constructor(
private readonly inventoryItemDetailsApp: InventoryItemDetailsApplication, private readonly inventoryItemDetailsApp: InventoryItemDetailsApplication,
) {} ) {}
@Get('/')
@ApiOperation({ summary: 'Get inventory item details' })
async inventoryItemDetails( async inventoryItemDetails(
@Query() query: IInventoryDetailsQuery, @Query() query: IInventoryDetailsQuery,
@Res() res: Response, @Res() res: Response,

View File

@@ -5,14 +5,23 @@ import { InventoryDetailsService } from './InventoryItemDetails.service';
import { InventoryDetailsTableInjectable } from './InventoryItemDetailsTableInjectable'; import { InventoryDetailsTableInjectable } from './InventoryItemDetailsTableInjectable';
import { InventoryItemDetailsExportInjectable } from './InventoryItemDetailsExportInjectable'; import { InventoryItemDetailsExportInjectable } from './InventoryItemDetailsExportInjectable';
import { InventoryItemDetailsApplication } from './InventoryItemDetailsApplication'; 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({ @Module({
imports: [FinancialSheetCommonModule, InventoryCostModule],
providers: [ providers: [
InventoryItemDetailsApplication, InventoryItemDetailsApplication,
InventoryItemDetailsExportInjectable, InventoryItemDetailsExportInjectable,
InventoryDetailsTableInjectable, InventoryDetailsTableInjectable,
InventoryDetailsService, InventoryDetailsService,
InventoryDetailsTablePdf, InventoryDetailsTablePdf,
InventoryItemDetailsRepository,
InventoryDetailsMetaInjectable,
TenancyContext,
], ],
controllers: [InventoryItemDetailsController], controllers: [InventoryItemDetailsController],
}) })

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,12 @@ import { PurchasesByItemsApplication } from './PurchasesByItemsApplication';
import { IPurchasesByItemsReportQuery } from './types/PurchasesByItems.types'; import { IPurchasesByItemsReportQuery } from './types/PurchasesByItems.types';
import { AcceptType } from '@/constants/accept-type'; import { AcceptType } from '@/constants/accept-type';
import { PublicRoute } from '@/modules/Auth/Jwt.guard'; 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') @Controller('/reports/purchases-by-items')
@PublicRoute() @PublicRoute()
@@ -16,6 +21,7 @@ export class PurchasesByItemReportController {
@Get() @Get()
@ApiResponse({ status: 200, description: 'Purchases by items report' }) @ApiResponse({ status: 200, description: 'Purchases by items report' })
@ApiOperation({ summary: 'Get purchases by items report' })
async purchasesByItems( async purchasesByItems(
@Query() filter: IPurchasesByItemsReportQuery, @Query() filter: IPurchasesByItemsReportQuery,
@Res() res: Response, @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 { ISalesByItemsReportQuery } from './SalesByItems.types';
import { AcceptType } from '@/constants/accept-type'; import { AcceptType } from '@/constants/accept-type';
import { SalesByItemsApplication } from './SalesByItemsApplication'; import { SalesByItemsApplication } from './SalesByItemsApplication';
import { Response } from 'express'; import { Response } from 'express';
import { ApiResponse, ApiTags } from '@nestjs/swagger'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
@Controller('/reports/sales-by-items') @Controller('/reports/sales-by-items')
@ApiTags('reports') @ApiTags('reports')
@@ -12,6 +20,7 @@ export class SalesByItemsController {
@Get() @Get()
@ApiResponse({ status: 200, description: 'Sales by items report' }) @ApiResponse({ status: 200, description: 'Sales by items report' })
@ApiOperation({ summary: 'Get sales by items report' })
public async salesByitems( public async salesByitems(
@Query() filter: ISalesByItemsReportQuery, @Query() filter: ISalesByItemsReportQuery,
@Res() res: Response, @Res() res: Response,

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,8 @@
import { groupBy } from 'lodash'; import { groupBy } from 'lodash';
export const transformToMapBy = <T>(collection: T[], key: keyof T): Map<string, T[]> => { export const transformToMapBy = <T>(
collection: T[],
key: keyof T,
): Map<string, T[]> => {
return new Map(Object.entries(groupBy(collection, key))); return new Map(Object.entries(groupBy(collection, key)));
}; };