invoice
This commit is contained in:
@@ -233,7 +233,7 @@ export class AdminService {
|
||||
customersCount,
|
||||
] = await Promise.all([
|
||||
this.em.count(Request),
|
||||
this.em.count(Invoice, { confirmStatus: InvoiceConfirmStatusEnum.PENDING }),
|
||||
this.em.count(Invoice, { status: InvoiceConfirmStatusEnum.PENDING }),
|
||||
this.em.count(Order, {
|
||||
status: { $nin: [OrderStatusEnum.FINISHED, OrderStatusEnum.CANCELED] },
|
||||
}),
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
IsDateString,
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsArray,
|
||||
} from 'class-validator';
|
||||
import { InvoiceConfirmStatusEnum } from '../enum/invoice-confirm-status.enum';
|
||||
import { Type, Transform } from 'class-transformer';
|
||||
@@ -68,12 +69,21 @@ export class FindInvoicesDto {
|
||||
enableTax?: boolean;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Filter by invoice statuses',
|
||||
enum: InvoiceConfirmStatusEnum,
|
||||
description: 'Filter by invoice confirmation status',
|
||||
isArray: true,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEnum(InvoiceConfirmStatusEnum)
|
||||
confirmStatus?: InvoiceConfirmStatusEnum;
|
||||
@Transform(({ value }: { value: unknown }) =>
|
||||
Array.isArray(value)
|
||||
? value
|
||||
: typeof value === 'string'
|
||||
? value.split(',')
|
||||
: value,
|
||||
)
|
||||
@IsArray()
|
||||
@IsEnum(InvoiceConfirmStatusEnum, { each: true })
|
||||
statuses?: InvoiceConfirmStatusEnum[];
|
||||
|
||||
@ApiPropertyOptional({ default: 'createdAt' })
|
||||
@IsOptional()
|
||||
|
||||
@@ -23,7 +23,7 @@ import { IAttachment } from 'src/modules/order/interface/order.interface';
|
||||
@Entity({ tableName: 'invoices' })
|
||||
@Index({ properties: ['user'] })
|
||||
export class Invoice extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt' | 'invoiceNumber' | 'confirmStatus'
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt' | 'invoiceNumber' | 'status'
|
||||
|
||||
@PrimaryKey({ type: 'string', columnType: 'char(26)' })
|
||||
id: string = ulid()
|
||||
@@ -80,7 +80,7 @@ export class Invoice extends BaseEntity {
|
||||
|
||||
|
||||
@Enum(() => InvoiceConfirmStatusEnum)
|
||||
confirmStatus: InvoiceConfirmStatusEnum = InvoiceConfirmStatusEnum.PENDING;
|
||||
status: InvoiceConfirmStatusEnum = InvoiceConfirmStatusEnum.PENDING;
|
||||
|
||||
@Property({ type: 'boolean', default: false })
|
||||
enableTax?: boolean = false
|
||||
|
||||
@@ -2,4 +2,5 @@ export enum InvoiceConfirmStatusEnum {
|
||||
PENDING = 'pending',
|
||||
PARTIALLY_CONFIRMED = 'partially_confirmed',
|
||||
CONFIRMED = 'confirmed',
|
||||
ARCHIVED = 'archived',
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum InvoiceStatusEnum {
|
||||
PENDING = 'pending',
|
||||
PAID = 'paid',
|
||||
}
|
||||
|
||||
@@ -80,6 +80,14 @@ export class InvoiceController {
|
||||
return this.invoiceService.update(id, updateInvoiceDto);
|
||||
}
|
||||
|
||||
@Patch('admin/invoice/:id/archive')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.UPDATE_INVOICE)
|
||||
@ApiOperation({ summary: 'Archive an invoice (admin)' })
|
||||
archive(@Param('id') id: string) {
|
||||
return this.invoiceService.archive(id);
|
||||
}
|
||||
|
||||
@Delete('admin/invoice/:id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.DELETE_INVOICE)
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ProductService } from '../product/providers/product.service';
|
||||
import { RequestService } from '../request/request.service';
|
||||
import { InvoiceRepository } from './repositories/invoice.repository';
|
||||
import { InvoiceCreatedEvent } from './events/invoice.events';
|
||||
import { InvoiceConfirmStatusEnum } from './enum/invoice-confirm-status.enum';
|
||||
const TAX_RATE = 0.1;
|
||||
|
||||
type ResolvedItemDiscount = {
|
||||
@@ -336,6 +337,16 @@ export class InvoiceService {
|
||||
return invoice;
|
||||
}
|
||||
|
||||
async archive(id: string) {
|
||||
const invoice = await this.findOneOrFail(id);
|
||||
if (invoice.status === InvoiceConfirmStatusEnum.ARCHIVED) {
|
||||
throw new BadRequestException('Invoice is already archived');
|
||||
}
|
||||
invoice.status = InvoiceConfirmStatusEnum.ARCHIVED;
|
||||
await this.em.flush();
|
||||
return invoice;
|
||||
}
|
||||
|
||||
async remove(id: string) {
|
||||
const invoice = await this.findOneOrFail(id);
|
||||
this.em.remove(invoice);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { FilterQuery } from '@mikro-orm/core';
|
||||
import { Invoice } from '../entities/invoice.entity';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { FindInvoicesDto } from '../dto/find-invoices.dto';
|
||||
import { InvoiceConfirmStatusEnum } from '../enum/invoice-confirm-status.enum';
|
||||
|
||||
interface FindInvoicesOpts extends FindInvoicesDto {
|
||||
userId?: string;
|
||||
@@ -27,7 +28,7 @@ export class InvoiceRepository extends EntityRepository<Invoice> {
|
||||
to,
|
||||
enableTax,
|
||||
requestId,
|
||||
confirmStatus,
|
||||
statuses,
|
||||
} = opts;
|
||||
|
||||
const offset = (page - 1) * limit;
|
||||
@@ -46,8 +47,17 @@ export class InvoiceRepository extends EntityRepository<Invoice> {
|
||||
where.enableTax = enableTax;
|
||||
}
|
||||
|
||||
if (confirmStatus) {
|
||||
where.confirmStatus = confirmStatus;
|
||||
if (statuses) {
|
||||
const normalizedStatuses = Array.isArray(statuses) ? statuses : [statuses];
|
||||
const validStatuses = normalizedStatuses.filter(
|
||||
(s): s is InvoiceConfirmStatusEnum => !!s,
|
||||
);
|
||||
|
||||
if (validStatuses.length === 1) {
|
||||
where.status = validStatuses[0];
|
||||
} else if (validStatuses.length > 1) {
|
||||
where.status = { $in: validStatuses };
|
||||
}
|
||||
}
|
||||
|
||||
if (from || to) {
|
||||
|
||||
Reference in New Issue
Block a user