Merge branch 'develop' into more-e2e-test-cases

This commit is contained in:
Ahmed Bouhuolia
2026-01-18 15:01:49 +02:00
22 changed files with 248 additions and 98 deletions

View File

@@ -22,6 +22,9 @@
"field.status.unpaid": "Unpaid",
"field.status.opened": "Opened",
"field.status.draft": "Draft",
"field.created_at": "Created At"
"field.created_at": "Created At",
"allocation_method": "Allocation Method",
"allocation_method.quantity": "Quantity",
"allocation_method.value": "Valuation"
}

View File

@@ -4,10 +4,6 @@ import { ClsMiddleware } from 'nestjs-cls';
import * as path from 'path';
import './utils/moment-mysql';
import { AppModule } from './modules/App/App.module';
import { ServiceErrorFilter } from './common/filters/service-error.filter';
import { ModelHasRelationsFilter } from './common/filters/model-has-relations.filter';
import { ValidationPipe } from './common/pipes/ClassValidation.pipe';
import { ToJsonInterceptor } from './common/interceptors/to-json.interceptor';
import { NestExpressApplication } from '@nestjs/platform-express';
global.__public_dirname = path.join(__dirname, '..', 'public');
@@ -25,11 +21,6 @@ async function bootstrap() {
// create and mount the middleware manually here
app.use(new ClsMiddleware({}).use);
app.useGlobalInterceptors(new ToJsonInterceptor());
// use the validation pipe globally
app.useGlobalPipes(new ValidationPipe());
const config = new DocumentBuilder()
.setTitle('Bigcapital')
.setDescription('Financial accounting software')
@@ -39,9 +30,6 @@ async function bootstrap() {
const documentFactory = () => SwaggerModule.createDocument(app, config);
SwaggerModule.setup('swagger', app, documentFactory);
app.useGlobalFilters(new ServiceErrorFilter());
app.useGlobalFilters(new ModelHasRelationsFilter());
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

View File

@@ -1,7 +1,7 @@
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE, APP_FILTER } from '@nestjs/core';
import { join } from 'path';
import { ServeStaticModule } from '@nestjs/serve-static';
import { RedisModule } from '@liaoliaots/nestjs-redis';
@@ -36,6 +36,10 @@ import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module';
import { BranchesModule } from '../Branches/Branches.module';
import { WarehousesModule } from '../Warehouses/Warehouses.module';
import { SerializeInterceptor } from '@/common/interceptors/serialize.interceptor';
import { ValidationPipe } from '@/common/pipes/ClassValidation.pipe';
import { ToJsonInterceptor } from '@/common/interceptors/to-json.interceptor';
import { ServiceErrorFilter } from '@/common/filters/service-error.filter';
import { ModelHasRelationsFilter } from '@/common/filters/model-has-relations.filter';
import { ChromiumlyTenancyModule } from '../ChromiumlyTenancy/ChromiumlyTenancy.module';
import { CustomersModule } from '../Customers/Customers.module';
import { VendorsModule } from '../Vendors/Vendors.module';
@@ -234,10 +238,18 @@ import { AppThrottleModule } from './AppThrottle.module';
],
controllers: [AppController],
providers: [
{
provide: APP_PIPE,
useClass: ValidationPipe,
},
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
{
provide: APP_INTERCEPTOR,
useClass: ToJsonInterceptor,
},
{
provide: APP_INTERCEPTOR,
useClass: SerializeInterceptor,
@@ -250,6 +262,14 @@ import { AppThrottleModule } from './AppThrottle.module';
provide: APP_INTERCEPTOR,
useClass: ExcludeNullInterceptor,
},
{
provide: APP_FILTER,
useClass: ServiceErrorFilter,
},
{
provide: APP_FILTER,
useClass: ModelHasRelationsFilter,
},
AppService,
],
})

View File

