feat: enhance sale invoices filtering with additional fields and refactor findAll method

This commit is contained in:
2026-05-16 16:12:19 +03:30
parent 5baf5bfea6
commit ba3c544ff8
5 changed files with 228 additions and 16 deletions
+5 -2
View File
@@ -5,6 +5,7 @@ ARG NPM_REGISTRY=https://registry.npmjs.org/
ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY} ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY}
ENV npm_config_registry=${NPM_REGISTRY} ENV npm_config_registry=${NPM_REGISTRY}
ENV PNPM_HOME="/pnpm" ENV PNPM_HOME="/pnpm"
ENV PNPM_STORE_DIR="/pnpm/store"
ENV PATH="${PNPM_HOME}:${PATH}" ENV PATH="${PNPM_HOME}:${PATH}"
ENV COREPACK_NPM_REGISTRY=${NPM_REGISTRY} ENV COREPACK_NPM_REGISTRY=${NPM_REGISTRY}
ARG PNPM_VERSION=10.17.1 ARG PNPM_VERSION=10.17.1
@@ -15,7 +16,8 @@ RUN npm config set registry ${NPM_REGISTRY} \
FROM base AS build FROM base AS build
COPY package.json pnpm-lock.yaml ./ COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \
pnpm install --frozen-lockfile
COPY . . COPY . .
ENV PRISMA_CLIENT_ENGINE_TYPE=binary ENV PRISMA_CLIENT_ENGINE_TYPE=binary
@@ -24,7 +26,8 @@ RUN pnpm run build
FROM base AS prod-deps FROM base AS prod-deps
COPY package.json pnpm-lock.yaml ./ COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod --frozen-lockfile \ RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \
pnpm install --prod --frozen-lockfile \
&& pnpm store prune \ && pnpm store prune \
&& rm -rf /root/.npm /root/.cache && rm -rf /root/.npm /root/.cache
@@ -1,6 +1,15 @@
import { ApiPropertyOptional } from '@nestjs/swagger' import { ApiPropertyOptional } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { Type } from 'class-transformer'
import { IsOptional, Max, Min } from 'class-validator' import {
IsDateString,
IsEnum,
IsNumber,
IsOptional,
IsString,
Max,
Min,
} from 'class-validator'
import { TspProviderResponseStatus } from 'generated/prisma/enums'
export class ConsumerSaleInvoicesFilterDto { export class ConsumerSaleInvoicesFilterDto {
@ApiPropertyOptional({ type: Number, example: 1 }) @ApiPropertyOptional({ type: Number, example: 1 })
@@ -15,4 +24,72 @@ export class ConsumerSaleInvoicesFilterDto {
@Max(50) @Max(50)
@IsOptional() @IsOptional()
perPage?: number perPage?: number
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
invoice_date_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_from?: string
@ApiPropertyOptional()
@IsOptional()
@IsDateString()
created_at_to?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
code?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_name?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_mobile?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_national_id?: string
@ApiPropertyOptional()
@IsOptional()
@IsString()
customer_economic_code?: string
@ApiPropertyOptional({ enum: TspProviderResponseStatus })
@IsOptional()
@IsEnum(TspProviderResponseStatus)
status?: TspProviderResponseStatus
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_from?: number
@ApiPropertyOptional()
@IsOptional()
@Type(() => Number)
@IsNumber()
total_amount_to?: number
} }
@@ -19,15 +19,9 @@ export class StatisticsController {
@Get('') @Get('')
async findAll( async findAll(
@TokenAccount('userId') consumerId: string, @TokenAccount('userId') consumerId: string,
@Query('page') page = '1', @Query() query: ConsumerSaleInvoicesFilterDto,
@Query('perPage') perPage = '10',
): Promise<SaleInvoicesServiceFindAllResponseDto> { ): Promise<SaleInvoicesServiceFindAllResponseDto> {
const filter: ConsumerSaleInvoicesFilterDto = { return this.service.findAll(consumerId, query)
page: Number(page) || 1,
perPage: Number(perPage) || 10,
}
return this.service.findAll(consumerId, filter)
} }
@Get(':id') @Get(':id')
@@ -59,11 +59,7 @@ export class SaleInvoicesService {
} }
async findAll(consumer_id: string, filter: ConsumerSaleInvoicesFilterDto) { async findAll(consumer_id: string, filter: ConsumerSaleInvoicesFilterDto) {
const invoicesWhere: SalesInvoiceWhereInput = { const invoicesWhere = this.buildFindAllWhere(consumer_id, filter)
consumer_account: {
consumer_id,
},
}
const normalizedPageValue = Number(filter.page ?? 1) const normalizedPageValue = Number(filter.page ?? 1)
const normalizedPage = Number.isFinite(normalizedPageValue) const normalizedPage = Number.isFinite(normalizedPageValue)
? Math.max(1, Math.floor(normalizedPageValue)) ? Math.max(1, Math.floor(normalizedPageValue))
@@ -99,6 +95,146 @@ export class SaleInvoicesService {
}) })
} }
private buildFindAllWhere(
consumer_id: string,
filter: ConsumerSaleInvoicesFilterDto,
): SalesInvoiceWhereInput {
const where: SalesInvoiceWhereInput = {
consumer_account: {
consumer_id,
},
}
if (filter.code?.trim()) {
where.code = {
contains: filter.code.trim(),
}
}
if (filter.invoice_date_from || filter.invoice_date_to) {
where.invoice_date = {
...(filter.invoice_date_from ? { gte: new Date(filter.invoice_date_from) } : {}),
...(filter.invoice_date_to ? { lte: new Date(filter.invoice_date_to) } : {}),
}
}
if (filter.created_at_from || filter.created_at_to) {
where.created_at = {
...(filter.created_at_from ? { gte: new Date(filter.created_at_from) } : {}),
...(filter.created_at_to ? { lte: new Date(filter.created_at_to) } : {}),
}
}
if (
filter.total_amount !== undefined ||
filter.total_amount_from !== undefined ||
filter.total_amount_to !== undefined
) {
where.total_amount = {
...(filter.total_amount !== undefined ? { equals: filter.total_amount } : {}),
...(filter.total_amount_from !== undefined
? { gte: filter.total_amount_from }
: {}),
...(filter.total_amount_to !== undefined ? { lte: filter.total_amount_to } : {}),
}
}
if (
filter.customer_name?.trim() ||
filter.customer_mobile?.trim() ||
filter.customer_national_id?.trim() ||
filter.customer_economic_code?.trim()
) {
where.customer = {
is: {
OR: [
...(filter.customer_name?.trim()
? [
{
individual: {
is: {
OR: [
{ first_name: { contains: filter.customer_name.trim() } },
{ last_name: { contains: filter.customer_name.trim() } },
],
},
},
},
{
legal: {
is: {
name: {
contains: filter.customer_name.trim(),
},
},
},
},
]
: []),
...(filter.customer_mobile?.trim()
? [
{
individual: {
is: {
mobile_number: { contains: filter.customer_mobile.trim() },
},
},
},
]
: []),
...(filter.customer_national_id?.trim()
? [
{
individual: {
is: {
national_id: { contains: filter.customer_national_id.trim() },
},
},
},
]
: []),
...(filter.customer_economic_code?.trim()
? [
{
legal: {
is: {
OR: [
{
economic_code: {
contains: filter.customer_economic_code.trim(),
},
},
{
registration_number: {
contains: filter.customer_economic_code.trim(),
},
},
],
},
},
},
]
: []),
],
},
}
}
if (filter.status) {
if (filter.status === TspProviderResponseStatus.NOT_SEND) {
where.tsp_attempts = undefined
} else {
where.tsp_attempts = {
some: {
status: filter.status,
},
}
}
}
return where
}
async findOne(consumer_id: string, id: string) { async findOne(consumer_id: string, id: string) {
const invoicesWhere: SalesInvoiceWhereUniqueInput = { const invoicesWhere: SalesInvoiceWhereUniqueInput = {
id, id,
+2
View File
@@ -10,6 +10,8 @@ export class PosService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async getInfo(pos_id: string) { async getInfo(pos_id: string) {
console.log('pos_id', pos_id)
const pos = await this.prisma.pos.findUniqueOrThrow({ const pos = await this.prisma.pos.findUniqueOrThrow({
where: { where: {
id: pos_id, id: pos_id,