feat: add swagger docs

This commit is contained in:
Ahmed Bouhuolia
2025-06-16 15:53:00 +02:00
parent c4668d7d22
commit e057b4e2f0
22 changed files with 3532 additions and 13 deletions

View File

@@ -1,5 +1,11 @@
import { Controller, Get, Param, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
ApiTags,
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
} from '@nestjs/swagger';
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
@Controller('banking/recognized')
@@ -10,6 +16,20 @@ export class BankingRecognizedTransactionsController {
) {}
@Get(':recognizedTransactionId')
@ApiOperation({ summary: 'Get recognized transaction' })
@ApiParam({
name: 'recognizedTransactionId',
description: 'The ID of the recognized transaction',
type: 'number',
})
@ApiResponse({
status: 200,
description: 'Returns the recognized transaction details',
})
@ApiResponse({
status: 404,
description: 'Recognized transaction not found',
})
async getRecognizedTransaction(
@Param('recognizedTransactionId') recognizedTransactionId: number,
) {
@@ -19,7 +39,19 @@ export class BankingRecognizedTransactionsController {
}
@Get()
@ApiOperation({ summary: 'Get a list of recognized transactions' })
@ApiQuery({
name: 'query',
required: false,
description: 'Query parameters for filtering recognized transactions',
})
@ApiResponse({
status: 200,
description: 'Returns a list of recognized transactions',
})
async getRecognizedTransactions(@Query() query: any) {
return this.recognizedTransactionsApplication.getRecognizedTransactions(query);
return this.recognizedTransactionsApplication.getRecognizedTransactions(
query,
);
}
}

View File

@@ -1,7 +1,7 @@
import { IsArray, IsOptional } from "class-validator";
import { IsArray, IsOptional } from 'class-validator';
export class FinancialSheetBranchesQueryDto {
@IsArray()
@IsOptional()
branchesIds: Array<number>;
}
}

View File