@@ -4,8 +4,8 @@ import {
validateTransactionShouldBeExcluded,
} from './utils';
import {
IBankTransactionExcludedEventPayload,
IBankTransactionExcludingEventPayload,
IBankTransactionUnexcludedEventPayload,
IBankTransactionUnexcludingEventPayload,
} from '../types/BankTransactionsExclude.types';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Inject, Injectable } from '@nestjs/common';
@@ -24,7 +24,7 @@ export class UnexcludeBankTransactionService {
private readonly uncategorizedBankTransactionModel: TenantModelProxy<
typeof UncategorizedBankTransaction
>,
) {}
) { }
/**
* Marks the given bank transaction as excluded.
@@ -50,7 +50,8 @@ export class UnexcludeBankTransactionService {
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
await this.eventEmitter.emitAsync(events.bankTransactions.onUnexcluding, {
uncategorizedTransactionId,
} as IBankTransactionExcludingEventPayload);
trx,
} as IBankTransactionUnexcludingEventPayload);
await this.uncategorizedBankTransactionModel()
.query(trx)
@@ -61,7 +62,8 @@ export class UnexcludeBankTransactionService {
await this.eventEmitter.emitAsync(events.bankTransactions.onUnexcluded, {
uncategorizedTransactionId,
} as IBankTransactionExcludedEventPayload);
trx,
} as IBankTransactionUnexcludedEventPayload);
});
}
}

View File

@@ -19,7 +19,7 @@ export class DecrementUncategorizedTransactionOnExclude {
private readonly uncategorizedBankTransaction: TenantModelProxy<
typeof UncategorizedBankTransaction
>,
) {}
) { }
/**
* Validates the cashflow transaction whether matched with bank transaction on deleting.
@@ -50,7 +50,7 @@ export class DecrementUncategorizedTransactionOnExclude {
trx,
}: IBankTransactionUnexcludedEventPayload) {
const transaction = await this.uncategorizedBankTransaction()
.query()
.query(trx)
.findById(uncategorizedTransactionId);
//
await this.account()

View File

@@ -25,7 +25,7 @@ export class BillAllocateLandedCostController {
private billAllocatedCostTransactions: BillAllocatedLandedCostTransactions,
private revertAllocatedLandedCost: RevertAllocatedLandedCost,
private landedCostTransactions: LandedCostTranasctions,
) {}
) { }
@Get('/transactions')
@ApiOperation({ summary: 'Get landed cost transactions' })

View File

@@ -21,7 +21,7 @@ export class BillAllocatedLandedCostTransactions {
private readonly billLandedCostModel: TenantModelProxy<
typeof BillLandedCost
>,
) {}
) { }
/**
* Retrieve the bill associated landed cost transactions.
@@ -77,6 +77,13 @@ export class BillAllocatedLandedCostTransactions {
transaction.fromTransactionType,
transaction,
);
const allocationMethodFormattedKey = transaction.allocationMethodFormatted;
const allocationMethodFormatted = allocationMethodFormattedKey
? this.i18nService.t(allocationMethodFormattedKey, {
defaultValue: allocationMethodFormattedKey,
})
: '';
return {
formattedAmount: formatNumber(transaction.amount, {
currencyCode: transaction.currencyCode,
@@ -84,12 +91,14 @@ export class BillAllocatedLandedCostTransactions {
...omit(transaction, [
'allocatedFromBillEntry',
'allocatedFromExpenseEntry',
'allocationMethodFormatted',
]),
name,
description,
formattedLocalAmount: formatNumber(transaction.localAmount, {
currencyCode: 'USD',
}),
allocationMethodFormatted,
};
};

View File

@@ -14,7 +14,7 @@ import { LandedCostTransactionsQueryDto } from '../dtos/LandedCostTransactionsQu
@Injectable()
export class LandedCostTranasctions {
constructor(private readonly transactionLandedCost: TransactionLandedCost) {}
constructor(private readonly transactionLandedCost: TransactionLandedCost) { }
/**
* Retrieve the landed costs based on the given query.
@@ -45,8 +45,8 @@ export class LandedCostTranasctions {
)(transactionType);
return pipe(
this.transformLandedCostTransactions,
R.map(transformLandedCost),
this.transformLandedCostTransactions,
)(transactions);
};
@@ -90,7 +90,7 @@ export class LandedCostTranasctions {
const entries = R.map<
ILandedCostTransactionEntry,
ILandedCostTransactionEntryDOJO
>(transformLandedCostEntry)(transaction.entries);
>(transformLandedCostEntry)(transaction.entries ?? []);
return {
...transaction,

View File

@@ -4,7 +4,6 @@ import {
IsOptional,
IsArray,
ValidateNested,
IsDecimal,
IsString,
IsNumber,
} from 'class-validator';
@@ -17,8 +16,9 @@ export class AllocateBillLandedCostItemDto {
@ToNumber()
entryId: number;
@IsDecimal()
cost: string; // Use string for IsDecimal, or use @IsNumber() if you want a number
@IsNumber()
@ToNumber()
cost: number;
}
export class AllocateBillLandedCostDto {

View File

@@ -60,8 +60,8 @@ export class BillLandedCost extends BaseModel {
const allocationMethod = lowerCase(this.allocationMethod);
const keyLabelsPairs = {
value: 'allocation_method.value.label',
quantity: 'allocation_method.quantity.label',
value: 'bill.allocation_method.value',
quantity: 'bill.allocation_method.quantity',
};
return keyLabelsPairs[allocationMethod] || '';
}