mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
388 lines
11 KiB
TypeScript
388 lines
11 KiB
TypeScript
import { Response } from 'express';
|
|
import {
|
|
Body,
|
|
Controller,
|
|
DefaultValuePipe,
|
|
Delete,
|
|
Get,
|
|
Headers,
|
|
HttpCode,
|
|
Param,
|
|
ParseBoolPipe,
|
|
ParseIntPipe,
|
|
Post,
|
|
Put,
|
|
Query,
|
|
Res,
|
|
} from '@nestjs/common';
|
|
import {
|
|
ISaleInvoiceWriteoffDTO,
|
|
ISalesInvoicesFilter,
|
|
SaleInvoiceMailState,
|
|
SendInvoiceMailDTO,
|
|
} from './SaleInvoice.types';
|
|
import { SaleInvoiceApplication } from './SaleInvoices.application';
|
|
import {
|
|
ApiOperation,
|
|
ApiParam,
|
|
ApiQuery,
|
|
ApiResponse,
|
|
ApiTags,
|
|
ApiExtraModels,
|
|
getSchemaPath,
|
|
} from '@nestjs/swagger';
|
|
import {
|
|
CreateSaleInvoiceDto,
|
|
EditSaleInvoiceDto,
|
|
} from './dtos/SaleInvoice.dto';
|
|
import { AcceptType } from '@/constants/accept-type';
|
|
import { SaleInvoiceResponseDto } from './dtos/SaleInvoiceResponse.dto';
|
|
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
|
|
import { SaleInvoiceStateResponseDto } from './dtos/SaleInvoiceState.dto';
|
|
import { GenerateSaleInvoiceSharableLinkResponseDto } from './dtos/GenerateSaleInvoiceSharableLinkResponse.dto';
|
|
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
|
|
import {
|
|
BulkDeleteDto,
|
|
ValidateBulkDeleteResponseDto,
|
|
} from '@/common/dtos/BulkDelete.dto';
|
|
|
|
@Controller('sale-invoices')
|
|
@ApiTags('Sale Invoices')
|
|
@ApiExtraModels(SaleInvoiceResponseDto)
|
|
@ApiExtraModels(PaginatedResponseDto)
|
|
@ApiExtraModels(SaleInvoiceStateResponseDto)
|
|
@ApiExtraModels(GenerateSaleInvoiceSharableLinkResponseDto)
|
|
@ApiCommonHeaders()
|
|
@ApiExtraModels(ValidateBulkDeleteResponseDto)
|
|
export class SaleInvoicesController {
|
|
constructor(private saleInvoiceApplication: SaleInvoiceApplication) { }
|
|
|
|
@Post('validate-bulk-delete')
|
|
@ApiOperation({
|
|
summary:
|
|
'Validates which sale invoices can be deleted and returns the results.',
|
|
})
|
|
@ApiResponse({
|
|
status: 200,
|
|
description:
|
|
'Validation completed with counts and IDs of deletable and non-deletable sale invoices.',
|
|
schema: {
|
|
$ref: getSchemaPath(ValidateBulkDeleteResponseDto),
|
|
},
|
|
})
|
|
validateBulkDeleteSaleInvoices(
|
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
|
): Promise<ValidateBulkDeleteResponseDto> {
|
|
return this.saleInvoiceApplication.validateBulkDeleteSaleInvoices(
|
|
bulkDeleteDto.ids,
|
|
);
|
|
}
|
|
|
|
@Post('bulk-delete')
|
|
@ApiOperation({ summary: 'Deletes multiple sale invoices.' })
|
|
@ApiQuery({
|
|
name: 'skip_undeletable',
|
|
required: false,
|
|
type: Boolean,
|
|
description:
|
|
'When true, undeletable invoices will be skipped and only deletable ones will be removed.',
|
|
})
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'Sale invoices deleted successfully',
|
|
})
|
|
bulkDeleteSaleInvoices(
|
|
@Body() bulkDeleteDto: BulkDeleteDto,
|
|
@Query('skip_undeletable', new DefaultValuePipe(false), ParseBoolPipe)
|
|
skipUndeletable: boolean,
|
|
): Promise<void> {
|
|
return this.saleInvoiceApplication.bulkDeleteSaleInvoices(
|
|
bulkDeleteDto.ids,
|
|
{ skipUndeletable },
|
|
);
|
|
}
|
|
|
|
@Post()
|
|
@ApiOperation({ summary: 'Create a new sale invoice.' })
|
|
@ApiResponse({
|
|
status: 201,
|
|
description: 'Sale invoice created successfully',
|
|
})
|
|
createSaleInvoice(@Body() saleInvoiceDTO: CreateSaleInvoiceDto) {
|
|
return this.saleInvoiceApplication.createSaleInvoice(saleInvoiceDTO);
|
|
}
|
|
|
|
@Put(':id/mail')
|
|
@ApiOperation({ summary: 'Send the sale invoice mail.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'Sale invoice mail sent successfully',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
sendSaleInvoiceMail(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Body() messageDTO: SendInvoiceMailDTO,
|
|
) {
|
|
return this.saleInvoiceApplication.sendSaleInvoiceMail(id, messageDTO);
|
|
}
|
|
|
|
@Put(':id')
|
|
@ApiOperation({ summary: 'Edit the given sale invoice.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'Sale invoice edited successfully',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
editSaleInvoice(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Body() saleInvoiceDTO: EditSaleInvoiceDto,
|
|
) {
|
|
return this.saleInvoiceApplication.editSaleInvoice(id, saleInvoiceDTO);
|
|
}
|
|
|
|
@Delete(':id')
|
|
@ApiOperation({ summary: 'Delete the given sale invoice.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoice has been successfully deleted.',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
deleteSaleInvoice(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.deleteSaleInvoice(id);
|
|
}
|
|
|
|
@Get('receivable')
|
|
@ApiOperation({ summary: 'Retrieves the receivable sale invoices.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description:
|
|
'The receivable sale invoices have been successfully retrieved.',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The customer not found.' })
|
|
@ApiQuery({
|
|
name: 'customerId',
|
|
required: false,
|
|
type: Number,
|
|
description: 'The customer id',
|
|
})
|
|
getReceivableSaleInvoices(@Query('customerId') customerId?: number) {
|
|
return this.saleInvoiceApplication.getReceivableSaleInvoices(customerId);
|
|
}
|
|
|
|
@Get('state')
|
|
@ApiOperation({ summary: 'Retrieves the sale invoice state.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoice state has been successfully retrieved.',
|
|
schema: {
|
|
$ref: getSchemaPath(SaleInvoiceStateResponseDto),
|
|
},
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
getSaleInvoiceState() {
|
|
return this.saleInvoiceApplication.getSaleInvoiceState();
|
|
}
|
|
|
|
@Get(':id')
|
|
@ApiOperation({ summary: 'Retrieves the sale invoice details.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoice details have been successfully retrieved.',
|
|
schema: {
|
|
$ref: getSchemaPath(SaleInvoiceResponseDto),
|
|
},
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
async getSaleInvoice(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Headers('accept') acceptHeader: string,
|
|
@Res({ passthrough: true }) res: Response,
|
|
) {
|
|
if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
|
const pdfContent = await this.saleInvoiceApplication.saleInvoicePdf(id);
|
|
|
|
res.set({
|
|
'Content-Type': 'application/pdf',
|
|
'Content-Length': pdfContent.length,
|
|
});
|
|
res.send(pdfContent);
|
|
} else if (acceptHeader.includes(AcceptType.ApplicationTextHtml)) {
|
|
const htmlContent = await this.saleInvoiceApplication.saleInvoiceHtml(id);
|
|
return { htmlContent };
|
|
} else {
|
|
return this.saleInvoiceApplication.getSaleInvoice(id);
|
|
}
|
|
}
|
|
|
|
@Get()
|
|
@ApiOperation({ summary: 'Retrieves the sale invoices.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoices have been successfully retrieved.',
|
|
schema: {
|
|
allOf: [
|
|
{ $ref: getSchemaPath(PaginatedResponseDto) },
|
|
{
|
|
properties: {
|
|
data: {
|
|
type: 'array',
|
|
items: { $ref: getSchemaPath(SaleInvoiceResponseDto) },
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
})
|
|
getSaleInvoices(@Query() filterDTO: Partial<ISalesInvoicesFilter>) {
|
|
return this.saleInvoiceApplication.getSaleInvoices(filterDTO);
|
|
}
|
|
|
|
@Put(':id/deliver')
|
|
@ApiOperation({ summary: 'Deliver the given sale invoice.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoice has been successfully marked asdelivered.',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
@HttpCode(200)
|
|
deliverSaleInvoice(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.deliverSaleInvoice(id);
|
|
}
|
|
|
|
@Post(':id/writeoff')
|
|
@ApiOperation({ summary: 'Write off the given sale invoice.' })
|
|
@HttpCode(200)
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'The sale invoice has been successfully written off.',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
writeOff(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
@Body() writeoffDTO: ISaleInvoiceWriteoffDTO,
|
|
) {
|
|
return this.saleInvoiceApplication.writeOff(id, writeoffDTO);
|
|
}
|
|
|
|
@Post(':id/cancel-writeoff')
|
|
@ApiOperation({ summary: 'Cancel the written off sale invoice.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description:
|
|
'The sale invoice has been successfully marked as not written off.',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
@HttpCode(200)
|
|
cancelWrittenoff(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.cancelWrittenoff(id);
|
|
}
|
|
|
|
@Get(':id/payments')
|
|
@ApiOperation({ summary: 'Retrieves the sale invoice payments.' })
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
getInvoicePayments(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.getInvoicePayments(id);
|
|
}
|
|
|
|
@Get(':id/html')
|
|
@ApiOperation({ summary: 'Retrieves the sale invoice HTML.' })
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
saleInvoiceHtml(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.saleInvoiceHtml(id);
|
|
}
|
|
|
|
@Get(':id/mail')
|
|
@ApiOperation({ summary: 'Retrieves the sale invoice mail state.' })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: 'Sale invoice mail state retrieved successfully',
|
|
})
|
|
@ApiResponse({ status: 404, description: 'The sale invoice not found.' })
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
getSaleInvoiceMailState(
|
|
@Param('id', ParseIntPipe) id: number,
|
|
): Promise<SaleInvoiceMailState> {
|
|
return this.saleInvoiceApplication.getSaleInvoiceMailState(id);
|
|
}
|
|
|
|
@Post(':id/generate-link')
|
|
@ApiOperation({
|
|
summary: 'Generate sharable sale invoice link (private or public)',
|
|
})
|
|
@ApiResponse({
|
|
status: 201,
|
|
description: 'The link has been generated successfully.',
|
|
schema: {
|
|
$ref: getSchemaPath(GenerateSaleInvoiceSharableLinkResponseDto),
|
|
},
|
|
})
|
|
@ApiParam({
|
|
name: 'id',
|
|
required: true,
|
|
type: Number,
|
|
description: 'The sale invoice id',
|
|
})
|
|
generateSaleInvoiceSharableLink(@Param('id', ParseIntPipe) id: number) {
|
|
return this.saleInvoiceApplication.generateSaleInvoiceSharableLink(id);
|
|
}
|
|
}
|