refactor: restructure suppliers module and update DTOs

- Removed old supplier DTOs and controller, replacing them with new implementations.
- Introduced new CreateSupplierDto and UpdateSupplierDto in the index directory.
- Updated SuppliersController to handle new routes and methods.
- Implemented SuppliersService with updated logic for creating, finding, updating, and removing suppliers.
- Added new invoices module with corresponding controller and service for handling invoice-related operations.
- Created new DTOs for handling receipt payments and updated the service to manage payment creation and retrieval.
- Updated Prisma migrations to reflect changes in the database schema, including dropping unnecessary columns.
This commit is contained in:
2025-12-27 20:34:00 +03:30
parent d98507fc1f
commit af9695e23c
27 changed files with 636 additions and 575 deletions
@@ -0,0 +1,30 @@
import { IsEnum, IsInt, IsNumber, IsOptional, IsString } from 'class-validator'
import { PaymentMethodType, PaymentType } from '../../../generated/prisma/enums'
export class CreatePurchaseReceiptPaymentDto {
@IsNumber()
amount: number
@IsEnum(PaymentMethodType)
paymentMethod: PaymentMethodType
@IsEnum(PaymentType)
type: PaymentType
@IsInt()
bankAccountId: number
@IsInt()
receiptId: number
@IsString()
payedAt: string
@IsOptional()
@IsString()
description?: string
@IsOptional()
@IsString()
createdAt?: string
}
@@ -0,0 +1,6 @@
import { PartialType } from '@nestjs/swagger'
import { CreatePurchaseReceiptPaymentDto } from './create-purchase-receipt-payment.dto'
export class UpdatePurchaseReceiptPaymentDto extends PartialType(
CreatePurchaseReceiptPaymentDto,
) {}
@@ -0,0 +1,36 @@
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'
import { CreatePurchaseReceiptPaymentDto } from './dto/create-purchase-receipt-payment.dto'
import { UpdatePurchaseReceiptPaymentDto } from './dto/update-purchase-receipt-payment.dto'
import { PurchaseReceiptPaymentsService } from './purchase-receipt-payments.service'
@Controller('purchase-receipt-payments')
export class PurchaseReceiptPaymentsController {
constructor(
private readonly purchaseReceiptPaymentsService: PurchaseReceiptPaymentsService,
) {}
@Post()
create(@Body() dto: CreatePurchaseReceiptPaymentDto) {
return this.purchaseReceiptPaymentsService.create(dto)
}
@Get()
findAll() {
return this.purchaseReceiptPaymentsService.findAll()
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.purchaseReceiptPaymentsService.findOne(Number(id))
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdatePurchaseReceiptPaymentDto) {
return this.purchaseReceiptPaymentsService.update(Number(id), dto)
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.purchaseReceiptPaymentsService.remove(Number(id))
}
}
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common'
import { PrismaModule } from '../../prisma/prisma.module'
import { PurchaseReceiptPaymentsController } from './purchase-receipt-payments.controller'
import { PurchaseReceiptPaymentsService } from './purchase-receipt-payments.service'
@Module({
imports: [PrismaModule],
controllers: [PurchaseReceiptPaymentsController],
providers: [PurchaseReceiptPaymentsService],
})
export class PurchaseReceiptPaymentsModule {}
@@ -0,0 +1,65 @@
import { Injectable } from '@nestjs/common'
import { ResponseMapper } from '../../common/response/response-mapper'
import { PrismaService } from '../../prisma/prisma.service'
@Injectable()
export class PurchaseReceiptPaymentsService {
constructor(private prisma: PrismaService) {}
async create(data: any) {
const item = await this.prisma.purchaseReceiptPayments.create({ data })
return ResponseMapper.create(item)
}
async findAll() {
const items = await this.prisma.purchaseReceiptPayments.findMany({
include: {
receipt: {
select: {
id: true,
code: true,
totalAmount: true,
paidAmount: true,
status: true,
supplier: {
select: { id: true, firstName: true, lastName: true },
},
},
},
},
})
return ResponseMapper.list(items)
}
async findOne(id: number) {
const item = await this.prisma.purchaseReceiptPayments.findUnique({
where: { id },
include: {
receipt: {
select: {
id: true,
code: true,
totalAmount: true,
paidAmount: true,
status: true,
supplier: {
select: { id: true, firstName: true, lastName: true },
},
},
},
},
})
if (!item) return null
return ResponseMapper.single(item)
}
async update(id: number, data: any) {
const item = await this.prisma.purchaseReceiptPayments.update({ where: { id }, data })
return ResponseMapper.update(item)
}
async remove(id: number) {
const item = await this.prisma.purchaseReceiptPayments.delete({ where: { id } })
return ResponseMapper.single(item)
}
}
@@ -0,0 +1,33 @@
import { IsEmail, IsOptional, IsString } from 'class-validator'
export class CreateSupplierDto {
@IsString()
firstName: string
@IsString()
lastName: string
@IsOptional()
@IsEmail()
email?: string
@IsOptional()
@IsString()
mobileNumber?: string
@IsOptional()
@IsString()
address?: string
@IsOptional()
@IsString()
city?: string
@IsOptional()
@IsString()
state?: string
@IsOptional()
@IsString()
country?: string
}
@@ -0,0 +1,41 @@
import { Type } from 'class-transformer'
import { IsBoolean, IsEmail, IsOptional, IsString } from 'class-validator'
export class UpdateSupplierDto {
@IsOptional()
@IsString()
firstName?: string
@IsOptional()
@IsString()
lastName?: string
@IsOptional()
@IsEmail()
email?: string
@IsOptional()
@IsString()
mobileNumber?: string
@IsOptional()
@IsString()
address?: string
@IsOptional()
@IsString()
city?: string
@IsOptional()
@IsString()
state?: string
@IsOptional()
@IsString()
country?: string
@IsOptional()
@Type(() => Boolean)
@IsBoolean()
isActive?: boolean
}
@@ -0,0 +1,39 @@
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'
import { CreateSupplierDto } from './dto/create-supplier.dto'
import { UpdateSupplierDto } from './dto/update-supplier.dto'
import { SuppliersService } from './suppliers.service'
@Controller('suppliers')
export class SuppliersController {
constructor(private readonly suppliersService: SuppliersService) {}
@Post()
create(@Body() dto: CreateSupplierDto) {
return this.suppliersService.create(dto)
}
@Get()
findAll() {
return this.suppliersService.findAll()
}
@Get(':supplierId')
findOne(@Param('supplierId') supplierId: string) {
return this.suppliersService.findOne(Number(supplierId))
}
@Get(':supplierId/ledger')
getLedger(@Param('supplierId') supplierId: string) {
return this.suppliersService.getLedger(Number(supplierId))
}
@Patch(':id')
update(@Param('id') id: string, @Body() dto: UpdateSupplierDto) {
return this.suppliersService.update(Number(id), dto)
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.suppliersService.remove(Number(id))
}
}
@@ -0,0 +1,61 @@
import { Injectable } from '@nestjs/common'
import { ResponseMapper } from '../../../common/response/response-mapper'
import { PrismaService } from '../../../prisma/prisma.service'
@Injectable()
export class SuppliersService {
constructor(private prisma: PrismaService) {}
async create(data: any) {
const item = await this.prisma.supplier.create({ data })
return ResponseMapper.create(item)
}
async findAll() {
const items = await this.prisma.supplier.findMany()
return ResponseMapper.list(items)
}
async findOne(id: number) {
const item = await this.prisma.supplier.findUnique({ where: { id } })
if (!item) return null
const receiptsInfo = await this.prisma.purchaseReceipt.aggregate({
where: {
supplierId: id,
},
_count: true,
_sum: {
totalAmount: true,
},
})
return ResponseMapper.single({
...item,
receiptsOverview: {
totalPayment: receiptsInfo._sum.totalAmount,
count: receiptsInfo._count,
},
})
}
async getLedger(supplierId: number) {
const items = await this.prisma.supplierLedger.findMany({
where: {
supplierId,
},
omit: {
supplierId: true,
},
})
return ResponseMapper.list(items)
}
async update(id: number, data: any) {
const item = await this.prisma.supplier.update({ where: { id }, data })
return ResponseMapper.update(item)
}
async remove(id: number) {
const item = await this.prisma.supplier.delete({ where: { id } })
return ResponseMapper.single(item)
}
}
@@ -0,0 +1,34 @@
import {
IsDateString,
IsEnum,
IsInt,
IsNumber,
IsOptional,
IsString,
} from 'class-validator'
import { PaymentMethodType, PaymentType } from '../../../../generated/prisma/enums'
export class CreateReceiptPaymentDto {
@IsNumber()
amount: number
@IsEnum(PaymentMethodType)
paymentMethod: PaymentMethodType
@IsEnum(PaymentType)
type: PaymentType
@IsInt()
bankAccountId: number
@IsDateString()
payedAt: string
@IsOptional()
@IsString()
description?: string
@IsOptional()
@IsString()
createdAt?: string
}
@@ -0,0 +1,42 @@
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
import { CreateReceiptPaymentDto } from './dto/create-receipt-payment.dto'
import { SupplierInvoicesService } from './invoices.service'
@Controller('suppliers/:supplierId/invoices')
export class SupplierInvoicesController {
constructor(private readonly supplierInvoicesService: SupplierInvoicesService) {}
@Get()
getInvoices(@Param('supplierId') supplierId: string) {
return this.supplierInvoicesService.findAll(Number(supplierId))
}
@Get(':invoiceId')
getInvoice(
@Param('supplierId') supplierId: string,
@Param('invoiceId') invoiceId: string,
) {
return this.supplierInvoicesService.findOne(Number(supplierId), Number(invoiceId))
}
@Post(':invoiceId/pay')
createPayment(
@Param('invoiceId') invoiceId: string,
@Body() data: CreateReceiptPaymentDto,
) {
return this.supplierInvoicesService.createPayment(Number(invoiceId), data)
}
@Get(':invoiceId/payments')
getInvoicePayments(
@Param('supplierId') supplierId: string,
@Param('invoiceId') invoiceId: string,
) {
return this.supplierInvoicesService.findPayments(Number(invoiceId))
}
@Get('payments')
getPayments(@Param('supplierId') supplierId: string) {
return this.supplierInvoicesService.findPayments(Number(supplierId))
}
}
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common'
import { PrismaModule } from '../../../prisma/prisma.module'
import { SupplierInvoicesController } from './invoices.controller'
import { SupplierInvoicesService } from './invoices.service'
@Module({
imports: [PrismaModule],
controllers: [SupplierInvoicesController],
providers: [SupplierInvoicesService],
})
export class SupplierInvoicesModule {}
@@ -0,0 +1,145 @@
import { Injectable } from '@nestjs/common'
import { ResponseMapper } from '../../../common/response/response-mapper'
import { PrismaService } from '../../../prisma/prisma.service'
import { CreateReceiptPaymentDto } from './dto/create-receipt-payment.dto'
@Injectable()
export class SupplierInvoicesService {
constructor(private prisma: PrismaService) {}
async findAll(supplierId: number) {
const items = await this.prisma.purchaseReceipt.findMany({
where: {
supplierId,
},
include: {
inventory: {
select: {
id: true,
name: true,
},
},
items: {
select: {
id: true,
count: true,
fee: true,
total: true,
product: {
select: {
id: true,
name: true,
sku: true,
},
},
},
},
payments: {
select: {
id: true,
amount: true,
},
},
},
omit: {
inventoryId: true,
supplierId: true,
},
})
return ResponseMapper.list(items)
}
async findOne(supplierId: number, invoiceId: number) {
const invoice = await this.prisma.purchaseReceipt.findUnique({
where: {
id: invoiceId,
supplierId,
},
include: {
inventory: {
select: {
id: true,
name: true,
},
},
items: true,
},
omit: {
inventoryId: true,
supplierId: true,
},
})
return ResponseMapper.single(invoice)
}
async findPayments(invoiceId: number) {
const items = await this.prisma.purchaseReceiptPayments.findMany({
where: {
receipt: {
id: invoiceId,
},
},
include: {
receipt: {
include: {
inventory: {
select: {
id: true,
name: true,
},
},
},
},
},
omit: {
receiptId: true,
},
})
return ResponseMapper.list(items)
}
async findAllPayments(supplierId: number) {
const items = await this.prisma.purchaseReceiptPayments.findMany({
where: {
receipt: {
supplierId,
},
},
include: {
receipt: {
select: {
id: true,
totalAmount: true,
status: true,
paidAmount: true,
},
},
},
omit: {
receiptId: true,
},
})
return ResponseMapper.list(items)
}
async createPayment(invoiceId: number, data: CreateReceiptPaymentDto) {
const payment = await this.prisma.purchaseReceiptPayments.create({
data: {
...data,
payedAt: new Date(data.payedAt),
receipt: {
connect: {
id: invoiceId,
},
},
},
include: {
receipt: true,
},
omit: {
receiptId: true,
},
})
return ResponseMapper.create(payment)
}
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common'
import { PrismaModule } from '../../prisma/prisma.module'
import { SuppliersController } from './index/suppliers.controller'
import { SuppliersService } from './index/suppliers.service'
import { SupplierInvoicesModule } from './invoices/invoices.module'
@Module({
imports: [PrismaModule, SupplierInvoicesModule],
controllers: [SuppliersController],
providers: [SuppliersService],
})
export class SuppliersModule {}