feat(invoices): add public invoices module with controller and service

refactor: remove unused trigger logs module and related files
refactor: simplify good snapshot handling in sale invoice creation
This commit is contained in:
2026-05-21 21:35:36 +03:30
parent 9aa12184a1
commit 2dc9480170
13 changed files with 180 additions and 86 deletions
@@ -0,0 +1,16 @@
import { Public } from '@/common/decorators/public.decorator'
import { Controller, Get, Param } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { InvoicesService } from './invoices.service'
@ApiTags('PublicInvoices')
@Controller('public-invoices')
export class InvoicesController {
constructor(private readonly service: InvoicesService) {}
@Get(':id')
@Public()
findOne(@Param('id') id: string) {
return this.service.findOne(id)
}
}
+10
View File
@@ -0,0 +1,10 @@
import { PrismaService } from '@/prisma/prisma.service'
import { Module } from '@nestjs/common'
import { InvoicesController } from './invoices.controller'
import { InvoicesService } from './invoices.service'
@Module({
controllers: [InvoicesController],
providers: [InvoicesService, PrismaService],
})
export class PublicInvoicesModule {}
+143
View File
@@ -0,0 +1,143 @@
import { RedisKeyMaker, translateEnumValue } from '@/common/utils'
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { SalesInvoiceSelect } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { RedisService } from '@/redis/redis.service'
import { Injectable } from '@nestjs/common'
@Injectable()
export class InvoicesService {
constructor(
private readonly prisma: PrismaService,
private readonly redisService: RedisService,
) {}
private readonly summarySelect: SalesInvoiceSelect = {
id: true,
code: true,
invoice_date: true,
invoice_number: true,
notes: true,
tax_id: true,
total_amount: true,
type: true,
pos: {
select: {
name: true,
complex: {
select: {
name: true,
branch_code: true,
business_activity: {
select: {
name: true,
guild: {
select: {
name: true,
},
},
},
},
},
},
},
},
payments: {
select: {
amount: true,
paid_at: true,
payment_method: true,
terminal_info: {
select: {
stan: true,
rrn: true,
transaction_date_time: true,
customer_card_no: true,
},
},
},
},
unknown_customer: true,
customer: {
select: {
type: true,
legal: {
select: {
name: true,
economic_code: true,
postal_code: true,
registration_number: true,
},
},
individual: {
select: {
economic_code: true,
first_name: true,
last_name: true,
mobile_number: true,
national_id: true,
postal_code: true,
},
},
},
},
items: {
select: {
good_snapshot: true,
measure_unit_text: true,
notes: true,
quantity: true,
total_amount: true,
unit_price: true,
discount: true,
payload: true,
sku_code: true,
sku_vat: true,
},
},
}
private readonly select: SalesInvoiceSelect = {
...this.summarySelect,
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
select: {
status: true,
},
take: 1,
},
}
private readonly where = () => ({})
private readonly invoiceMapper = (invoice: any) => {
const { tsp_attempts, type, ...rest } = invoice || {}
return {
...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue(
'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND,
),
}
}
async findOne(id: string) {
await this.redisService.delete(RedisKeyMaker.publicSaleInvoice(id))
return await this.redisService.getAndSet(
RedisKeyMaker.publicSaleInvoice(id),
'single',
async () => {
const item = await this.prisma.salesInvoice.findUnique({
where: { ...this.where(), id },
select: this.select,
})
return this.invoiceMapper(item)
},
60 * 60,
)
}
}
@@ -1,14 +0,0 @@
import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsString } from 'class-validator'
export class CreateTriggerLogDto {
@ApiProperty()
@IsString()
message: string
@ApiProperty()
@IsString()
name: string
}
export class UpdateTriggerLogDto extends PartialType(CreateTriggerLogDto) {}
@@ -1,5 +0,0 @@
import type { TriggerLogsService } from '../trigger-logs.service'
export type TriggerLogsServiceCreateResponseDto = Awaited<ReturnType<TriggerLogsService['create']>>
export type TriggerLogsServiceFindAllResponseDto = Awaited<ReturnType<TriggerLogsService['findAll']>>
export type TriggerLogsServiceFindOneResponseDto = Awaited<ReturnType<TriggerLogsService['findOne']>>
@@ -1,22 +0,0 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
import { TriggerLogsService } from './trigger-logs.service'
@Controller('trigger-logs')
export class TriggerLogsController {
constructor(private readonly triggerLogsService: TriggerLogsService) {}
@Get()
findAll() {
return this.triggerLogsService.findAll()
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.triggerLogsService.findOne(+id)
}
@Post()
create(@Body() data: any) {
return this.triggerLogsService.create(data)
}
}
@@ -1,9 +0,0 @@
import { Module } from '@nestjs/common'
import { TriggerLogsController } from './trigger-logs.controller'
import { TriggerLogsService } from './trigger-logs.service'
@Module({
controllers: [TriggerLogsController],
providers: [TriggerLogsService],
})
export class TriggerLogsModule {}
@@ -1,19 +0,0 @@
import { Injectable } from '@nestjs/common'
@Injectable()
export class TriggerLogsService {
findAll() {
// TODO: Implement fetching all trigger logs
return []
}
findOne(id: number) {
// TODO: Implement fetching a single trigger log
return {}
}
create(data: any) {
// TODO: Implement trigger log creation
return data
}
}