@@ -4,6 +4,7 @@ import { AcceptType } from '@/constants/accept-type';
import { BalanceSheetApplication } from './BalanceSheetApplication';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { BalanceSheetQueryDto } from './BalanceSheet.dto';
import { BalanceSheetResponseExample } from './BalanceSheet.swagger';
@Controller('/reports/balance-sheet')
@ApiTags('Reports')
@@ -18,7 +19,11 @@ export class BalanceSheetStatementController {
*/
@Get('')
@ApiOperation({ summary: 'Get balance sheet statement' })
@ApiResponse({ status: 200, description: 'Balance sheet statement' })
@ApiResponse({
status: 200,
description: 'Balance sheet statement',
example: BalanceSheetResponseExample,
})
public async balanceSheet(
@Query() query: BalanceSheetQueryDto,
@Res({ passthrough: true }) res: Response,

View File

@@ -10,81 +10,165 @@ import {
ValidateNested,
} from 'class-validator';
import { FinancialSheetBranchesQueryDto } from '../../dtos/FinancialSheetBranchesQuery.dto';
import { ApiProperty } from '@nestjs/swagger';
export class BalanceSheetQueryDto extends FinancialSheetBranchesQueryDto {
@ApiProperty({
enum: ['total', 'date_periods'],
default: 'total',
description: 'Type of columns to display in the balance sheet',
})
@IsString()
@IsOptional()
@IsEnum(['total', 'date_periods'])
displayColumnsType: 'total' | 'date_periods' = 'total';
@ApiProperty({
enum: ['day', 'month', 'year'],
default: 'year',
description: 'Time period for column display',
})
@IsString()
@IsOptional()
@IsEnum(['day', 'month', 'year'])
displayColumnsBy: 'day' | 'month' | 'year' = 'year';
@ApiProperty({
description: 'Start date for the balance sheet period',
required: false,
})
@IsDateString()
@IsOptional()
fromDate: string;
@ApiProperty({
description: 'End date for the balance sheet period',
required: false,
})
@IsDateString()
@IsOptional()
toDate: string;
@ApiProperty({
type: NumberFormatQueryDto,
description: 'Number formatting options',
required: false,
})
@ValidateNested()
@Type(() => NumberFormatQueryDto)
@IsOptional()
numberFormat: NumberFormatQueryDto;
@ApiProperty({
description: 'Whether to include accounts with no transactions',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
noneTransactions: boolean;
@ApiProperty({
description: 'Whether to exclude zero balance accounts',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
noneZero: boolean;
@ApiProperty({
enum: ['cash', 'accrual'],
description: 'Accounting basis for the balance sheet',
required: false,
})
@IsString()
@IsOptional()
basis: 'cash' | 'accrual';
@ApiProperty({
description: 'Array of account IDs to include in the balance sheet',
type: [Number],
})
accountIds: number[];
@ApiProperty({
description: 'Whether to show percentage of column total',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
percentageOfColumn: boolean;
@ApiProperty({
description: 'Whether to show percentage of row total',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
percentageOfRow: boolean;
@ApiProperty({
description: 'Whether to include previous period data',
default: false,
required: false,
})
@IsBoolean()
@IsOptional()
@Transform(({ value }) => parseBoolean(value, false))
previousPeriod: boolean;
@ApiProperty({
description: 'Whether to show amount change from previous period',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
previousPeriodAmountChange: boolean;
@ApiProperty({
description: 'Whether to show percentage change from previous period',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
previousPeriodPercentageChange: boolean;
@ApiProperty({
description: 'Whether to include previous year data',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
previousYear: boolean;
@ApiProperty({
description: 'Whether to show amount change from previous year',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
previousYearAmountChange: boolean;
@ApiProperty({
description: 'Whether to show percentage change from previous year',
default: false,
required: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()

View File

@@ -0,0 +1,501 @@
export const BalanceSheetResponseExample = {
query: {
display_columns_type: 'total',
display_columns_by: 'year',
from_date: '2025-01-01',
to_date: '2025-06-16',
number_format: {
precision: 2,
divide_on1000: false,
show_zero: false,
format_money: 'total',
negative_format: 'mines',
},
none_zero: false,
none_transactions: false,
basis: 'cash',
account_ids: [],
percentage_of_column: false,
percentage_of_row: false,
previous_period: false,
previous_period_amount_change: false,
previous_period_percentage_change: false,
previous_year: false,
previous_year_amount_change: false,
previous_year_percentage_change: false,
},
data: [
{
name: 'Assets',
id: 'ASSETS',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -122623,
formatted_amount: '-$122,623.00',
currency_code: 'USD',
},
children: [
{
name: 'Current Asset',
id: 'CURRENT_ASSETS',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -122623,
formatted_amount: '-$122,623.00',
currency_code: 'USD',
},
children: [
{
name: 'Cash and cash equivalents',
id: 'CASH_EQUIVALENTS',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -500,
formatted_amount: '-$500.00',
currency_code: 'USD',
},
children: [
{
id: 1002,
index: 1,
name: 'Undeposited Funds',
code: '10003',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1003,
index: 1,
name: 'Petty Cash',
code: '10004',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1000,
index: 1,
name: 'Bank Account',
code: '10001',
total: {
amount: -500,
formatted_amount: '-500.00',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1001,
index: 1,
name: 'Saving Bank Account',
code: '10002',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1034,
index: null,
name: 'Chase - Plaid Checking',
code: '',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
{
name: 'Accounts Receivable',
id: 'ACCOUNTS_RECEIVABLE',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
children: [
{
id: 1006,
index: 1,
name: 'Accounts Receivable (A/R)',
code: '10007',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
{
name: 'Inventory',
id: 'INVENTORY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 1000,
formatted_amount: '$1,000.00',
currency_code: 'USD',
},
children: [
{
id: 1007,
index: 1,
name: 'Inventory Asset',
code: '10008',
total: {
amount: 1000,
formatted_amount: '1,000.00',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
{
name: 'Other current assets',
id: 'OTHER_CURRENT_ASSET',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -123123,
formatted_amount: '-$123,123.00',
currency_code: 'USD',
},
children: [
{
id: 1030,
index: 1,
name: 'Prepaid Expenses',
code: '100010',
total: {
amount: -123123,
formatted_amount: '-123,123.00',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
],
},
{
name: 'Fixed Asset',
id: 'FIXED_ASSET',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
children: [
{
id: 1004,
index: 1,
name: 'Computer Equipment',
code: '10005',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1005,
index: 1,
name: 'Office Equipment',
code: '10006',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
{
name: 'Non-Current Assets',
id: 'NON_CURRENT_ASSET',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
children: [],
},
],
},
{
name: 'Liabilities and Equity',
id: 'LIABILITY_EQUITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -122623,
formatted_amount: '-$122,623.00',
currency_code: 'USD',
},
children: [
{
name: 'Liabilities',
id: 'LIABILITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -8700,
formatted_amount: '-$8,700.00',
currency_code: 'USD',
},
children: [
{
name: 'Current Liabilties',
id: 'CURRENT_LIABILITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -8700,
formatted_amount: '-$8,700.00',
currency_code: 'USD',
},
children: [
{
id: 1008,
index: 1,
name: 'Accounts Payable (A/P)',
code: '20001',
total: {
amount: 1300,
formatted_amount: '1,300.00',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1013,
index: 1,
name: 'Tax Payable',
code: '20006',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1009,
index: 1,
name: 'Owner A Drawings',
code: '20002',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1010,
index: 1,
name: 'Loan',
code: '20003',
total: {
amount: -10000,
formatted_amount: '-10,000.00',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1011,
index: 1,
name: 'Opening Balance Liabilities',
code: '20004',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1012,
index: 1,
name: 'Revenue Received in Advance',
code: '20005',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1029,
index: 1,
name: 'Unearned Revenue',
code: '50005',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
],
},
{
name: 'Long-Term Liabilities',
id: 'LOGN_TERM_LIABILITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
children: [],
},
{
name: 'Non-Current Liabilities',
id: 'NON_CURRENT_LIABILITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
children: [],
},
],
},
{
name: 'Equity',
id: 'EQUITY',
node_type: 'AGGREGATE',
type: 'AGGREGATE',
total: {
amount: -113923,
formatted_amount: '-$113,923.00',
currency_code: 'USD',
},
children: [
{
id: 1014,
index: 1,
name: 'Retained Earnings',
code: '30001',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1015,
index: 1,
name: 'Opening Balance Equity',
code: '30002',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1016,
index: 1,
name: "Owner's Equity",
code: '30003',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 1017,
index: 1,
name: 'Drawings',
code: '30003',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
node_type: 'ACCOUNT',
children: [],
},
{
id: 'NET_INCOME',
name: 'Net Income',
node_type: 'NET_INCOME',
total: {
amount: -113923,
formatted_amount: '-$113,923.00',
currency_code: 'USD',
},
children: [],
},
],
},
],
},
],
meta: {
organization_name: 'BIGCAPITAL, INC',
base_currency: 'USD',
date_format: 'DD MMM yyyy',
is_cost_compute_running: false,
sheet_name: 'Balance Sheet Statement',
formatted_as_date: '2025/06/16',
formatted_date_range: 'As 2025/06/16',
},
};

View File

@@ -10,39 +10,84 @@ import { FinancialSheetBranchesQueryDto } from '../../dtos/FinancialSheetBranche
import { NumberFormatQueryDto } from '@/modules/BankingTransactions/dtos/NumberFormatQuery.dto';
import { Transform, Type } from 'class-transformer';
import { parseBoolean } from '@/utils/parse-boolean';
import { ApiProperty } from '@nestjs/swagger';
export class CashFlowStatementQueryDto extends FinancialSheetBranchesQueryDto {
@ApiProperty({
description: 'Start date for the cash flow statement period',
required: false,
type: Date,
})
@IsDateString()
@IsOptional()
fromDate: Date | string;
@ApiProperty({
description: 'End date for the cash flow statement period',
required: false,
type: Date,
})
@IsDateString()
@IsOptional()
toDate: Date | string;
@ApiProperty({
description: 'Display columns by time period',
required: false,
enum: ['day', 'month', 'year'],
default: 'year',
})
@IsString()
@IsOptional()
@IsEnum(['day', 'month', 'year'])
displayColumnsBy: 'day' | 'month' | 'year' = 'year';
@ApiProperty({
description: 'Type of column display',
required: false,
enum: ['total', 'date_periods'],
default: 'total',
})
@IsEnum(['total', 'date_periods'])
@IsOptional()
displayColumnsType: 'total' | 'date_periods' = 'total';
@ApiProperty({
description: 'Filter out zero values',
required: false,
type: Boolean,
default: false,
})
@Transform(({ value }) => parseBoolean(value, false))
@IsBoolean()
@IsOptional()
noneZero: boolean;
@ApiProperty({
description: 'Filter out transactions',
required: false,
type: Boolean,
default: false,
})
@Transform(({ value }) => parseBoolean(value, false))
@IsBoolean()
@IsOptional()
noneTransactions: boolean;
@ApiProperty({
description: 'Number format configuration',
required: true,
type: NumberFormatQueryDto,
})
@ValidateNested()
@Type(() => NumberFormatQueryDto)
numberFormat: NumberFormatQueryDto;
@ApiProperty({
description: 'Basis for the cash flow statement',
required: false,
type: String,
})
@IsString()
@IsOptional()
basis: string;

View File

@@ -4,6 +4,7 @@ import { AcceptType } from '@/constants/accept-type';
import { CashflowSheetApplication } from './CashflowSheetApplication';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CashFlowStatementQueryDto } from './CashFlowStatementQuery.dto';
import { CashflowStatementResponseExample } from './CashflowStatement.swagger';
@Controller('reports/cashflow-statement')
@ApiTags('Reports')
@@ -11,7 +12,11 @@ export class CashflowController {
constructor(private readonly cashflowSheetApp: CashflowSheetApplication) {}
@Get()
@ApiResponse({ status: 200, description: 'Cashflow statement report' })
@ApiResponse({
status: 200,
description: 'Cashflow statement report',
example: CashflowStatementResponseExample,
})
@ApiOperation({ summary: 'Get cashflow statement report' })
async getCashflow(
@Query() query: CashFlowStatementQueryDto,
@@ -20,7 +25,7 @@ export class CashflowController {
) {
// Retrieves the json table format.
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
return this.cashflowSheetApp.table(query);
return this.cashflowSheetApp.table(query);
// Retrieves the csv format.
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
const buffer = await this.cashflowSheetApp.csv(query);

View File

@@ -0,0 +1,397 @@
export const CashflowStatementResponseExample = {
data: [
{
id: 'OPERATING',
label: 'OPERATING ACTIVITIES',
footer_label: 'Net cash provided by operating activities',
section_type: 'AGGREGATE',
children: [
{
id: 'NET_INCOME',
label: 'Net income',
total: {
amount: -113923,
formatted_amount: '-113,923.00',
currency_code: 'USD',
},
section_type: 'NET_INCOME',
children: [],
},
{
section_type: 'ACCOUNTS',
id: 'OPERATING_ACCOUNTS',
label: 'Adjustments net income by operating activities.',
children: [
{
id: 1006,
code: '10007',
label: 'Accounts Receivable (A/R)',
account_type: 'accounts-receivable',
adjustment_type: 'mines',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1007,
code: '10008',
label: 'Inventory Asset',
account_type: 'inventory',
adjustment_type: 'mines',
total: {
amount: -1000,
formatted_amount: '-1,000.00',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1008,
code: '20001',
label: 'Accounts Payable (A/P)',
account_type: 'accounts-payable',
adjustment_type: 'plus',
total: {
amount: 1300,
formatted_amount: '1,300.00',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1013,
code: '20006',
label: 'Tax Payable',
account_type: 'tax-payable',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1030,
code: '100010',
label: 'Prepaid Expenses',
account_type: 'other-current-asset',
adjustment_type: 'mines',
total: {
amount: 123123,
formatted_amount: '123,123.00',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1009,
code: '20002',
label: 'Owner A Drawings',
account_type: 'other-current-liability',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1010,
code: '20003',
label: 'Loan',
account_type: 'other-current-liability',
adjustment_type: 'plus',
total: {
amount: -10000,
formatted_amount: '-10,000.00',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1011,
code: '20004',
label: 'Opening Balance Liabilities',
account_type: 'other-current-liability',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1012,
code: '20005',
label: 'Revenue Received in Advance',
account_type: 'other-current-liability',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1029,
code: '50005',
label: 'Unearned Revenue',
account_type: 'other-current-liability',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
],
total: {
amount: 113423,
formatted_amount: '$113,423.00',
currency_code: 'USD',
},
},
],
total: {
amount: -500,
formatted_amount: '-$500.00',
currency_code: 'USD',
},
},
{
section_type: 'ACCOUNTS',
id: 'INVESTMENT',
label: 'INVESTMENT ACTIVITIES',
footer_label: 'cash_flow_statement.net_cash_investing',
children: [
{
id: 1004,
code: '10005',
label: 'Computer Equipment',
account_type: 'fixed-asset',
adjustment_type: 'mines',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1005,
code: '10006',
label: 'Office Equipment',
account_type: 'fixed-asset',
adjustment_type: 'mines',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
],
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
},
{
section_type: 'ACCOUNTS',
id: 'FINANCIAL',
label: 'FINANCIAL ACTIVITIES',
footer_label: 'cash_flow_statement.net_cash_financing',
children: [
{
id: 1014,
code: '30001',
label: 'Retained Earnings',
account_type: 'equity',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1015,
code: '30002',
label: 'Opening Balance Equity',
account_type: 'equity',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1016,
code: '30003',
label: "Owner's Equity",
account_type: 'equity',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1017,
code: '30003',
label: 'Drawings',
account_type: 'equity',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
],
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
},
{
section_type: 'CASH_AT_BEGINNING',
id: 'CASH_BEGINNING_PERIOD',
label: 'Cash at beginning of period',
children: [
{
id: 1002,
code: '10003',
label: 'Undeposited Funds',
account_type: 'cash',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1003,
code: '10004',
label: 'Petty Cash',
account_type: 'cash',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1000,
code: '10001',
label: 'Bank Account',
account_type: 'bank',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1001,
code: '10002',
label: 'Saving Bank Account',
account_type: 'bank',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
{
id: 1034,
code: '',
label: 'Chase - Plaid Checking',
account_type: 'bank',
adjustment_type: 'plus',
total: {
amount: 0,
formatted_amount: '',
currency_code: 'USD',
},
section_type: 'ACCOUNT',
},
],
total: {
amount: 0,
formatted_amount: '$0.00',
currency_code: 'USD',
},
},
{
section_type: 'TOTAL',
id: 'NET_CASH_INCREASE',
label: 'NET CASH INCREASE FOR PERIOD',
total: {
amount: -500,
formatted_amount: '-$500.00',
currency_code: 'USD',
},
},
{
section_type: 'TOTAL',
id: 'CASH_END_PERIOD',
label: 'CASH AT END OF PERIOD',
total: {
amount: -500,
formatted_amount: '-$500.00',
currency_code: 'USD',
},
},
],
query: {
display_columns_type: 'total',
display_columns_by: 'year',
from_date: '2025-01-01',
to_date: '2025-06-16',
number_format: {
precision: 2,
divide_on1000: false,
show_zero: false,
format_money: 'total',
negative_format: 'mines',
},
none_zero: false,
none_transactions: false,
basis: 'cash',
},
meta: {
organization_name: 'BIGCAPITAL, INC',
base_currency: 'USD',
date_format: 'DD MMM yyyy',
is_cost_compute_running: false,
sheet_name: 'Statement of Cash Flow',
formatted_to_date: '2025/06/16',
formatted_from_date: '2025/01/01',
formatted_date_range: 'From 2025/01/01 | To 2025/06/16',
},
};

View File

@@ -4,6 +4,7 @@ import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
import { GeneralLedgerApplication } from './GeneralLedgerApplication';
import { AcceptType } from '@/constants/accept-type';
import { GeneralLedgerQueryDto } from './GeneralLedgerQuery.dto';
import { GeneralLedgerResponseExample } from './GeneralLedger.swagger';
@Controller('/reports/general-ledger')
@ApiTags('Reports')
@@ -13,7 +14,11 @@ export class GeneralLedgerController {
) {}
@Get()
@ApiResponse({ status: 200, description: 'General ledger report' })
@ApiResponse({
status: 200,
description: 'General ledger report',
example: GeneralLedgerResponseExample,
})
@ApiOperation({ summary: 'Get general ledger report' })
public async getGeneralLedger(
@Query() query: GeneralLedgerQueryDto,

View File

@@ -10,29 +10,61 @@ import {
} from 'class-validator';
import { Transform, Type } from 'class-transformer';
import { parseBoolean } from '@/utils/parse-boolean';
import { ApiProperty } from '@nestjs/swagger';
export class GeneralLedgerQueryDto extends FinancialSheetBranchesQueryDto {
@ApiProperty({
description: 'Start date for the general ledger report',
example: '2024-01-01',
required: false,
})
@IsDateString()
@IsOptional()
fromDate: Date | string;
@ApiProperty({
description: 'End date for the general ledger report',
example: '2024-12-31',
required: false,
})
@IsDateString()
@IsOptional()
toDate: Date | string;
@ApiProperty({
description: 'Accounting basis for the report (e.g., cash, accrual)',
example: 'accrual',
required: false,
})
@IsString()
@IsOptional()
basis: string;
@ApiProperty({
description: 'Number format configuration for the report',
type: NumberFormatQueryDto,
})
@ValidateNested()
@Type(() => NumberFormatQueryDto)
numberFormat: NumberFormatQueryDto;
@ApiProperty({
description: 'Whether to exclude transactions from the report',
example: false,
required: false,
default: false,
})
@Transform(({ value }) => parseBoolean(value, false))
@IsBoolean()
@IsOptional()
noneTransactions: boolean;
@ApiProperty({
description: 'Array of account IDs to filter the report',
example: [1, 2, 3],
required: false,
type: [Number],
})
@IsArray()
@IsOptional()
accountsIds: number[];

View File

@@ -5,6 +5,7 @@ import { Response } from 'express';
import { AcceptType } from '@/constants/accept-type';
import { TrialBalanceSheetApplication } from './TrialBalanceSheetApplication';
import { TrialBalanceSheetQueryDto } from './TrialBalanceSheetQuery.dto';
import { TrialBalanceSheetResponseExample } from './TrialBalanceSheet.swagger';
@Controller('reports/trial-balance-sheet')
@ApiTags('Reports')
@@ -15,7 +16,11 @@ export class TrialBalanceSheetController {
@Get()
@ApiOperation({ summary: 'Get trial balance sheet' })
@ApiResponse({ status: 200, description: 'Trial balance sheet' })
@ApiResponse({
status: 200,
description: 'Trial balance sheet',
example: TrialBalanceSheetResponseExample,
})
async getTrialBalanceSheet(
@Query() query: TrialBalanceSheetQueryDto,
@Res({ passthrough: true }) res: Response,

View File

@@ -0,0 +1,585 @@
export const TrialBalanceSheetResponseExample = {
data: {
accounts: [
{
id: 1000,
parent_account_id: null,
name: 'Bank Account',
formatted_name: 'Bank Account - 10001',
code: '10001',
account_normal: 'debit',
credit: 500,
debit: 0,
balance: -500,
currency_code: 'USD',
formatted_credit: '500.00',
formatted_debit: '',
formatted_balance: '-500.00',
children: [],
},
{
id: 1001,
parent_account_id: null,
name: 'Saving Bank Account',
formatted_name: 'Saving Bank Account - 10002',
code: '10002',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1002,
parent_account_id: null,
name: 'Undeposited Funds',
formatted_name: 'Undeposited Funds - 10003',
code: '10003',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1003,
parent_account_id: null,
name: 'Petty Cash',
formatted_name: 'Petty Cash - 10004',
code: '10004',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1004,
parent_account_id: null,
name: 'Computer Equipment',
formatted_name: 'Computer Equipment - 10005',
code: '10005',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1005,
parent_account_id: null,
name: 'Office Equipment',
formatted_name: 'Office Equipment - 10006',
code: '10006',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1006,
parent_account_id: null,
name: 'Accounts Receivable (A/R)',
formatted_name: 'Accounts Receivable (A/R) - 10007',
code: '10007',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1007,
parent_account_id: null,
name: 'Inventory Asset',
formatted_name: 'Inventory Asset - 10008',
code: '10008',
account_normal: 'debit',
credit: 0,
debit: 1000,
balance: 1000,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '1,000.00',
formatted_balance: '1,000.00',
children: [],
},
{
id: 1008,
parent_account_id: null,
name: 'Accounts Payable (A/P)',
formatted_name: 'Accounts Payable (A/P) - 20001',
code: '20001',
account_normal: 'credit',
credit: 2000,
debit: 700,
balance: -1300,
currency_code: 'USD',
formatted_credit: '2,000.00',
formatted_debit: '700.00',
formatted_balance: '-1,300.00',
children: [],
},
{
id: 1009,
parent_account_id: null,
name: 'Owner A Drawings',
formatted_name: 'Owner A Drawings - 20002',
code: '20002',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1010,
parent_account_id: null,
name: 'Loan',
formatted_name: 'Loan - 20003',
code: '20003',
account_normal: 'credit',
credit: 0,
debit: 10000,
balance: 10000,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '10,000.00',
formatted_balance: '10,000.00',
children: [],
},
{
id: 1011,
parent_account_id: null,
name: 'Opening Balance Liabilities',
formatted_name: 'Opening Balance Liabilities - 20004',
code: '20004',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1012,
parent_account_id: null,
name: 'Revenue Received in Advance',
formatted_name: 'Revenue Received in Advance - 20005',
code: '20005',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1013,
parent_account_id: null,
name: 'Tax Payable',
formatted_name: 'Tax Payable - 20006',
code: '20006',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1014,
parent_account_id: null,
name: 'Retained Earnings',
formatted_name: 'Retained Earnings - 30001',
code: '30001',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1015,
parent_account_id: null,
name: 'Opening Balance Equity',
formatted_name: 'Opening Balance Equity - 30002',
code: '30002',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1016,
parent_account_id: null,
name: "Owner's Equity",
formatted_name: "Owner's Equity - 30003",
code: '30003',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1017,
parent_account_id: null,
name: 'Drawings',
formatted_name: 'Drawings - 30003',
code: '30003',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1018,
parent_account_id: null,
name: 'Other Expenses',
formatted_name: 'Other Expenses - 40011',
code: '40011',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1019,
parent_account_id: null,
name: 'Cost of Goods Sold',
formatted_name: 'Cost of Goods Sold - 40002',
code: '40002',
account_normal: 'debit',
credit: 200,
debit: 1000,
balance: 800,
currency_code: 'USD',
formatted_credit: '200.00',
formatted_debit: '1,000.00',
formatted_balance: '800.00',
children: [],
},
{
id: 1020,
parent_account_id: null,
name: 'Office expenses',
formatted_name: 'Office expenses - 40003',
code: '40003',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1021,
parent_account_id: null,
name: 'Rent',
formatted_name: 'Rent - 40004',
code: '40004',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1022,
parent_account_id: null,
name: 'Exchange Gain or Loss',
formatted_name: 'Exchange Gain or Loss - 40005',
code: '40005',
account_normal: 'debit',
credit: 0,
debit: 123123,
balance: 123123,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '123,123.00',
formatted_balance: '123,123.00',
children: [],
},
{
id: 1023,
parent_account_id: null,
name: 'Bank Fees and Charges',
formatted_name: 'Bank Fees and Charges - 40006',
code: '40006',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1024,
parent_account_id: null,
name: 'Depreciation Expense',
formatted_name: 'Depreciation Expense - 40007',
code: '40007',
account_normal: 'debit',
credit: 10000,
debit: 0,
balance: -10000,
currency_code: 'USD',
formatted_credit: '10,000.00',
formatted_debit: '',
formatted_balance: '-10,000.00',
children: [],
},
{
id: 1025,
parent_account_id: null,
name: 'Sales of Product Income',
formatted_name: 'Sales of Product Income - 50001',
code: '50001',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1026,
parent_account_id: null,
name: 'Sales of Service Income',
formatted_name: 'Sales of Service Income - 50002',
code: '50002',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1027,
parent_account_id: null,
name: 'Uncategorized Income',
formatted_name: 'Uncategorized Income - 50003',
code: '50003',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1029,
parent_account_id: null,
name: 'Unearned Revenue',
formatted_name: 'Unearned Revenue - 50005',
code: '50005',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1030,
parent_account_id: null,
name: 'Prepaid Expenses',
formatted_name: 'Prepaid Expenses - 100010',
code: '100010',
account_normal: 'debit',
credit: 123123,
debit: 0,
balance: -123123,
currency_code: 'USD',
formatted_credit: '123,123.00',
formatted_debit: '',
formatted_balance: '-123,123.00',
children: [],
},
{
id: 1031,
parent_account_id: null,
name: 'Discount',
formatted_name: 'Discount - 40008',
code: '40008',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1032,
parent_account_id: null,
name: 'Purchase Discount',
formatted_name: 'Purchase Discount - 40009',
code: '40009',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1033,
parent_account_id: null,
name: 'Other Charges',
formatted_name: 'Other Charges - 40010',
code: '40010',
account_normal: 'credit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
{
id: 1034,
parent_account_id: null,
name: 'Chase - Plaid Checking',
formatted_name: 'Chase - Plaid Checking',
code: '',
account_normal: 'debit',
credit: 0,
debit: 0,
balance: 0,
currency_code: 'USD',
formatted_credit: '',
formatted_debit: '',
formatted_balance: '',
children: [],
},
],
total: {
credit: 135823,
debit: 135823,
balance: 0,
currency_code: 'USD',
formatted_credit: '$135,823.00',
formatted_debit: '$135,823.00',
formatted_balance: '$0.00',
},
},
query: {
from_date: '2025-01-01',
to_date: '2025-06-16',
number_format: {
divide_on1000: false,
negative_format: 'mines',
show_zero: false,
format_money: 'total',
precision: 2,
},
basis: 'accrual',
none_zero: false,
none_transactions: true,
only_active: false,
account_ids: [null],
},
meta: {
organization_name: 'BIGCAPITAL, INC',
base_currency: 'USD',
date_format: 'DD MMM yyyy',
is_cost_compute_running: false,
sheet_name: 'Trial Balance Sheet',
formatted_from_date: '2025/01/01',
formatted_to_date: '2025/06/16',
formatted_date_range: 'From 2025/01/01 to 2025/06/16',
},
};

View File

@@ -11,40 +11,84 @@ import {
} from 'class-validator';
import { Transform, Type } from 'class-transformer';
import { parseBoolean } from '@/utils/parse-boolean';
import { ApiProperty } from '@nestjs/swagger';
export class TrialBalanceSheetQueryDto extends FinancialSheetBranchesQueryDto {
@ApiProperty({
description: 'Start date for the trial balance sheet',
required: false,
type: Date,
})
@IsDateString()
@IsOptional()
fromDate: Date;
@ApiProperty({
description: 'End date for the trial balance sheet',
required: false,
type: Date,
})
@IsDateString()
@IsOptional()
toDate: Date;
@ApiProperty({
description: 'Number format configuration for the report',
required: false,
type: NumberFormatQueryDto,
})
@ValidateNested()
@Type(() => NumberFormatQueryDto)
@IsOptional()
numberFormat: INumberFormatQuery;
@ApiProperty({
description: 'Accounting basis for the report',
required: false,
enum: ['cash', 'accrual'],
})
@IsString()
@IsOptional()
basis: 'cash' | 'accrual';
@ApiProperty({
description: 'Filter out zero balance accounts',
required: false,
type: Boolean,
default: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
noneZero: boolean;
@ApiProperty({
description: 'Filter out accounts with no transactions',
required: false,
type: Boolean,
default: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
noneTransactions: boolean;
@ApiProperty({
description: 'Show only active accounts',
required: false,
type: Boolean,
default: false,
})
@IsBoolean()
@Transform(({ value }) => parseBoolean(value, false))
@IsOptional()
onlyActive: boolean;
@ApiProperty({
description: 'Filter by specific account IDs',
required: false,
type: [Number],
})
@IsArray()
@IsOptional()
accountIds: number[];

View File

@@ -1,4 +1,10 @@
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import {
ApiExtraModels,
ApiOperation,
ApiResponse,
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
import {
Body,
Controller,
@@ -13,9 +19,11 @@ import { InventoryAdjustmentsApplicationService } from './InventoryAdjustmentsAp
import { IInventoryAdjustmentsFilter } from './types/InventoryAdjustments.types';
import { InventoryAdjustment } from './models/InventoryAdjustment';
import { CreateQuickInventoryAdjustmentDto } from './dtos/CreateQuickInventoryAdjustment.dto';
import { InventoryAdjustmentResponseDto } from './dtos/InventoryAdjustmentResponse.dto';
@Controller('inventory-adjustments')
@ApiTags('Inventory Adjustments')
@ApiExtraModels(InventoryAdjustmentResponseDto)
export class InventoryAdjustmentsController {
constructor(
private readonly inventoryAdjustmentsApplicationService: InventoryAdjustmentsApplicationService,
@@ -69,6 +77,7 @@ export class InventoryAdjustmentsController {
status: 200,
description:
'The inventory adjustment details have been successfully retrieved.',
schema: { $ref: getSchemaPath(InventoryAdjustmentResponseDto) },
})
public async getInventoryAdjustment(
@Param('id') inventoryAdjustmentId: number,

View File

@@ -0,0 +1,92 @@
import { ApiProperty } from '@nestjs/swagger';
import { InventoryAdjustmentEntry } from '../models/InventoryAdjustmentEntry';
export class InventoryAdjustmentResponseDto {
@ApiProperty({
description: 'The unique identifier of the inventory adjustment',
example: 1,
})
id: number;
@ApiProperty({
description: 'The date of the inventory adjustment',
example: '2024-03-20',
})
date: string;
@ApiProperty({
description: 'The type of adjustment (increment or decrement)',
enum: ['increment', 'decrement'],
example: 'increment',
})
type: string;
@ApiProperty({
description: 'The formatted type of adjustment',
example: 'inventory_adjustment.increment',
})
formattedType: string;
@ApiProperty({
description: 'The ID of the adjustment account',
example: 100,
})
adjustmentAccountId: number;
@ApiProperty({
description: 'The reason for the adjustment',
example: 'Stock count discrepancy',
})
reason: string;
@ApiProperty({
description: 'The reference number for the adjustment',
example: 'IA-2024-001',
})
referenceNo: string;
@ApiProperty({
description: 'Additional description of the adjustment',
example: 'Year-end inventory reconciliation',
required: false,
})
description?: string;
@ApiProperty({
description: 'The ID of the user who created the adjustment',
example: 1,
})
userId: number;
@ApiProperty({
description: 'The date when the adjustment was published',
example: '2024-03-20T10:00:00Z',
required: false,
})
publishedAt?: string;
@ApiProperty({
description: 'The ID of the branch where the adjustment was made',
example: 1,
})
branchId: number;
@ApiProperty({
description: 'The ID of the warehouse where the adjustment was made',
example: 1,
})
warehouseId: number;
@ApiProperty({
description: 'The date when the adjustment was created',
example: '2024-03-20T09:00:00Z',
})
createdAt: string;
@ApiProperty({
description: 'The entries associated with this adjustment',
type: [InventoryAdjustmentEntry],
isArray: true,
})
entries: InventoryAdjustmentEntry[];
}

View File

@@ -15,18 +15,22 @@ import { SubscriptionGuard } from '../Subscription/interceptors/Subscription.gua
import { JwtAuthGuard } from '../Auth/guards/jwt.guard';
import { ItemsApplicationService } from './ItemsApplication.service';
import {
ApiExtraModels,
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
import { CreateItemDto, EditItemDto } from './dtos/Item.dto';
import { GetItemsQueryDto } from './dtos/GetItemsQuery.dto';
import { ItemResponseDto } from './dtos/itemResponse.dto';
@Controller('/items')
@ApiTags('Items')
@UseGuards(SubscriptionGuard)
@ApiExtraModels(ItemResponseDto)
export class ItemsController extends TenantController {
constructor(private readonly itemsApplication: ItemsApplicationService) {
super();
@@ -221,7 +225,10 @@ export class ItemsController extends TenantController {
@ApiOperation({ summary: 'Get the given item (product or service).' })
@ApiResponse({
status: 200,
description: 'The item has been successfully retrieved.',
description: 'The item details have been successfully retrieved.',
schema: {
$ref: getSchemaPath(ItemResponseDto),
},
})
@ApiResponse({ status: 404, description: 'The item not found.' })
@ApiParam({

View File

@@ -0,0 +1,243 @@
import { ApiProperty } from '@nestjs/swagger';
import { Item } from '../models/Item';
export class ItemResponseDto {
@ApiProperty({
description: 'The unique identifier of the item',
example: 1,
})
id: number;
@ApiProperty({
description: 'The name of the item',
example: 'Ergonomic Office Chair Model X-2000',
})
name: string;
@ApiProperty({
description: 'The type of the item',
enum: ['service', 'non-inventory', 'inventory'],
example: 'inventory',
})
type: string;
@ApiProperty({
description: 'The formatted type of the item',
example: 'Inventory Item',
})
typeFormatted: string;
@ApiProperty({
description: 'The item code/SKU',
example: 'CHAIR-X2000',
required: false,
})
code?: string;
@ApiProperty({
description: 'Whether the item can be sold',
example: true,
})
sellable: boolean;
@ApiProperty({
description: 'Whether the item can be purchased',
example: true,
})
purchasable: boolean;
@ApiProperty({
description: 'The selling price of the item',
example: 399.99,
required: false,
})
sellPrice?: number;
@ApiProperty({
description: 'The formatted selling price of the item',
example: '$399.99',
required: false,
})
sellPriceFormatted?: string;
@ApiProperty({
description: 'The cost price of the item',
example: 299.99,
required: false,
})
costPrice?: number;
@ApiProperty({
description: 'The formatted cost price of the item',
example: '$299.99',
required: false,
})
costPriceFormatted?: string;
@ApiProperty({
description: 'The currency code of the item',
example: 'USD',
})
currencyCode: string;
@ApiProperty({
description: 'The ID of the cost account',
example: 1001,
required: false,
})
costAccountId?: number;
@ApiProperty({
description: 'The cost account details',
required: false,
})
costAccount?: {
id: number;
name: string;
};
@ApiProperty({
description: 'The ID of the inventory account',
example: 3001,
required: false,
})
inventoryAccountId?: number;
@ApiProperty({
description: 'The inventory account details',
required: false,
})
inventoryAccount?: {
id: number;
name: string;
};
@ApiProperty({
description: 'The ID of the sell account',
example: 2001,
required: false,
})
sellAccountId?: number;
@ApiProperty({
description: 'The sell account details',
required: false,
})
sellAccount?: {
id: number;
name: string;
};
@ApiProperty({
description: 'The ID of the item category',
example: 5,
required: false,
})
categoryId?: number;
@ApiProperty({
description: 'The category details',
required: false,
})
category?: {
id: number;
name: string;
};
@ApiProperty({
description: 'The description shown on sales documents',
example:
'Premium ergonomic office chair with adjustable height and lumbar support',
required: false,
})
sellDescription?: string;
@ApiProperty({
description: 'The description shown on purchase documents',
example: 'Ergonomic office chair - Model X-2000 with standard features',
required: false,
})
purchaseDescription?: string;
@ApiProperty({
description: 'The quantity of the item in stock (for inventory items)',
example: 50,
required: false,
})
quantityOnHand?: number;
@ApiProperty({
description: 'Additional notes about the item',
example:
'Available in black, gray, and navy colors. 5-year warranty included.',
required: false,
})
note?: string;
@ApiProperty({
description: 'Whether the item is active',
example: true,
})
active: boolean;
@ApiProperty({
description: 'The ID of the tax rate applied to sales',
example: 1,
required: false,
})
sellTaxRateId?: number;
@ApiProperty({
description: 'The tax rate details for sales',
required: false,
})
sellTaxRate?: {
id: number;
name: string;
rate: number;
};
@ApiProperty({
description: 'The ID of the tax rate applied to purchases',
example: 1,
required: false,
})
purchaseTaxRateId?: number;
@ApiProperty({
description: 'The tax rate details for purchases',
required: false,
})
purchaseTaxRate?: {
id: number;
name: string;
rate: number;
};
@ApiProperty({
description: 'The warehouse quantities for the item',
type: 'array',
required: false,
})
itemWarehouses?: Array<{
id: number;
warehouseId: number;
quantity: number;
warehouse: {
id: number;
name: string;
};
}>;
@ApiProperty({
description: 'The date when the item was created',
example: '2024-03-20T10:00:00Z',
})
createdAt: Date;
@ApiProperty({
description: 'The date when the item was last updated',
example: '2024-03-20T10:00:00Z',
})
updatedAt: Date;
}

View File

@@ -10,20 +10,34 @@ import {
Query,
} from '@nestjs/common';
import { ManualJournalsApplication } from './ManualJournalsApplication.service';
import { ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';
import {
ApiExtraModels,
ApiOperation,
ApiParam,
ApiResponse,
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
import {
CreateManualJournalDto,
EditManualJournalDto,
} from './dtos/ManualJournal.dto';
import { IManualJournalsFilter } from './types/ManualJournals.types';
import { ManualJournalResponseDto } from './dtos/ManualJournalResponse.dto';
@Controller('manual-journals')
@ApiTags('Manual Journals')
@ApiExtraModels(ManualJournalResponseDto)
export class ManualJournalsController {
constructor(private manualJournalsApplication: ManualJournalsApplication) {}
@Post()
@ApiOperation({ summary: 'Create a new manual journal.' })
@ApiResponse({
status: 201,
description: 'The manual journal has been successfully created.',
schema: { $ref: getSchemaPath(ManualJournalResponseDto) },
})
public createManualJournal(@Body() manualJournalDTO: CreateManualJournalDto) {
return this.manualJournalsApplication.createManualJournal(manualJournalDTO);
}
@@ -33,6 +47,7 @@ export class ManualJournalsController {
@ApiResponse({
status: 200,
description: 'The manual journal has been successfully edited.',
schema: { $ref: getSchemaPath(ManualJournalResponseDto) },
})
@ApiResponse({ status: 404, description: 'The manual journal not found.' })
@ApiParam({
@@ -73,6 +88,9 @@ export class ManualJournalsController {
@ApiResponse({
status: 200,
description: 'The manual journal has been successfully published.',
schema: {
$ref: getSchemaPath(ManualJournalResponseDto),
},
})
@ApiResponse({ status: 404, description: 'The manual journal not found.' })
@ApiParam({
@@ -90,6 +108,9 @@ export class ManualJournalsController {
@ApiResponse({
status: 200,
description: 'The manual journal details have been successfully retrieved.',
schema: {
$ref: getSchemaPath(ManualJournalResponseDto),
},
})
@ApiResponse({ status: 404, description: 'The manual journal not found.' })
@ApiParam({
@@ -107,6 +128,12 @@ export class ManualJournalsController {
@ApiResponse({
status: 200,
description: 'The manual journal details have been successfully retrieved.',
schema: {
type: 'array',
items: {
$ref: getSchemaPath(ManualJournalResponseDto),
},
},
})
@ApiResponse({ status: 404, description: 'The manual journal not found.' })
public getManualJournals(@Query() filterDto: Partial<IManualJournalsFilter>) {

View File

@@ -0,0 +1,132 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsDate,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from 'class-validator';
export class ManualJournalEntryResponseDto {
@ApiProperty({ description: 'Entry index', example: 1 })
index: number;
@ApiPropertyOptional({ description: 'Credit amount', example: 1000.0 })
credit?: number;
@ApiPropertyOptional({ description: 'Debit amount', example: 0.0 })
debit?: number;
@ApiProperty({ description: 'Account ID', example: 1 })
accountId: number;
@ApiPropertyOptional({
description: 'Entry note',
example: 'Payment for services',
})
note?: string;
@ApiPropertyOptional({ description: 'Contact ID', example: 1 })
contactId?: number;
@ApiPropertyOptional({ description: 'Branch ID', example: 1 })
branchId?: number;
@ApiPropertyOptional({ description: 'Project ID', example: 1 })
projectId?: number;
@ApiPropertyOptional({ description: 'Account details' })
account?: any;
@ApiPropertyOptional({ description: 'Contact details' })
contact?: any;
@ApiPropertyOptional({ description: 'Branch details' })
branch?: any;
}
export class ManualJournalResponseDto {
@ApiProperty({ description: 'Manual Journal ID', example: 1 })
id: number;
@ApiProperty({ description: 'Journal date', example: '2024-03-20' })
date: Date;
@ApiProperty({ description: 'Journal number', example: 'MJ-2024-001' })
journalNumber: string;
@ApiPropertyOptional({ description: 'Journal type', example: 'General' })
journalType?: string;
@ApiPropertyOptional({ description: 'Reference number', example: 'REF-001' })
reference?: string;
@ApiProperty({ description: 'Total amount', example: 1000.0 })
amount: number;
@ApiPropertyOptional({ description: 'Currency code', example: 'USD' })
currencyCode?: string;
@ApiPropertyOptional({ description: 'Exchange rate', example: 1.0 })
exchangeRate?: number;
@ApiPropertyOptional({
description: 'Description',
example: 'Monthly journal entry',
})
description?: string;
@ApiProperty({ description: 'Published status', example: false })
isPublished: boolean;
@ApiPropertyOptional({
description: 'Published date',
example: '2024-03-20T10:00:00Z',
})
publishedAt?: Date;
@ApiProperty({ description: 'Created date', example: '2024-03-20T09:00:00Z' })
createdAt: Date;
@ApiPropertyOptional({
description: 'Updated date',
example: '2024-03-20T09:30:00Z',
})
updatedAt?: Date;
@ApiPropertyOptional({ description: 'Branch ID', example: 1 })
branchId?: number;
@ApiProperty({ description: 'Formatted amount', example: '$1,000.00' })
formattedAmount: string;
@ApiProperty({ description: 'Formatted date', example: 'Mar 20, 2024' })
formattedDate: string;
@ApiPropertyOptional({
description: 'Formatted published date',
example: 'Mar 20, 2024',
})
formattedPublishedAt?: string;
@ApiProperty({
description: 'Formatted created date',
example: 'Mar 20, 2024',
})
formattedCreatedAt: string;
@ApiProperty({
description: 'Journal entries',
type: [ManualJournalEntryResponseDto],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => ManualJournalEntryResponseDto)
entries: ManualJournalEntryResponseDto[];
@ApiPropertyOptional({ description: 'Attachments' })
attachments?: any[];
}

View File

@@ -1,4 +1,9 @@
import { ApiOperation } from '@nestjs/swagger';
import {
ApiOperation,
ApiResponse,
ApiExtraModels,
getSchemaPath,
} from '@nestjs/swagger';
import { ApiTags } from '@nestjs/swagger';
import { Controller, Put, Get, Body, Param } from '@nestjs/common';
import { TransactionsLockingService } from './commands/CommandTransactionsLockingService';
@@ -9,9 +14,11 @@ import {
CancelTransactionsLockingDto,
TransactionsLockingDto,
} from './dtos/TransactionsLocking.dto';
import { TransactionLockingResponseDto } from './dtos/TransactionLockingResponse.dto';
@Controller('transactions-locking')
@ApiTags('Transactions Locking')
@ApiExtraModels(TransactionLockingResponseDto)
export class TransactionsLockingController {
constructor(
private readonly transactionsLockingService: TransactionsLockingService,
@@ -22,6 +29,13 @@ export class TransactionsLockingController {
@ApiOperation({
summary: 'Lock all transactions for a module or all modules',
})
@ApiResponse({
status: 200,
description: 'The transactions have been successfully locked.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async commandTransactionsLocking(
@Body('module') module: TransactionsLockingGroup,
@Body() transactionLockingDTO: TransactionsLockingDto,
@@ -41,6 +55,13 @@ export class TransactionsLockingController {
@ApiOperation({
summary: 'Cancel all transactions locking for a module or all modules',
})
@ApiResponse({
status: 200,
description: 'The transactions locking has been successfully canceled.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async cancelTransactionLocking(
@Body('module') module: TransactionsLockingGroup,
@Body() cancelLockingDTO: CancelTransactionsLockingDto,
@@ -60,6 +81,13 @@ export class TransactionsLockingController {
summary:
'Partial unlock all transactions locking for a module or all modules',
})
@ApiResponse({
status: 200,
description: 'The transactions have been successfully partially unlocked.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async unlockTransactionsLockingBetweenPeriod(
@Body('module') module: TransactionsLockingGroup,
@Body() unlockDTO: ITransactionLockingPartiallyDTO,
@@ -80,6 +108,14 @@ export class TransactionsLockingController {
summary:
'Cancel partial unlocking all transactions locking for a module or all modules',
})
@ApiResponse({
status: 200,
description:
'The partial transaction unlocking has been successfully canceled.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async cancelPartialUnlocking(
@Body('module') module: TransactionsLockingGroup,
) {
@@ -95,12 +131,28 @@ export class TransactionsLockingController {
@Get('/')
@ApiOperation({ summary: 'Get all transactions locking meta' })
@ApiResponse({
status: 200,
description:
'The transactions locking meta has been successfully retrieved.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async getTransactionLockingMetaList() {
return await this.queryTransactionsLocking.getTransactionsLockingList();
}
@Get(':module')
@ApiOperation({ summary: 'Get transactions locking meta for a module' })
@ApiResponse({
status: 200,
description:
'The module transactions locking meta has been successfully retrieved.',
schema: {
$ref: getSchemaPath(TransactionLockingResponseDto),
},
})
async getTransactionLockingMeta(@Param('module') module: string) {
return await this.queryTransactionsLocking.getTransactionsLockingModuleMeta(
module as TransactionsLockingGroup,

View File

@@ -0,0 +1,51 @@
import { ApiProperty } from '@nestjs/swagger';
export class TransactionLockingResponseDto {
@ApiProperty({
description: 'Indicates whether transaction locking is enabled',
example: true,
})
isEnabled: boolean;
@ApiProperty({
description: 'Indicates whether partial unlock is enabled',
example: false,
})
isPartialUnlock: boolean;
@ApiProperty({
description: 'The date until which transactions are locked',
example: '2024-12-31',
})
lockToDate: Date;
@ApiProperty({
description: 'The start date of the unlock period',
example: '2025-01-01',
})
unlockFromDate: string;
@ApiProperty({
description: 'The end date of the unlock period',
example: '2025-01-31',
})
unlockToDate: string;
@ApiProperty({
description: 'The reason for locking transactions',
example: 'Year-end closing',
})
lockReason: string;
@ApiProperty({
description: 'The reason for unlocking transactions',
example: 'New fiscal year',
})
unlockReason: string;
@ApiProperty({
description: 'The reason for partial unlock of transactions',
example: 'Special adjustment period',
})
partialUnlockReason: string;
}