set consumer customers and saleInvoices

This commit is contained in:
2026-04-08 18:15:44 +03:30
parent b8c5cb4c80
commit 89726c8904
22 changed files with 936 additions and 411 deletions
@@ -71,7 +71,7 @@ export class SalesInvoicesService {
customer: {
select: {
type: true,
customer_individuals: {
customer_individual: {
select: {
economic_code: true,
first_name: true,
@@ -80,7 +80,7 @@ export class SalesInvoicesService {
national_id: true,
},
},
customer_legals: {
customer_legal: {
select: {
economic_code: true,
postal_code: true,
+2 -2
View File
@@ -1,4 +1,4 @@
import { ConsumerInfoInfo } from '@/common/decorators/consumerInfo.decorator'
import { ConsumerInfo } from '@/common/decorators/consumerInfo.decorator'
import { Controller, Get } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { ConsumerService } from './consumer.service'
@@ -9,7 +9,7 @@ export class ConsumerController {
constructor(private service: ConsumerService) {}
@Get('')
async findOne(@ConsumerInfoInfo('user_id') userId: string) {
async findOne(@ConsumerInfo('user_id') userId: string) {
return this.service.getInfo(userId)
}
}
+6 -1
View File
@@ -5,10 +5,15 @@ import { ConsumerBusinessActivitiesModule } from './business-activities/business
import { ConsumerController } from './consumer.controller'
import { ConsumerMiddleware } from './consumer.middleware'
import { ConsumerService } from './consumer.service'
import { ConsumerCustomersModule } from './customers/customers.module'
@Module({
controllers: [ConsumerController],
imports: [ConsumerAccountsModule, ConsumerBusinessActivitiesModule],
imports: [
ConsumerAccountsModule,
ConsumerBusinessActivitiesModule,
ConsumerCustomersModule,
],
providers: [JwtService, ConsumerService],
})
export class ConsumerModule implements NestModule {
@@ -0,0 +1,40 @@
import { ConsumerInfo } from '@/common/decorators/consumerInfo.decorator'
import { Body, Controller, Get, Param, Patch } from '@nestjs/common'
import { consumerCustomersService } from './customers.service'
import {
UpdateCustomerIndividualDto,
UpdateCustomerLegalDto,
} from './dto/create-customers.dto'
@Controller('consumer/customers')
export class consumerCustomersController {
constructor(private readonly service: consumerCustomersService) {}
@Get()
async findAll(@ConsumerInfo('user_id') userId: string) {
return this.service.findAll(userId)
}
@Get(':id')
async findOne(@ConsumerInfo('user_id') userId: string, @Param('id') id: string) {
return this.service.findOne(userId, id)
}
@Patch(':id/legal')
async updateLegal(
@ConsumerInfo('user_id') userId: string,
@Param('id') id: string,
@Body() data: UpdateCustomerLegalDto,
) {
return this.service.updateLegal(userId, id, data)
}
@Patch(':id/individual')
async updateIndividual(
@ConsumerInfo('user_id') userId: string,
@Param('id') id: string,
@Body() data: UpdateCustomerIndividualDto,
) {
return this.service.updateIndividual(userId, id, data)
}
}
@@ -0,0 +1,12 @@
import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common'
import { consumerCustomersController } from './customers.controller'
import { consumerCustomersService } from './customers.service'
import { ConsumerSaleInvoicesModule } from './sale-invoices/sale-invoices.module'
@Module({
imports: [PrismaModule, ConsumerSaleInvoicesModule],
controllers: [consumerCustomersController],
providers: [consumerCustomersService],
})
export class ConsumerCustomersModule {}
@@ -0,0 +1,145 @@
import { CustomerSelect, CustomerWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
import {
UpdateCustomerIndividualDto,
UpdateCustomerLegalDto,
} from './dto/create-customers.dto'
@Injectable()
export class consumerCustomersService {
constructor(private readonly prisma: PrismaService) {}
defaultSelect: CustomerSelect = {
id: true,
type: true,
is_favorite: true,
created_at: true,
customer_individual: {
select: {
first_name: true,
last_name: true,
national_id: true,
postal_code: true,
economic_code: true,
},
},
customer_legal: {
select: {
company_name: true,
registration_number: true,
postal_code: true,
economic_code: true,
},
},
}
private defaultWhere(user_id: string): CustomerWhereInput {
return {
OR: [
{
customer_individual: {
complex: {
business_activity: {
user_id,
},
},
},
},
{
customer_legal: {
complex: {
business_activity: {
user_id,
},
},
},
},
],
}
}
async findAll(user_id: string, page = 1, pageSize = 10) {
const [customers, count] = await this.prisma.$transaction(async tx => [
await tx.customer.findMany({
where: this.defaultWhere(user_id),
select: this.defaultSelect,
skip: (page - 1) * pageSize,
take: 10,
}),
await tx.customer.count({
where: this.defaultWhere(user_id),
}),
])
return ResponseMapper.paginate(customers, { count, page, pageSize })
}
async findOne(user_id: string, customer_id: string) {
const customer = await this.prisma.customer.findUniqueOrThrow({
where: {
...this.defaultWhere(user_id),
id: customer_id,
},
select: this.defaultSelect,
})
console.log(customer)
return ResponseMapper.single(customer)
}
async updateLegal(user_id: string, customer_id: string, data: UpdateCustomerLegalDto) {
const customer = await this.prisma.customer.update({
where: {
id: customer_id,
customer_legal: {
complex: {
business_activity: {
user_id,
},
},
},
},
data: {
is_favorite: data.is_favorite,
customer_legal: {
update: {
...data,
},
},
},
})
return ResponseMapper.update(customer)
}
async updateIndividual(
user_id: string,
customer_id: string,
data: UpdateCustomerIndividualDto,
) {
const customer = await this.prisma.customer.update({
where: {
id: customer_id,
customer_individual: {
complex: {
business_activity: {
user_id,
},
},
},
},
data: {
is_favorite: data.is_favorite,
customer_individual: {
update: {
...data,
},
},
},
})
return ResponseMapper.update(customer)
}
}
@@ -0,0 +1,74 @@
import { ApiProperty } from '@nestjs/swagger'
import {
IsBoolean,
IsNumber,
IsOptional,
IsString,
MaxLength,
MinLength,
} from 'class-validator'
export class UpdateCustomerLegalDto {
@IsString()
@IsOptional()
@ApiProperty({ required: true })
company_name?: string
@IsString()
@IsOptional()
@ApiProperty({ required: true })
economic_code?: string
@IsString()
@IsOptional()
@ApiProperty({ required: true })
registration_number?: string
@IsNumber()
@MaxLength(10)
@MinLength(10)
@IsOptional()
@ApiProperty({ maxLength: 10, minLength: 10 })
postal_code?: string
@IsBoolean()
@IsOptional()
@ApiProperty({ required: false })
is_favorite?: boolean
}
export class UpdateCustomerIndividualDto {
@IsString()
@IsOptional()
@ApiProperty({ required: true })
first_name?: string
@IsString()
@IsOptional()
@ApiProperty({ required: true })
last_name?: string
@IsNumber()
@MaxLength(10)
@MinLength(10)
@IsOptional()
@ApiProperty({ required: true, maxLength: 10, minLength: 10 })
national_code?: string
@IsNumber()
@MaxLength(10)
@MinLength(10)
@IsOptional()
@ApiProperty({ maxLength: 10, minLength: 10 })
postal_code?: string
@IsBoolean()
@IsOptional()
@ApiProperty({ required: false })
is_favorite?: boolean
@IsNumber()
@IsOptional()
@ApiProperty({ required: false })
economic_code?: string
}
@@ -0,0 +1,27 @@
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import { Controller, Get, Param } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { CustomerSaleInvoicesService } from './sale-invoices.service'
@ApiTags('customerSaleInvoices')
@Controller('consumer/customers/:customerId/sale-invoices')
export class CustomerSaleInvoicesController {
constructor(private readonly service: CustomerSaleInvoicesService) {}
@Get()
async findAll(
@TokenAccount('userId') userId: string,
@Param('customerId') customerId: string,
) {
return this.service.findAll(userId, customerId)
}
@Get(':id')
async findOne(
@TokenAccount('userId') userId: string,
@Param('customerId') customerId: string,
@Param('id') id: string,
) {
return this.service.findOne(userId, customerId, id)
}
}
@@ -0,0 +1,11 @@
import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common'
import { CustomerSaleInvoicesController } from './sale-invoices.controller'
import { CustomerSaleInvoicesService } from './sale-invoices.service'
@Module({
imports: [PrismaModule],
controllers: [CustomerSaleInvoicesController],
providers: [CustomerSaleInvoicesService],
})
export class ConsumerSaleInvoicesModule {}
@@ -0,0 +1,152 @@
import { SalesInvoiceSelect, SalesInvoiceWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
@Injectable()
export class CustomerSaleInvoicesService {
constructor(private readonly prisma: PrismaService) {}
defaultSelect: SalesInvoiceSelect = {
id: true,
code: true,
invoice_date: true,
notes: true,
total_amount: true,
pos: {
select: {
id: true,
name: true,
complex: {
select: {
id: true,
name: true,
business_activity: {
select: {
id: true,
name: true,
},
},
},
},
},
},
account: {
select: {
role: true,
user: {
select: {
first_name: true,
last_name: true,
},
},
account: {
select: {
username: true,
},
},
},
},
created_at: true,
}
async findAll(user_id: string, customer_id: string, page = 1, pageSize = 10) {
const salesWhere: SalesInvoiceWhereInput = {
customer_id,
pos: {
complex: {
business_activity: {
user_id,
},
},
},
}
const [accounts, count] = await this.prisma.$transaction(async tx => [
await tx.salesInvoice.findMany({
where: salesWhere,
select: {
...this.defaultSelect,
_count: {
select: {
items: true,
},
},
},
skip: (page - 1) * pageSize,
take: 10,
}),
await tx.salesInvoice.count({
where: salesWhere,
}),
])
const mappedAccounts = accounts.map(account => {
const { _count, ...rest } = account
return {
...rest,
items_count: _count.items,
}
})
return ResponseMapper.paginate(mappedAccounts, {
count,
page,
pageSize,
})
}
async findOne(user_id: string, customer_id: string, id: string) {
const account = await this.prisma.salesInvoice.findUniqueOrThrow({
where: {
id,
customer_id,
pos: {
complex: {
business_activity: {
user_id,
},
},
},
},
select: {
...this.defaultSelect,
items: {
select: {
id: true,
notes: true,
unit_price: true,
discount: true,
quantity: true,
total_amount: true,
payload: true,
good: {
select: {
id: true,
name: true,
pricing_model: true,
unit_type: true,
category: {
select: {
id: true,
name: true,
image_url: true,
},
},
},
},
},
},
payments: {
select: {
amount: true,
paid_at: true,
payment_method: true,
},
},
},
})
return ResponseMapper.single(account)
}
}
@@ -40,6 +40,8 @@ export class SalesInvoicesService {
}
async create(data: CreateSalesInvoiceDto, posInfo: IPosPayload) {
console.log(posInfo)
data.invoice_date = new Date(data.invoice_date).toISOString() as any
const { complex_id, pos_id, consumer_account_id } = posInfo