transform core api codes into this project, update modules as admin/pos context modules
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
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 {
|
||||
@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) {}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import { ApiProperty, PartialType } from '@nestjs/swagger'
|
||||
import { IsEnum, IsNumber, IsObject, IsOptional, IsString } from 'class-validator'
|
||||
import type { SaleInvoiceStandardPayload } from 'common/interfaces/sale-invoice-payload'
|
||||
import { UnitType } from 'generated/prisma/enums'
|
||||
|
||||
export class CreateSalesInvoiceItemDto {
|
||||
@IsNumber()
|
||||
@ApiProperty()
|
||||
unit_price: number
|
||||
|
||||
@IsNumber()
|
||||
@ApiProperty()
|
||||
total_amount: number
|
||||
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
invoice_id: string
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({ required: false })
|
||||
good_id?: string
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({ required: false })
|
||||
service_id?: string
|
||||
|
||||
@IsNumber()
|
||||
@ApiProperty({ required: true, default: 1 })
|
||||
quantity: number
|
||||
|
||||
@IsEnum(UnitType)
|
||||
@ApiProperty({ enum: Object.values(UnitType) })
|
||||
unit_type: UnitType
|
||||
|
||||
// @IsEnum(SalesInvoiceItemPricingModel)
|
||||
// @ApiProperty({ enum: Object.values(SalesInvoiceItemPricingModel) })
|
||||
// @IsOptional()
|
||||
// pricingModel: SalesInvoiceItemPricingModel
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
@ApiProperty({ required: false, default: {} })
|
||||
payload?: SaleInvoiceStandardPayload
|
||||
|
||||
@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
|
||||
}
|
||||
}
|
||||
+32
@@ -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,
|
||||
) {}
|
||||
+24
@@ -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 {}
|
||||
+19
@@ -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,25 @@
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
|
||||
|
||||
import { reqTokenPayload } from '@/modules/auth/current-user.decorator'
|
||||
import { CreateSalesInvoiceDto } from './dto/create-sales-invoice.dto'
|
||||
import { SalesInvoicesService } from './sales-invoices.service'
|
||||
|
||||
@Controller('pos/sales_invoices')
|
||||
export class SalesInvoicesController {
|
||||
constructor(private readonly salesInvoicesService: SalesInvoicesService) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.salesInvoicesService.findAll()
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id') id: string) {
|
||||
return this.salesInvoicesService.findOne(+id)
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() data: CreateSalesInvoiceDto, @reqTokenPayload() account) {
|
||||
return this.salesInvoicesService.create(data, account)
|
||||
}
|
||||
}
|
||||
@@ -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 PosSalesInvoicesModule {}
|
||||
@@ -0,0 +1,194 @@
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { 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'
|
||||
import { CreateSalesInvoiceDto } from './dto/create-sales-invoice.dto'
|
||||
|
||||
// Define type guard for CustomerIndividual
|
||||
function isCustomerIndividual(customer: any): customer is CustomerIndividual {
|
||||
console.log(
|
||||
customer &&
|
||||
typeof customer.first_name === 'string' &&
|
||||
typeof customer.last_name === 'string',
|
||||
)
|
||||
|
||||
return (
|
||||
customer &&
|
||||
typeof customer.first_name === 'string' &&
|
||||
typeof customer.last_name === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
// Define type guard for CustomerLegal
|
||||
function isCustomerLegal(customer: any): customer is CustomerLegal {
|
||||
return (
|
||||
customer &&
|
||||
typeof customer.company_name === 'string' &&
|
||||
typeof customer.registration_number === 'string'
|
||||
)
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SalesInvoicesService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
findAll() {
|
||||
// TODO: Implement fetching all sales invoices
|
||||
return []
|
||||
}
|
||||
|
||||
findOne(id: number) {
|
||||
// TODO: Implement fetching a single sales invoice
|
||||
return {}
|
||||
}
|
||||
|
||||
async create(data: CreateSalesInvoiceDto, account) {
|
||||
data.invoice_date = new Date(data.invoice_date).toISOString() as any
|
||||
|
||||
const salesInvoice = await this.prisma.$transaction(async $tx => {
|
||||
const payments = Object.entries(data.payments)
|
||||
.filter(([_, value]) => value > 0 && PaymentMethodType[_.toUpperCase()])
|
||||
.map(([key, value]) => {
|
||||
return {
|
||||
amount: value,
|
||||
payment_method: key.toLocaleUpperCase() as PaymentMethodType,
|
||||
paid_at: data.invoice_date,
|
||||
}
|
||||
})
|
||||
|
||||
const totalPayments = payments.reduce((sum, payment) => sum + payment.amount, 0)
|
||||
if (totalPayments !== data.total_amount) {
|
||||
throw new Error('مبلغ پرداختی باید برابر با مبلغ کل فاکتور باشد.')
|
||||
}
|
||||
|
||||
const { customer_id, customer_type, customer, ...invoiceData } = data
|
||||
let newCustomerId: string | null = customer_id || null
|
||||
if (customer_id) {
|
||||
} else if (
|
||||
customer_type === CustomerType.INDIVIDUAL &&
|
||||
isCustomerIndividual(customer)
|
||||
) {
|
||||
let customerIndividual = await $tx.customerIndividual.findUnique({
|
||||
where: {
|
||||
complex_id_national_id: {
|
||||
complex_id: account.complex_id,
|
||||
national_id: customer.national_id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (customerIndividual) {
|
||||
await $tx.customerIndividual.update({
|
||||
where: {
|
||||
complex_id_national_id: {
|
||||
complex_id: account.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,
|
||||
complex_id: account.complex_id,
|
||||
customerIndividuals: {
|
||||
connect: {
|
||||
customer_id: customerIndividual.customer_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (createdCustomer && createdCustomer.id) {
|
||||
newCustomerId = createdCustomer.id
|
||||
}
|
||||
}
|
||||
} else if (data.customer_type === CustomerType.LEGAL && isCustomerLegal(customer)) {
|
||||
let customerLegal = await $tx.customerLegal.findUnique({
|
||||
where: {
|
||||
complex_id_registration_number: {
|
||||
complex_id: account.complex_id,
|
||||
registration_number: customer.registration_number,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (customerLegal) {
|
||||
await $tx.customerLegal.update({
|
||||
where: {
|
||||
complex_id_registration_number: {
|
||||
complex_id: account.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,
|
||||
complex_id: account.complex_id,
|
||||
customerIndividuals: {
|
||||
connect: {
|
||||
customer_id: customerLegal.customer_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (createdCustomer && createdCustomer.id) {
|
||||
newCustomerId = createdCustomer.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const salesInvoice = await $tx.salesInvoice.create({
|
||||
data: {
|
||||
...invoiceData,
|
||||
account_id: account.account_id,
|
||||
customer_id: newCustomerId,
|
||||
total_amount: data.total_amount,
|
||||
code: 'INV-' + Date.now(),
|
||||
complex_id: account.complex_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,
|
||||
unit_type: item.unit_type,
|
||||
// pricing_model: item.pricingModel,
|
||||
})),
|
||||
},
|
||||
},
|
||||
payments: {
|
||||
createMany: {
|
||||
data: payments,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return salesInvoice
|
||||
})
|
||||
return ResponseMapper.create(salesInvoice)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user