mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
wip
This commit is contained in:
@@ -9,6 +9,27 @@ import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis'
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => {
|
||||
// Use in-memory storage with very high limits for test environment
|
||||
const isTest = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined;
|
||||
|
||||
if (isTest) {
|
||||
return {
|
||||
throttlers: [
|
||||
{
|
||||
name: 'default',
|
||||
ttl: 60000,
|
||||
limit: 1000000, // Effectively disable throttling in tests
|
||||
},
|
||||
{
|
||||
name: 'auth',
|
||||
ttl: 60000,
|
||||
limit: 1000000, // Effectively disable throttling in tests
|
||||
},
|
||||
],
|
||||
// No storage specified = uses in-memory storage
|
||||
};
|
||||
}
|
||||
|
||||
const host = configService.get<string>('redis.host') || 'localhost';
|
||||
const port = Number(configService.get<number>('redis.port') || 6379);
|
||||
const password = configService.get<string>('redis.password');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Patch, Post, Query } from '@nestjs/common';
|
||||
import { BankingMatchingApplication } from './BankingMatchingApplication';
|
||||
import { GetMatchedTransactionsFilter } from './types';
|
||||
import { MatchBankTransactionDto } from './dtos/MatchBankTransaction.dto';
|
||||
@@ -34,7 +34,7 @@ export class BankingMatchingController {
|
||||
);
|
||||
}
|
||||
|
||||
@Post('/unmatch/:uncategorizedTransactionId')
|
||||
@Patch('/unmatch/:uncategorizedTransactionId')
|
||||
@ApiOperation({ summary: 'Unmatch the given uncategorized transaction.' })
|
||||
async unmatchMatchedTransaction(
|
||||
@Param('uncategorizedTransactionId') uncategorizedTransactionId: number,
|
||||
|
||||
@@ -11,10 +11,12 @@ import {
|
||||
Post,
|
||||
Body,
|
||||
Put,
|
||||
Patch,
|
||||
Param,
|
||||
Delete,
|
||||
Get,
|
||||
Query,
|
||||
HttpCode,
|
||||
} from '@nestjs/common';
|
||||
import { BillsApplication } from './Bills.application';
|
||||
import { IBillsFilter } from './Bills.types';
|
||||
@@ -40,6 +42,7 @@ export class BillsController {
|
||||
@ApiOperation({
|
||||
summary: 'Validate which bills can be deleted and return the results.',
|
||||
})
|
||||
@HttpCode(200)
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
@@ -56,6 +59,7 @@ export class BillsController {
|
||||
|
||||
@Post('bulk-delete')
|
||||
@ApiOperation({ summary: 'Deletes multiple bills.' })
|
||||
@HttpCode(200)
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Bills deleted successfully',
|
||||
@@ -160,7 +164,7 @@ export class BillsController {
|
||||
return this.billsApplication.getBill(billId);
|
||||
}
|
||||
|
||||
@Post(':id/open')
|
||||
@Patch(':id/open')
|
||||
@ApiOperation({ summary: 'Open the given bill.' })
|
||||
@ApiParam({
|
||||
name: 'id',
|
||||
|
||||
@@ -6,7 +6,7 @@ import { DeleteItemService } from './DeleteItem.service';
|
||||
|
||||
@Injectable()
|
||||
export class BulkDeleteItemsService {
|
||||
constructor(private readonly deleteItemService: DeleteItemService) {}
|
||||
constructor(private readonly deleteItemService: DeleteItemService) { }
|
||||
|
||||
/**
|
||||
* Deletes multiple items.
|
||||
|
||||
@@ -163,6 +163,41 @@ export class ItemsController extends TenantController {
|
||||
return { id: itemId, message: 'The item has been successfully updated.' };
|
||||
}
|
||||
|
||||
@Post('validate-bulk-delete')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Validates which items can be deleted and returns counts of deletable and non-deletable items.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'Validation completed. Returns counts and IDs of deletable and non-deletable items.',
|
||||
schema: {
|
||||
$ref: getSchemaPath(ValidateBulkDeleteItemsResponseDto),
|
||||
},
|
||||
})
|
||||
async validateBulkDeleteItems(
|
||||
@Body() bulkDeleteDto: BulkDeleteItemsDto,
|
||||
): Promise<ValidateBulkDeleteItemsResponseDto> {
|
||||
return this.itemsApplication.validateBulkDeleteItems(bulkDeleteDto.ids);
|
||||
}
|
||||
|
||||
@Post('bulk-delete')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({ summary: 'Deletes multiple items in bulk.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The items have been successfully deleted.',
|
||||
})
|
||||
async bulkDeleteItems(
|
||||
@Body() bulkDeleteDto: BulkDeleteItemsDto,
|
||||
): Promise<void> {
|
||||
return this.itemsApplication.bulkDeleteItems(bulkDeleteDto.ids, {
|
||||
skipUndeletable: bulkDeleteDto.skipUndeletable ?? false,
|
||||
});
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new item (product or service).' })
|
||||
@ApiResponse({
|
||||
@@ -352,37 +387,4 @@ export class ItemsController extends TenantController {
|
||||
return this.itemsApplication.getItemReceiptsTransactions(itemId);
|
||||
}
|
||||
|
||||
@Post('validate-bulk-delete')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({
|
||||
summary:
|
||||
'Validates which items can be deleted and returns counts of deletable and non-deletable items.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'Validation completed. Returns counts and IDs of deletable and non-deletable items.',
|
||||
schema: {
|
||||
$ref: getSchemaPath(ValidateBulkDeleteItemsResponseDto),
|
||||
},
|
||||
})
|
||||
async validateBulkDeleteItems(
|
||||
@Body() bulkDeleteDto: BulkDeleteItemsDto,
|
||||
): Promise<ValidateBulkDeleteItemsResponseDto> {
|
||||
return this.itemsApplication.validateBulkDeleteItems(bulkDeleteDto.ids);
|
||||
}
|
||||
|
||||
@Post('bulk-delete')
|
||||
@ApiOperation({ summary: 'Deletes multiple items in bulk.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The items have been successfully deleted.',
|
||||
})
|
||||
async bulkDeleteItems(
|
||||
@Body() bulkDeleteDto: BulkDeleteItemsDto,
|
||||
): Promise<void> {
|
||||
return this.itemsApplication.bulkDeleteItems(bulkDeleteDto.ids, {
|
||||
skipUndeletable: bulkDeleteDto.skipUndeletable ?? false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ export class PaymentReceivesController {
|
||||
@Headers('accept') acceptHeader: string,
|
||||
@Res({ passthrough: true }) res: Response,
|
||||
) {
|
||||
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
||||
if (acceptHeader?.includes(AcceptType.ApplicationPdf)) {
|
||||
const [pdfContent, filename] = await this.paymentReceivesApplication.getPaymentReceivePdf(
|
||||
paymentReceiveId,
|
||||
);
|
||||
@@ -239,7 +239,7 @@ export class PaymentReceivesController {
|
||||
'Content-Disposition': `attachment; filename="${filename}"`,
|
||||
});
|
||||
res.send(pdfContent);
|
||||
} else if (acceptHeader.includes(AcceptType.ApplicationTextHtml)) {
|
||||
} else if (acceptHeader?.includes(AcceptType.ApplicationTextHtml)) {
|
||||
const htmlContent =
|
||||
await this.paymentReceivesApplication.getPaymentReceivedHtml(
|
||||
paymentReceiveId,
|
||||
|
||||
@@ -76,9 +76,14 @@ export class PaymentReceivedValidators {
|
||||
customerId: number,
|
||||
paymentReceiveEntries: { invoiceId: number }[],
|
||||
): Promise<SaleInvoice[]> {
|
||||
const invoicesIds = paymentReceiveEntries.map(
|
||||
(e: { invoiceId: number }) => e.invoiceId,
|
||||
);
|
||||
const invoicesIds = paymentReceiveEntries
|
||||
.map((e: { invoiceId: number }) => e.invoiceId)
|
||||
.filter((id): id is number => id !== undefined && id !== null);
|
||||
|
||||
if (invoicesIds.length === 0) {
|
||||
throw new ServiceError(ERRORS.INVOICES_IDS_NOT_FOUND);
|
||||
}
|
||||
|
||||
const storedInvoices = await this.saleInvoiceModel()
|
||||
.query()
|
||||
.whereIn('id', invoicesIds)
|
||||
|
||||
@@ -5,11 +5,9 @@ import {
|
||||
Delete,
|
||||
Param,
|
||||
Body,
|
||||
Next,
|
||||
HttpStatus,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { NextFunction } from 'express';
|
||||
import { CreateRoleDto, EditRoleDto } from './dtos/Role.dto';
|
||||
import { RolesApplication } from './Roles.application';
|
||||
import {
|
||||
@@ -29,7 +27,7 @@ import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
|
||||
@ApiExtraModels(RoleResponseDto)
|
||||
@ApiCommonHeaders()
|
||||
export class RolesController {
|
||||
constructor(private readonly rolesApp: RolesApplication) {}
|
||||
constructor(private readonly rolesApp: RolesApplication) { }
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new role' })
|
||||
@@ -38,14 +36,11 @@ export class RolesController {
|
||||
status: HttpStatus.OK,
|
||||
description: 'Role created successfully',
|
||||
})
|
||||
async createRole(
|
||||
@Next() next: NextFunction,
|
||||
@Body() createRoleDto: CreateRoleDto,
|
||||
) {
|
||||
async createRole(@Body() createRoleDto: CreateRoleDto) {
|
||||
const role = await this.rolesApp.createRole(createRoleDto);
|
||||
|
||||
return {
|
||||
data: { roleId: role.id },
|
||||
data: { id: role.id },
|
||||
message: 'The role has been created successfully.',
|
||||
};
|
||||
}
|
||||
@@ -65,7 +60,7 @@ export class RolesController {
|
||||
const role = await this.rolesApp.editRole(roleId, editRoleDto);
|
||||
|
||||
return {
|
||||
data: { roleId },
|
||||
data: { id: role.id },
|
||||
message: 'The given role has been updated successfully.',
|
||||
};
|
||||
}
|
||||
@@ -81,7 +76,7 @@ export class RolesController {
|
||||
await this.rolesApp.deleteRole(roleId);
|
||||
|
||||
return {
|
||||
data: { roleId },
|
||||
data: { id: roleId },
|
||||
message: 'The given role has been deleted successfully.',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ export class SaleInvoicesController {
|
||||
@Headers('accept') acceptHeader: string,
|
||||
@Res({ passthrough: true }) res: Response,
|
||||
) {
|
||||
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
||||
if (acceptHeader?.includes(AcceptType.ApplicationPdf)) {
|
||||
const [pdfContent, filename] =
|
||||
await this.saleInvoiceApplication.saleInvoicePdf(id);
|
||||
|
||||
@@ -219,7 +219,7 @@ export class SaleInvoicesController {
|
||||
'Content-Length': pdfContent.length,
|
||||
});
|
||||
res.send(pdfContent);
|
||||
} else if (acceptHeader.includes(AcceptType.ApplicationTextHtml)) {
|
||||
} else if (acceptHeader?.includes(AcceptType.ApplicationTextHtml)) {
|
||||
const htmlContent = await this.saleInvoiceApplication.saleInvoiceHtml(id);
|
||||
return { htmlContent };
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { UsersApplication } from './Users.application';
|
||||
import { InviteUserDto, SendInviteUserDto } from './dtos/InviteUser.dto';
|
||||
@@ -38,7 +38,7 @@ export class UsersInviteController {
|
||||
/**
|
||||
* Send an invitation to a new user.
|
||||
*/
|
||||
@Post()
|
||||
@Patch()
|
||||
@ApiOperation({ summary: 'Send an invitation to a new user.' })
|
||||
async sendInvite(@Body() sendInviteDTO: SendInviteUserDto) {
|
||||
const result = await this.usersApplication.sendInvite(sendInviteDTO);
|
||||
|
||||
@@ -18,7 +18,7 @@ export class EditUserService {
|
||||
private readonly tenantUserModel: TenantModelProxy<typeof TenantUser>,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
) {}
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Creates a new user.
|
||||
@@ -52,7 +52,10 @@ export class EditUserService {
|
||||
const tenantUser = await this.tenantUserModel()
|
||||
.query()
|
||||
.updateAndFetchById(userId, {
|
||||
...editUserDTO,
|
||||
firstName: editUserDTO.firstName,
|
||||
lastName: editUserDTO.lastName,
|
||||
email: editUserDTO.email,
|
||||
roleId: editUserDTO.roleId,
|
||||
});
|
||||
// Triggers `onTenantUserEdited` event.
|
||||
await this.eventEmitter.emitAsync(events.tenantUser.onEdited, {
|
||||
|
||||
Reference in New Issue
Block a user