change source of account id in prepared token to domain account id, create consumer salesInvoiceModule

This commit is contained in:
2026-03-30 13:16:36 +03:30
parent c870a43e35
commit 9cf9209daa
22 changed files with 758 additions and 142 deletions
+23
View File
@@ -0,0 +1,23 @@
node_modules
npm-debug.log
dist
.env
.env.local
.env.*.local
.git
.gitignore
README.md
.vscode
.idea
.DS_Store
*.log
coverage
.nyc_output
.jest-cache
prisma/dev.db
prisma/dev.db-journal
.turbo
.next
out
build
dist
+24
View File
@@ -0,0 +1,24 @@
# Server Configuration
NODE_ENV=development
PORT=5002
# Database Configuration
DB_HOST=localhost
DB_PORT=3306
DB_NAME=consumer_db
DB_USER=consumer_user
DB_PASSWORD=consumer_password
DB_ROOT_PASSWORD=root_password
DATABASE_URL=mysql://consumer_user:consumer_password@localhost:3306/consumer_db
SHADOW_DATABASE_URL=mysql://consumer_user:consumer_password@localhost:3306/consumer_db_shadow
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
JWT_EXPIRATION=604800
# CORS Configuration
CORS_ORIGINS=http://localhost:5000,http://127.0.0.1:5000
# File Upload Configuration
UPLOAD_PATH=./uploads
MAX_FILE_SIZE=10485760
+61
View File
@@ -0,0 +1,61 @@
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Install pnpm
RUN npm install -g pnpm
# Copy dependency files
COPY pnpm-lock.yaml package.json ./
# Install dependencies
RUN pnpm install --frozen-lockfile
# Copy source code
COPY . .
# Generate Prisma client and build the application
RUN pnpm exec prisma generate
RUN pnpm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
# Install pnpm
RUN npm install -g pnpm
# Install dumb-init for proper signal handling
RUN apk add --no-cache dumb-init
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install only production dependencies
RUN pnpm install --frozen-lockfile --prod
# Copy built application from builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
COPY prisma ./prisma
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
# Expose port
EXPOSE 5002
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:5002/api/v1/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
# Use dumb-init to handle signals properly
ENTRYPOINT ["dumb-init", "--"]
# Start application
CMD ["node", "dist/main.js"]
+73
View File
@@ -0,0 +1,73 @@
version: "3.9"
services:
database:
image: mariadb:11.4-jammy
container_name: consumer_api_db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root_password}
MARIADB_DATABASE: ${DB_NAME:-consumer_db}
MARIADB_USER: ${DB_USER:-consumer_user}
MARIADB_PASSWORD: ${DB_PASSWORD:-consumer_password}
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "false"
ports:
- "${DB_PORT:-3306}:3306"
volumes:
- mariadb_data:/var/lib/mysql
- ./prisma/migrations:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
networks:
- consumer_network
api:
build:
context: .
dockerfile: Dockerfile
container_name: consumer_api
restart: unless-stopped
depends_on:
database:
condition: service_healthy
environment:
NODE_ENV: ${NODE_ENV:-production}
PORT: ${PORT:-5002}
DATABASE_URL: mysql://${DB_USER:-consumer_user}:${DB_PASSWORD:-consumer_password}@database:3306/${DB_NAME:-consumer_db}
SHADOW_DATABASE_URL: mysql://${DB_USER:-consumer_user}:${DB_PASSWORD:-consumer_password}@database:3306/${DB_NAME:-consumer_db}_shadow
JWT_SECRET: ${JWT_SECRET:-your_jwt_secret_key_change_in_production}
JWT_EXPIRATION: ${JWT_EXPIRATION:-604800}
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:5000,http://127.0.0.1:5000}
ports:
- "${PORT:-5002}:5002"
volumes:
- ./src:/app/src
- /app/dist
- /app/node_modules
networks:
- consumer_network
healthcheck:
test:
[
"CMD",
"wget",
"--quiet",
"--tries=1",
"--spider",
"http://localhost:5002/api/v1/health",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
mariadb_data:
driver: local
networks:
consumer_network:
driver: bridge
+4 -8
View File
@@ -60,7 +60,7 @@ export class PosGuard implements CanActivate {
user: {
accounts: {
some: {
account_id: account.account_id,
id: account.account_id,
},
},
},
@@ -81,20 +81,16 @@ export class PosGuard implements CanActivate {
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
}
const foundedAccount = await this.prisma.account.findUnique({
const foundedAccount = await this.prisma.consumerAccount.findUnique({
where: {
id: account.account_id,
},
select: {
consumer_account: {
select: {
role: true,
},
},
role: true,
},
})
if (foundedAccount?.consumer_account?.role === 'OWNER') {
if (foundedAccount?.role === 'OWNER') {
return true
}
+58 -15
View File
@@ -40,7 +40,6 @@ export class AuthUtils {
id: accountId,
},
select: {
id: true,
admin_account: {
select: {
id: true,
@@ -58,10 +57,16 @@ export class AuthUtils {
},
})
if (!adminAccount) throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
if (!adminAccount || !adminAccount.admin_account)
throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
const { user, id } = adminAccount.admin_account
return {
...adminAccount.admin_account?.user,
fullname: `${adminAccount.admin_account?.user.first_name} ${adminAccount.admin_account?.user.last_name}`,
account_id: id,
user: {
...user,
fullname: `${user.first_name} ${user.last_name}`,
},
}
}
@@ -73,6 +78,7 @@ export class AuthUtils {
select: {
consumer_account: {
select: {
id: true,
user: {
select: {
id: true,
@@ -86,8 +92,17 @@ export class AuthUtils {
},
})
if (!consumerAccount) throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
return consumerAccount.consumer_account?.user
if (!consumerAccount || !consumerAccount.consumer_account)
throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
const { user, id } = consumerAccount.consumer_account
return {
account_id: id,
user: {
...user,
fullname: `${user.first_name} ${user.last_name}`,
},
}
}
async getProviderAccountInfo(accountId: string) {
@@ -98,6 +113,7 @@ export class AuthUtils {
select: {
provider_account: {
select: {
id: true,
user: {
select: {
id: true,
@@ -111,8 +127,17 @@ export class AuthUtils {
},
})
if (!providerAccount) throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
return providerAccount.provider_account?.user
if (!providerAccount || !providerAccount.provider_account)
throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
const { user, id } = providerAccount.provider_account
return {
account_id: id,
user: {
...user,
fullname: user.name,
},
}
}
async getPartnerAccountInfo(accountId: string) {
@@ -123,6 +148,7 @@ export class AuthUtils {
select: {
partner_account: {
select: {
id: true,
user: {
select: {
id: true,
@@ -136,33 +162,50 @@ export class AuthUtils {
},
})
if (!partnerAccount) throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
return partnerAccount.partner_account?.user
if (!partnerAccount || !partnerAccount.partner_account)
throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
const { user, id } = partnerAccount.partner_account
return {
account_id: id,
user: {
...user,
fullname: user.name,
},
}
}
async generateLoginResponse(account: Account) {
let preparedAccount = {
type: account.type,
username: account.username,
account_id: account.id,
account_id: '',
user: {},
} as AccessTokenPayload
let accountInfo = {
user: {},
account_id: '',
}
switch (account.type) {
case AccountType.ADMIN:
preparedAccount.user = await this.getAdminAccountInfo(account.id)
accountInfo = await this.getAdminAccountInfo(account.id)
break
case AccountType.CONSUMER:
preparedAccount.user = await this.getConsumerAccountInfo(account.id)
accountInfo = await this.getConsumerAccountInfo(account.id)
break
case AccountType.PARTNER:
preparedAccount.user = await this.getPartnerAccountInfo(account.id)
accountInfo = await this.getPartnerAccountInfo(account.id)
break
case AccountType.PROVIDER:
preparedAccount.user = await this.getProviderAccountInfo(account.id)
accountInfo = await this.getProviderAccountInfo(account.id)
break
}
preparedAccount.account_id = accountInfo.account_id
preparedAccount.user = accountInfo.user
if (!preparedAccount.user) {
throw new NotFoundException('متاسفانه کاربر شما یافت نشد')
} else {
@@ -2,9 +2,10 @@ import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common'
import { ComplexPosesController } from './poses.controller'
import { ComplexPosesService } from './poses.service'
import { ConsumerPosSalesInvoicesModule } from './sales-invoices/sales-invoices.module'
@Module({
imports: [PrismaModule],
imports: [PrismaModule, ConsumerPosSalesInvoicesModule],
controllers: [ComplexPosesController],
providers: [ComplexPosesService],
exports: [ComplexPosesService],
@@ -0,0 +1,66 @@
import { ApiProperty, PartialType } from '@nestjs/swagger'
import {
ArrayMinSize,
IsDateString,
IsEnum,
IsNumber,
IsObject,
IsOptional,
IsString,
} from 'class-validator'
import type { CustomerIndividual, CustomerLegal } from 'generated/prisma/client'
import { CustomerType } from 'generated/prisma/enums'
import { CreateSalesInvoiceItemDto } from '../sales-invoice-items/dto/create-sales-invoice-item.dto'
export class CreateSalesInvoiceDto {
// @TODO: totalAmount must calculated instead of get from api
@IsNumber()
@ApiProperty({ required: true, default: 0 })
total_amount: number
@ApiProperty({ required: true })
@IsDateString(
{ strict: true },
{ message: 'invoice_date must be a valid ISO-8601 string' },
)
invoice_date: Date
@ApiProperty({ required: true })
@IsObject()
payments: {
terminal: number
cash: number
set_off: number
}
@ApiProperty()
@ArrayMinSize(1)
items: CreateSalesInvoiceItemDto[]
@ApiProperty({ required: false })
@IsOptional()
@IsString()
notes?: string
@ApiProperty({ required: true, default: CustomerType.UNKNOWN })
@IsEnum(CustomerType)
customer_type: CustomerType
@IsOptional()
@IsString()
@ApiProperty({ required: false })
customer_id?: string
@ApiProperty({ required: false })
@IsOptional()
@IsObject()
customer?:
| {
first_name: string
last_name: string
}
| CustomerIndividual
| CustomerLegal
}
export class UpdateSalesInvoiceDto extends PartialType(CreateSalesInvoiceDto) {}
@@ -0,0 +1,57 @@
import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsEnum, IsNumber, IsObject, IsOptional, IsString } from 'class-validator'
import type { SaleInvoiceType } from 'common/interfaces/sale-invoice-payload'
import { UnitType } from 'generated/prisma/enums'
export class CreateSalesInvoiceItemDto {
@IsNumber()
@ApiProperty({ required: true })
unit_price: number
@IsNumber()
@ApiProperty({ required: true, default: 1 })
quantity: number
@IsNumber()
@ApiProperty({ required: true })
total_amount: number
@IsNumber()
@ApiProperty({ required: true })
discount_amount: number
@IsString()
@ApiProperty({ required: true })
invoice_id: string
@IsEnum(UnitType)
@ApiProperty({ enum: Object.values(UnitType) })
unit_type: UnitType
@IsOptional()
@IsString()
@ApiProperty({ required: false })
good_id?: string
@IsOptional()
@IsString()
@ApiProperty({ required: false })
service_id?: string
// @IsEnum(SalesInvoiceItemPricingModel)
// @ApiProperty({ enum: Object.values(SalesInvoiceItemPricingModel) })
// @IsOptional()
// pricingModel: SalesInvoiceItemPricingModel
@IsOptional()
@IsObject()
@ApiProperty({ required: false, default: {} })
payload: SaleInvoiceType
@IsOptional()
@IsString()
@ApiProperty({ required: false, default: '' })
notes: string
}
export class UpdateSalesInvoiceItemDto extends PartialType(CreateSalesInvoiceItemDto) {}
@@ -0,0 +1,22 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
import { SalesInvoiceItemsService } from './sales-invoice-items.service'
@Controller('sales_invoice_items')
export class SalesInvoiceItemsController {
constructor(private readonly salesInvoiceItemsService: SalesInvoiceItemsService) {}
@Get()
findAll() {
return this.salesInvoiceItemsService.findAll()
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.salesInvoiceItemsService.findOne(+id)
}
@Post()
create(@Body() data: any) {
return this.salesInvoiceItemsService.create(data)
}
}
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common'
import { SalesInvoiceItemsController } from './sales-invoice-items.controller'
import { SalesInvoiceItemsService } from './sales-invoice-items.service'
@Module({
controllers: [SalesInvoiceItemsController],
providers: [SalesInvoiceItemsService],
})
export class SalesInvoiceItemsModule {}
@@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common'
@Injectable()
export class SalesInvoiceItemsService {
findAll() {
// TODO: Implement fetching all sales invoice items
return []
}
findOne(id: number) {
// TODO: Implement fetching a single sales invoice item
return {}
}
create(data: any) {
// TODO: Implement sales invoice item creation
return data
}
}
@@ -0,0 +1,32 @@
import { ApiProperty, PartialType } from '@nestjs/swagger'
import { IsDateString, IsEnum, IsNumber, IsString } from 'class-validator'
enum PaymentMethodType {
CASH = 'CASH',
CARD = 'CARD',
BANK = 'BANK',
CHECK = 'CHECK',
OTHER = 'OTHER',
}
export class CreateSalesInvoicePaymentDto {
@ApiProperty()
@IsString()
invoice_id: string
@ApiProperty()
@IsNumber()
amount: number
@ApiProperty({ enum: PaymentMethodType })
@IsEnum(PaymentMethodType)
payment_method: PaymentMethodType
@ApiProperty()
@IsDateString()
paid_at: string
}
export class UpdateSalesInvoicePaymentDto extends PartialType(
CreateSalesInvoicePaymentDto,
) {}
@@ -0,0 +1,24 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
import { SalesInvoicePaymentsService } from './sales-invoice-payments.service'
@Controller('sales-invoice-payments')
export class SalesInvoicePaymentsController {
constructor(
private readonly salesInvoicePaymentsService: SalesInvoicePaymentsService,
) {}
@Get()
findAll() {
return this.salesInvoicePaymentsService.findAll()
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.salesInvoicePaymentsService.findOne(+id)
}
@Post()
create(@Body() data: any) {
return this.salesInvoicePaymentsService.create(data)
}
}
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common'
import { SalesInvoicePaymentsController } from './sales-invoice-payments.controller'
import { SalesInvoicePaymentsService } from './sales-invoice-payments.service'
@Module({
controllers: [SalesInvoicePaymentsController],
providers: [SalesInvoicePaymentsService],
})
export class SalesInvoicePaymentsModule {}
@@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common'
@Injectable()
export class SalesInvoicePaymentsService {
findAll() {
// TODO: Implement fetching all sales invoice payments
return []
}
findOne(id: number) {
// TODO: Implement fetching a single sales invoice payment
return {}
}
create(data: any) {
// TODO: Implement sales invoice payment creation
return data
}
}
@@ -0,0 +1,29 @@
import { Controller, Get, Param } from '@nestjs/common'
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import { ApiTags } from '@nestjs/swagger'
import { SalesInvoicesService } from './sales-invoices.service'
@ApiTags('ConsumerComplexPoses')
@Controller('consumer/complexes/:complexId/poses/:posId/sales_invoices')
export class SalesInvoicesController {
constructor(private readonly salesInvoicesService: SalesInvoicesService) {}
@Get()
findAll(
@TokenAccount('userId') userId: string,
@Param('complexId') complexId: string,
@Param('posId') posId: string,
) {
return this.salesInvoicesService.findAll(userId, complexId, posId)
}
@Get(':id')
findOne(
@Param('complexId') complexId: string,
@Param('posId') posId: string,
@Param('id') id: string,
) {
return this.salesInvoicesService.findOne(complexId, posId, id)
}
}
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common'
import { SalesInvoicesController } from './sales-invoices.controller'
import { SalesInvoicesService } from './sales-invoices.service'
@Module({
controllers: [SalesInvoicesController],
providers: [SalesInvoicesService],
})
export class ConsumerPosSalesInvoicesModule {}
@@ -0,0 +1,108 @@
import { ResponseMapper } from '@/common/response/response-mapper'
import { SalesInvoiceWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common'
@Injectable()
export class SalesInvoicesService {
constructor(private prisma: PrismaService) {}
async findAll(user_id: string, complex_id: string, pos_id: string) {
const defaultWhere: SalesInvoiceWhereInput = {
pos_id,
pos: {
complex: {
id: complex_id,
business_activity: {
user_id,
},
},
},
}
const pageSize = 10
const page = 1
const [items, count] = await this.prisma.$transaction([
this.prisma.salesInvoice.findMany({
where: defaultWhere,
select: {
id: true,
code: true,
invoice_date: true,
notes: true,
total_amount: true,
items: {
select: {
unit_type: true,
discount: true,
notes: true,
quantity: true,
total_amount: true,
unit_price: true,
payload: true,
good: {
select: {
id: true,
name: true,
sku: true,
barcode: true,
local_sku: true,
pricing_model: true,
unit_type: true,
category: {
select: {
id: true,
name: true,
},
},
},
},
},
},
payments: {
select: {
amount: true,
paid_at: true,
payment_method: true,
},
},
customer: {
select: {
type: true,
customer_individuals: {
select: {
economic_code: true,
first_name: true,
last_name: true,
postal_code: true,
national_id: true,
},
},
customer_legals: {
select: {
economic_code: true,
postal_code: true,
registration_number: true,
},
},
},
},
unknown_customer: true,
},
skip: (page - 1) * pageSize,
take: pageSize,
}),
this.prisma.salesInvoice.count({
where: defaultWhere,
}),
])
return ResponseMapper.paginate(items, { count, page, pageSize })
}
findOne(complex_id: string, pos_id: string, id: string) {
// TODO: Implement fetching a single sales invoice
return {}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ export class PosMiddleware implements NestMiddleware {
const consumerAccount = await this.prisma.consumerAccount.findUnique({
where: {
account_id: tokenAccount.account_id,
id: tokenAccount.account_id,
},
})
if (!consumerAccount) {
@@ -54,13 +54,14 @@ export class CreateSalesInvoiceDto {
@ApiProperty({ required: false })
@IsOptional()
@IsObject()
customer?:
| {
first_name: string
last_name: string
}
| CustomerIndividual
| CustomerLegal
customer?: {
customer_individual?: Omit<CustomerIndividual, 'complex_id' | 'customer_id'>
customer_legal?: Omit<CustomerLegal, 'complex_id' | 'customer_id'>
customer_unknown?: {
first_name: string
last_name: string
}
}
}
export class UpdateSalesInvoiceDto extends PartialType(CreateSalesInvoiceDto) {}
@@ -1,6 +1,7 @@
import { IPosPayload } from '@/common/models/posPayload.model'
import { SalesInvoiceCreateInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common'
import { BadRequestException, Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
import type { CustomerIndividual, CustomerLegal } from 'generated/prisma/client'
import { CustomerType, PaymentMethodType } from 'generated/prisma/enums'
@@ -65,138 +66,128 @@ export class SalesInvoicesService {
if (customer_id) {
} else if (
customer_type === CustomerType.INDIVIDUAL &&
isCustomerIndividual(customer)
customer?.customer_individual
) {
let customerIndividual = await $tx.customerIndividual.findUnique({
const customer_individual = customer.customer_individual
const customerIndividual = await $tx.customerIndividual.upsert({
where: {
complex_id_national_id: {
complex_id,
national_id: customer.national_id,
national_id: customer_individual.national_id,
},
},
create: {
...customer_individual,
customer: {
create: {
type: CustomerType.INDIVIDUAL,
},
},
complex: {
connect: {
id: complex_id,
},
},
},
update: {},
select: {
customer_id: true,
},
})
if (customerIndividual) {
await $tx.customerIndividual.update({
where: {
complex_id_national_id: {
complex_id,
national_id: customer.national_id,
},
},
data: {
...customer,
},
})
} else {
const customerIndividual = await $tx.customerIndividual.create({
data: {
...customer,
},
})
const createdCustomer = await $tx.customer.create({
data: {
type: CustomerType.INDIVIDUAL,
customer_individuals: {
connect: {
customer_id: customerIndividual.customer_id,
},
},
},
})
if (createdCustomer && createdCustomer.id) {
newCustomerId = createdCustomer.id
}
if (!customerIndividual) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
}
} else if (data.customer_type === CustomerType.LEGAL && isCustomerLegal(customer)) {
let customerLegal = await $tx.customerLegal.findUnique({
newCustomerId = customerIndividual.customer_id
} else if (data.customer_type === CustomerType.LEGAL && customer?.customer_legal) {
const customer_legal = customer.customer_legal
const customerLegal = await $tx.customerLegal.upsert({
where: {
complex_id_registration_number: {
complex_id,
registration_number: customer.registration_number,
registration_number: customer_legal.registration_number,
},
},
create: {
...customer_legal,
customer: {
create: {
type: CustomerType.LEGAL,
},
},
complex: {
connect: {
id: complex_id,
},
},
},
update: {},
select: {
customer_id: true,
},
})
if (customerLegal) {
await $tx.customerLegal.update({
where: {
complex_id_registration_number: {
complex_id,
registration_number: customer.registration_number,
},
},
data: {
...customer,
},
})
} else {
const customerLegal = await $tx.customerLegal.create({
data: {
...customer,
},
})
const createdCustomer = await $tx.customer.create({
data: {
type: CustomerType.LEGAL,
customer_individuals: {
connect: {
customer_id: customerLegal.customer_id,
},
},
},
})
if (createdCustomer && createdCustomer.id) {
newCustomerId = createdCustomer.id
}
if (!customerLegal) {
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
}
newCustomerId = customerLegal.customer_id
} else if (data.customer_type === CustomerType.UNKNOWN) {
}
const salesInvoice = await $tx.salesInvoice.create({
data: {
...invoiceData,
total_amount: data.total_amount,
code: 'INV-' + Date.now(),
const salesInvoiceData: SalesInvoiceCreateInput = {
...invoiceData,
total_amount: data.total_amount,
code: 'INV-' + Date.now(),
items: {
createMany: {
data: data.items.map(item => ({
good_id: item.good_id,
quantity: item.quantity,
unit_price: item.unit_price,
total_amount: item.total_amount,
payload: JSON.parse(JSON.stringify(item.payload)),
unit_type: item.unit_type,
// pricing_model: item.pricingModel,
})),
},
},
unknown_customer: {},
payments: {
createMany: {
data: payments,
},
},
// customer: {
// connect: {
// id: newCustomerId,
// },
// },
account: {
connect: {
id: consumer_account_id,
},
},
pos: {
connect: {
id: pos_id,
},
items: {
createMany: {
data: data.items.map(item => ({
good_id: item.good_id,
quantity: item.quantity,
unit_price: item.unit_price,
total_amount: item.total_amount,
payload: item.payload
? JSON.parse(JSON.stringify(item.payload))
: undefined,
unit_type: item.unit_type,
// pricing_model: item.pricingModel,
})),
},
},
unknown_customer: {},
payments: {
createMany: {
data: payments,
},
},
// customer: {
// connect: {
// id: newCustomerId || undefined,
// },
// },
account: {
connect: {
id: consumer_account_id,
},
},
pos: {
connect: {
id: pos_id,
},
},
}
if (newCustomerId) {
salesInvoiceData.customer = {
connect: {
id: newCustomerId || undefined,
},
}
}
const salesInvoice = await $tx.salesInvoice.create({
data: salesInvoiceData,
})
return salesInvoice