refactor: restructure purchase receipts module and related workflows
- Removed old DTOs for creating and updating purchase receipts. - Updated purchase receipts controller and service to use new DTOs and workflows. - Introduced transaction helper for managing database transactions. - Added new workflows for handling purchase receipt payments and supplier ledgers. - Implemented new logic for managing purchase receipt items and payments. - Enhanced error handling for payment processing in workflows. - Updated supplier ledger management to reflect changes in purchase receipts.
This commit is contained in:
+1
-5
@@ -11,7 +11,7 @@ import { BanksModule } from './modules/banks/banks.module'
|
||||
import { CardexModule } from './modules/cardex/cardex.module'
|
||||
import { InventoriesModule } from './modules/inventories/inventories.module'
|
||||
import { PosModule } from './modules/pos/pos.module'
|
||||
import { PurchaseReceiptPaymentsModule } from './modules/purchase-receipt-payments/purchase-receipt-payments.module'
|
||||
import { PurchaseReceiptsModule } from './modules/purchase-receipts/purchase-receipts.module'
|
||||
import { StatisticsModule } from './modules/statistics/statistics.module'
|
||||
import { SuppliersModule } from './modules/suppliers/suppliers.module'
|
||||
import { PrismaModule } from './prisma/prisma.module'
|
||||
@@ -19,8 +19,6 @@ import { ProductBrandsModule } from './product-brands/product-brands.module'
|
||||
import { ProductCategoriesModule } from './product-categories/product-categories.module'
|
||||
import { ProductVariantsModule } from './product-variants/product-variants.module'
|
||||
import { ProductsModule } from './products/products.module'
|
||||
import { PurchaseReceiptItemsModule } from './purchase-receipt-items/purchase-receipt-items.module'
|
||||
import { PurchaseReceiptsModule } from './purchase-receipts/purchase-receipts.module'
|
||||
import { RolesModule } from './roles/roles.module'
|
||||
import { SalesInvoiceItemsModule } from './sales-invoice-items/sales-invoice-items.module'
|
||||
import { SalesInvoicesModule } from './sales-invoices/sales-invoices.module'
|
||||
@@ -43,8 +41,6 @@ import { UsersModule } from './users/users.module'
|
||||
CustomersModule,
|
||||
InventoriesModule,
|
||||
PurchaseReceiptsModule,
|
||||
PurchaseReceiptItemsModule,
|
||||
PurchaseReceiptPaymentsModule,
|
||||
SalesInvoicesModule,
|
||||
SalesInvoiceItemsModule,
|
||||
InventoryTransfersModule,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// src/common/database/transaction.helper.ts
|
||||
import { PrismaService } from '../../prisma/prisma.service'
|
||||
|
||||
export async function withTransaction<T>(
|
||||
prisma: PrismaService,
|
||||
fn: (tx: PrismaService) => Promise<T>,
|
||||
): Promise<T> {
|
||||
return prisma.$transaction(async tx => {
|
||||
return fn(tx as PrismaService)
|
||||
})
|
||||
}
|
||||
@@ -2,10 +2,12 @@ import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../../prisma/prisma.module'
|
||||
import { BankAccountsController } from './bank-accounts.controller'
|
||||
import { BankAccountsService } from './bank-accounts.service'
|
||||
import { BankAccountsWorkflow } from './bank-accounts.workflow'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [BankAccountsController],
|
||||
providers: [BankAccountsService],
|
||||
providers: [BankAccountsService, BankAccountsWorkflow],
|
||||
exports: [BankAccountsWorkflow],
|
||||
})
|
||||
export class BankAccountsModule {}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { withTransaction } from '../../common/database/transaction.helper'
|
||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../prisma/prisma.service'
|
||||
|
||||
@@ -6,8 +7,16 @@ import { PrismaService } from '../../prisma/prisma.service'
|
||||
export class BankAccountsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
async create(data: any) {
|
||||
const item = await this.prisma.bankAccount.create({ data })
|
||||
return ResponseMapper.create(item)
|
||||
return withTransaction(this.prisma, async tx => {
|
||||
const item = await tx.bankAccount.create({ data })
|
||||
await tx.bankAccountBalance.create({
|
||||
data: {
|
||||
bankAccountId: item.id,
|
||||
balance: 0,
|
||||
},
|
||||
})
|
||||
return ResponseMapper.create(item)
|
||||
})
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Prisma } from '../../generated/prisma/client'
|
||||
import { AddTransactionToBankAccountDto } from './dto/add-transaction.dto'
|
||||
|
||||
@Injectable()
|
||||
export class BankAccountsWorkflow {
|
||||
async addTransaction(
|
||||
tx: Prisma.TransactionClient,
|
||||
payload: AddTransactionToBankAccountDto,
|
||||
) {
|
||||
const item = await tx.bankAccountBalance.findUnique({
|
||||
where: {
|
||||
bankAccountId: payload.bankAccountId,
|
||||
},
|
||||
})
|
||||
|
||||
const balance = item ? Number(item.balance) : 0
|
||||
|
||||
const newBalance = item
|
||||
? payload.type === 'DEPOSIT'
|
||||
? balance + payload.amount
|
||||
: balance - payload.amount
|
||||
: payload.type === 'DEPOSIT'
|
||||
? payload.amount
|
||||
: -payload.amount
|
||||
|
||||
await tx.bankAccountTransaction.create({
|
||||
data: {
|
||||
bankAccount: { connect: { id: payload.bankAccountId } },
|
||||
amount: payload.amount,
|
||||
type: payload.type,
|
||||
balanceAfter: newBalance,
|
||||
|
||||
referenceId: payload.referenceId,
|
||||
referenceType: payload.referenceType,
|
||||
},
|
||||
})
|
||||
|
||||
console.log('first')
|
||||
|
||||
const bankAccountBalanceItem = await tx.bankAccountBalance.findUnique({
|
||||
where: {
|
||||
bankAccountId: payload.bankAccountId,
|
||||
},
|
||||
})
|
||||
|
||||
if (!bankAccountBalanceItem) {
|
||||
return await tx.bankAccountBalance.create({
|
||||
data: {
|
||||
bankAccount: { connect: { id: payload.bankAccountId } },
|
||||
balance: newBalance,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return await tx.bankAccountBalance.update({
|
||||
where: {
|
||||
bankAccountId: payload.bankAccountId,
|
||||
},
|
||||
data: {
|
||||
balance: newBalance,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { IsEnum, IsInt } from 'class-validator'
|
||||
import {
|
||||
BankAccountTransactionType,
|
||||
BankTransactionRefType,
|
||||
} from '../../../generated/prisma/enums'
|
||||
|
||||
export class AddTransactionToBankAccountDto {
|
||||
@IsInt()
|
||||
bankAccountId: number
|
||||
|
||||
@IsInt()
|
||||
amount: number
|
||||
|
||||
@IsInt()
|
||||
referenceId: number
|
||||
|
||||
@IsEnum(BankTransactionRefType)
|
||||
referenceType: BankTransactionRefType
|
||||
|
||||
@IsEnum(BankAccountTransactionType)
|
||||
type: BankAccountTransactionType
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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 {}
|
||||
+26
-12
@@ -1,12 +1,17 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from '../common/response/response-mapper'
|
||||
import { Prisma } from '../generated/prisma/client'
|
||||
import { PrismaService } from '../prisma/prisma.service'
|
||||
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||
import { Prisma } from '../../../generated/prisma/client'
|
||||
import { PrismaService } from '../../../prisma/prisma.service'
|
||||
import { CreatePurchaseReceiptDto } from './dto/create-purchase-receipt.dto'
|
||||
import { PurchaseReceiptWorkflow } from './purchase-receipts.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class PurchaseReceiptsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private purchaseReceiptWorkflow: PurchaseReceiptWorkflow,
|
||||
) {}
|
||||
|
||||
async create(dto: CreatePurchaseReceiptDto) {
|
||||
const data: Prisma.PurchaseReceiptCreateInput = {
|
||||
@@ -31,15 +36,24 @@ export class PurchaseReceiptsService {
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
const item = await this.prisma.purchaseReceipt.create({
|
||||
data,
|
||||
include: { items: true },
|
||||
omit: {
|
||||
supplierId: true,
|
||||
inventoryId: true,
|
||||
},
|
||||
|
||||
return withTransaction(this.prisma, async tx => {
|
||||
const item = await tx.purchaseReceipt.create({
|
||||
data,
|
||||
include: { items: true },
|
||||
omit: {
|
||||
supplierId: true,
|
||||
inventoryId: true,
|
||||
},
|
||||
})
|
||||
await this.purchaseReceiptWorkflow.onCreatePurchaseReceipt(
|
||||
tx,
|
||||
dto.supplierId,
|
||||
dto.totalAmount,
|
||||
item.id,
|
||||
)
|
||||
return ResponseMapper.create(item)
|
||||
})
|
||||
return ResponseMapper.create(item)
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Prisma } from '../../../generated/prisma/client'
|
||||
import { SupplierLedgerWorkflow } from '../../suppliers/ledger/supplier-ledger.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class PurchaseReceiptWorkflow {
|
||||
constructor(private supplierLedgerWorkflow: SupplierLedgerWorkflow) {}
|
||||
|
||||
async onCreatePurchaseReceipt(
|
||||
tx: Prisma.TransactionClient,
|
||||
supplierId: number,
|
||||
amount: number,
|
||||
sourceId: number,
|
||||
) {
|
||||
await this.supplierLedgerWorkflow.updateLedgerBalance(
|
||||
tx,
|
||||
supplierId,
|
||||
amount,
|
||||
sourceId,
|
||||
'PURCHASE',
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../prisma/prisma.module'
|
||||
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||
import { PurchaseReceiptItemsController } from './purchase-receipt-items.controller'
|
||||
import { PurchaseReceiptItemsService } from './purchase-receipt-items.service'
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from '../common/response/response-mapper'
|
||||
import { PrismaService } from '../prisma/prisma.service'
|
||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../../prisma/prisma.service'
|
||||
import { CreatePurchaseReceiptItemDto } from './dto/create-purchase-receipt-item.dto'
|
||||
|
||||
@Injectable()
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { IsEnum, IsInt, IsNumber, IsOptional, IsString } from 'class-validator'
|
||||
import { PaymentMethodType, PaymentType } from '../../../generated/prisma/enums'
|
||||
import { PaymentMethodType, PaymentType } from '../../../../generated/prisma/enums'
|
||||
|
||||
export class CreatePurchaseReceiptPaymentDto {
|
||||
@IsNumber()
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
|
||||
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||
import { BankAccountsModule } from '../../bank-accounts/bank-accounts.module'
|
||||
import { PurchaseReceiptPaymentsController } from './purchase-receipt-payments.controller'
|
||||
import { PurchaseReceiptPaymentsService } from './purchase-receipt-payments.service'
|
||||
import { PurchaseReceiptPaymentsWorkflow } from './purchase-receipt-payments.workflow'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, BankAccountsModule],
|
||||
controllers: [PurchaseReceiptPaymentsController],
|
||||
providers: [PurchaseReceiptPaymentsService, PurchaseReceiptPaymentsWorkflow],
|
||||
exports: [PurchaseReceiptPaymentsWorkflow],
|
||||
})
|
||||
export class PurchaseReceiptPaymentsModule {}
|
||||
+21
-6
@@ -1,14 +1,29 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../prisma/prisma.service'
|
||||
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../../prisma/prisma.service'
|
||||
import { CreatePurchaseReceiptPaymentDto } from './dto/create-purchase-receipt-payment.dto'
|
||||
import { PurchaseReceiptPaymentsWorkflow } from './purchase-receipt-payments.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class PurchaseReceiptPaymentsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private purchaseReceiptPaymentsWorkflow: PurchaseReceiptPaymentsWorkflow,
|
||||
) {}
|
||||
|
||||
async create(data: any) {
|
||||
const item = await this.prisma.purchaseReceiptPayments.create({ data })
|
||||
return ResponseMapper.create(item)
|
||||
async create(data: CreatePurchaseReceiptPaymentDto) {
|
||||
return withTransaction(this.prisma, async tx => {
|
||||
const item = await tx.purchaseReceiptPayments.create({ data })
|
||||
await this.purchaseReceiptPaymentsWorkflow.onAddPayment(
|
||||
tx,
|
||||
data.bankAccountId,
|
||||
data.receiptId,
|
||||
data.amount,
|
||||
data.type,
|
||||
)
|
||||
return ResponseMapper.create(item)
|
||||
})
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Prisma } from '../../../generated/prisma/client'
|
||||
import { PaymentType } from '../../../generated/prisma/enums'
|
||||
import { BankAccountsWorkflow } from '../../bank-accounts/bank-accounts.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class PurchaseReceiptPaymentsWorkflow {
|
||||
constructor(private bankAccountsWorkflow: BankAccountsWorkflow) {}
|
||||
|
||||
async onAddPayment(
|
||||
tx: Prisma.TransactionClient,
|
||||
bankAccountId: number,
|
||||
receiptId: number,
|
||||
amount: number,
|
||||
type: PaymentType,
|
||||
) {
|
||||
const { paidAmount, totalAmount } = await tx.purchaseReceipt.findUniqueOrThrow({
|
||||
where: { id: receiptId },
|
||||
})
|
||||
|
||||
if (type === 'PAYMENT' && Number(paidAmount) + Number(amount) > Number(totalAmount)) {
|
||||
throw new Error('مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.')
|
||||
}
|
||||
|
||||
if (type === 'REFUND' && Number(paidAmount) - Number(amount) < 0) {
|
||||
throw new Error(
|
||||
'مجموع مبلغ بازپرداختی بیشتر از مبلغ پرداخت شده در این فاکتور است.',
|
||||
)
|
||||
}
|
||||
|
||||
await this.bankAccountsWorkflow.addTransaction(tx, {
|
||||
bankAccountId: bankAccountId,
|
||||
amount: amount,
|
||||
type: type === 'PAYMENT' ? 'WITHDRAWAL' : 'DEPOSIT',
|
||||
referenceId: receiptId,
|
||||
referenceType: type === 'PAYMENT' ? 'PURCHASE_PAYMENT' : 'PURCHASE_REFUND',
|
||||
})
|
||||
|
||||
const newPaidAmount =
|
||||
type === 'PAYMENT'
|
||||
? Number(paidAmount) + Number(amount)
|
||||
: Number(paidAmount) - Number(amount)
|
||||
const newStatus =
|
||||
newPaidAmount === 0
|
||||
? 'UNPAID'
|
||||
: newPaidAmount >= Number(totalAmount)
|
||||
? 'PAID'
|
||||
: 'PARTIALLY_PAID'
|
||||
|
||||
await tx.purchaseReceipt.update({
|
||||
where: { id: receiptId },
|
||||
data: {
|
||||
paidAmount: newPaidAmount,
|
||||
status: newStatus,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../../prisma/prisma.module'
|
||||
import { SupplierLedgerModule } from '../suppliers/ledger/supplier-ledger.module'
|
||||
import { PurchaseReceiptsController } from './index/purchase-receipts.controller'
|
||||
import { PurchaseReceiptsService } from './index/purchase-receipts.service'
|
||||
import { PurchaseReceiptWorkflow } from './index/purchase-receipts.workflow'
|
||||
import { PurchaseReceiptItemsModule } from './purchase-receipt-items/purchase-receipt-items.module'
|
||||
import { PurchaseReceiptPaymentsModule } from './purchase-receipt-payments/purchase-receipt-payments.module'
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
PurchaseReceiptItemsModule,
|
||||
PurchaseReceiptPaymentsModule,
|
||||
SupplierLedgerModule,
|
||||
],
|
||||
controllers: [PurchaseReceiptsController],
|
||||
providers: [PurchaseReceiptsService, PurchaseReceiptWorkflow],
|
||||
exports: [PurchaseReceiptWorkflow],
|
||||
})
|
||||
export class PurchaseReceiptsModule {}
|
||||
@@ -22,11 +22,6 @@ export class SuppliersController {
|
||||
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)
|
||||
|
||||
@@ -37,21 +37,6 @@ export class SuppliersService {
|
||||
})
|
||||
}
|
||||
|
||||
async getLedger(supplierId: number) {
|
||||
const items = await this.prisma.supplierLedger.findMany({
|
||||
where: {
|
||||
supplierId,
|
||||
},
|
||||
omit: {
|
||||
supplierId: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
})
|
||||
return ResponseMapper.list(items)
|
||||
}
|
||||
|
||||
async update(id: number, data: any) {
|
||||
const item = await this.prisma.supplier.update({ where: { id }, data })
|
||||
return ResponseMapper.update(item)
|
||||
|
||||
@@ -21,10 +21,15 @@ export class SupplierInvoicesController {
|
||||
|
||||
@Post(':invoiceId/pay')
|
||||
createPayment(
|
||||
@Param('supplierId') supplierId: string,
|
||||
@Param('invoiceId') invoiceId: string,
|
||||
@Body() data: CreateReceiptPaymentDto,
|
||||
) {
|
||||
return this.supplierInvoicesService.createPayment(Number(invoiceId), data)
|
||||
return this.supplierInvoicesService.createPayment(
|
||||
Number(supplierId),
|
||||
Number(invoiceId),
|
||||
data,
|
||||
)
|
||||
}
|
||||
|
||||
@Get(':invoiceId/payments')
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||
import { PurchaseReceiptPaymentsModule } from '../../purchase-receipts/purchase-receipt-payments/purchase-receipt-payments.module'
|
||||
import { SupplierLedgerModule } from '../ledger/supplier-ledger.module'
|
||||
import { SupplierInvoicesController } from './invoices.controller'
|
||||
import { SupplierInvoicesService } from './invoices.service'
|
||||
import { SupplierInvoicesWorkflow } from './invoices.workflow'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
imports: [PrismaModule, PurchaseReceiptPaymentsModule, SupplierLedgerModule],
|
||||
controllers: [SupplierInvoicesController],
|
||||
providers: [SupplierInvoicesService],
|
||||
providers: [SupplierInvoicesService, SupplierInvoicesWorkflow],
|
||||
})
|
||||
export class SupplierInvoicesModule {}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { withTransaction } from '../../../common/database/transaction.helper'
|
||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../../prisma/prisma.service'
|
||||
import { CreateReceiptPaymentDto } from './dto/create-receipt-payment.dto'
|
||||
import { SupplierInvoicesWorkflow } from './invoices.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class SupplierInvoicesService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private supplierInvoicesWorkflow: SupplierInvoicesWorkflow,
|
||||
) {}
|
||||
|
||||
async findAll(supplierId: number) {
|
||||
const items = await this.prisma.purchaseReceipt.findMany({
|
||||
@@ -147,32 +152,45 @@ export class SupplierInvoicesService {
|
||||
return ResponseMapper.list(items)
|
||||
}
|
||||
|
||||
async createPayment(invoiceId: number, data: CreateReceiptPaymentDto) {
|
||||
async createPayment(
|
||||
supplierId: number,
|
||||
invoiceId: number,
|
||||
data: CreateReceiptPaymentDto,
|
||||
) {
|
||||
const { bankAccountId, ...rest } = data
|
||||
console.log(data)
|
||||
|
||||
const payment = await this.prisma.purchaseReceiptPayments.create({
|
||||
data: {
|
||||
...rest,
|
||||
payedAt: new Date(data.payedAt),
|
||||
receipt: {
|
||||
connect: {
|
||||
id: invoiceId,
|
||||
return withTransaction(this.prisma, async tx => {
|
||||
await this.supplierInvoicesWorkflow.onPaymentCreated(
|
||||
tx,
|
||||
supplierId,
|
||||
data.amount,
|
||||
invoiceId,
|
||||
bankAccountId,
|
||||
)
|
||||
|
||||
const payment = await tx.purchaseReceiptPayments.create({
|
||||
data: {
|
||||
...rest,
|
||||
payedAt: new Date(data.payedAt),
|
||||
receipt: {
|
||||
connect: {
|
||||
id: invoiceId,
|
||||
},
|
||||
},
|
||||
bankAccount: {
|
||||
connect: {
|
||||
id: bankAccountId,
|
||||
},
|
||||
},
|
||||
},
|
||||
bankAccount: {
|
||||
connect: {
|
||||
id: bankAccountId,
|
||||
},
|
||||
include: {
|
||||
receipt: true,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
receipt: true,
|
||||
},
|
||||
omit: {
|
||||
receiptId: true,
|
||||
},
|
||||
omit: {
|
||||
receiptId: true,
|
||||
},
|
||||
})
|
||||
return ResponseMapper.create(payment)
|
||||
})
|
||||
return ResponseMapper.create(payment)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Prisma } from '../../../generated/prisma/client'
|
||||
import { PurchaseReceiptPaymentsWorkflow } from '../../purchase-receipts/purchase-receipt-payments/purchase-receipt-payments.workflow'
|
||||
import { SupplierLedgerWorkflow } from '../ledger/supplier-ledger.workflow'
|
||||
|
||||
@Injectable()
|
||||
export class SupplierInvoicesWorkflow {
|
||||
constructor(
|
||||
private supplierLedgerWorkflow: SupplierLedgerWorkflow,
|
||||
private purchaseReceiptPaymentWorkflow: PurchaseReceiptPaymentsWorkflow,
|
||||
) {}
|
||||
|
||||
async onPaymentCreated(
|
||||
tx: Prisma.TransactionClient,
|
||||
supplierId: number,
|
||||
amount: number,
|
||||
invoiceId: number,
|
||||
bankAccountId: number,
|
||||
) {
|
||||
await this.supplierLedgerWorkflow.updateLedgerBalance(
|
||||
tx,
|
||||
supplierId,
|
||||
amount,
|
||||
invoiceId,
|
||||
'PAYMENT',
|
||||
)
|
||||
|
||||
await this.purchaseReceiptPaymentWorkflow.onAddPayment(
|
||||
tx,
|
||||
bankAccountId,
|
||||
invoiceId,
|
||||
amount,
|
||||
'PAYMENT',
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Controller, Get, Param } from '@nestjs/common'
|
||||
import { SupplierLedgerService } from './supplier-ledger.service'
|
||||
|
||||
@Controller('suppliers/:supplierId/ledger')
|
||||
export class SupplierLedgerController {
|
||||
constructor(private readonly supplierLedgerService: SupplierLedgerService) {}
|
||||
|
||||
@Get('')
|
||||
getLedger(@Param('supplierId') supplierId: string) {
|
||||
return this.supplierLedgerService.findAll(Number(supplierId))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../../../prisma/prisma.module'
|
||||
import { SupplierLedgerController } from './supplier-ledger.controller'
|
||||
import { SupplierLedgerService } from './supplier-ledger.service'
|
||||
import { SupplierLedgerWorkflow } from './supplier-ledger.workflow'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [SupplierLedgerController],
|
||||
providers: [SupplierLedgerService, SupplierLedgerWorkflow],
|
||||
exports: [SupplierLedgerWorkflow],
|
||||
})
|
||||
export class SupplierLedgerModule {}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from '../../../common/response/response-mapper'
|
||||
import { PrismaService } from '../../../prisma/prisma.service'
|
||||
|
||||
@Injectable()
|
||||
export class SupplierLedgerService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async findAll(supplierId: number) {
|
||||
const items = await this.prisma.supplierLedger.findMany({
|
||||
where: {
|
||||
supplierId,
|
||||
},
|
||||
omit: {
|
||||
supplierId: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
})
|
||||
return ResponseMapper.list(items)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { Prisma } from '../../../generated/prisma/client'
|
||||
import { LedgerSourceType } from '../../../generated/prisma/enums'
|
||||
|
||||
@Injectable()
|
||||
export class SupplierLedgerWorkflow {
|
||||
async updateLedgerBalance(
|
||||
tx: Prisma.TransactionClient,
|
||||
supplierId: number,
|
||||
amount: number,
|
||||
sourceId: number,
|
||||
sourceType: LedgerSourceType,
|
||||
) {
|
||||
const lastSupplierLedgerBalance = await tx.supplierLedger
|
||||
.findFirstOrThrow({
|
||||
where: { supplierId },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
})
|
||||
.then(sl => (sl ? sl.balance : 0))
|
||||
|
||||
let newBalance = Number(lastSupplierLedgerBalance)
|
||||
let credit = 0
|
||||
let debit = 0
|
||||
let description = ''
|
||||
|
||||
switch (sourceType) {
|
||||
case 'PURCHASE':
|
||||
newBalance += amount
|
||||
credit = amount
|
||||
description = `خرید به مبلغ ${amount} بابت خرید شماره ${sourceId}`
|
||||
break
|
||||
case 'REFUND':
|
||||
case 'PAYMENT':
|
||||
newBalance -= amount
|
||||
debit = amount
|
||||
description = `پرداخت به مبلغ ${amount} بابت پرداخت شماره ${sourceId}`
|
||||
break
|
||||
case 'ADJUSTMENT':
|
||||
newBalance = amount
|
||||
description = `اصلاح حساب به مبلغ ${amount} بابت پرداخت شماره ${sourceId}`
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
return await tx.supplierLedger.create({
|
||||
data: {
|
||||
supplierId,
|
||||
debit,
|
||||
credit,
|
||||
balance: newBalance,
|
||||
sourceId,
|
||||
sourceType,
|
||||
description,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,10 @@ import { PrismaModule } from '../../prisma/prisma.module'
|
||||
import { SuppliersController } from './index/suppliers.controller'
|
||||
import { SuppliersService } from './index/suppliers.service'
|
||||
import { SupplierInvoicesModule } from './invoices/invoices.module'
|
||||
import { SupplierLedgerModule } from './ledger/supplier-ledger.module'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, SupplierInvoicesModule],
|
||||
imports: [PrismaModule, SupplierInvoicesModule, SupplierLedgerModule],
|
||||
controllers: [SuppliersController],
|
||||
providers: [SuppliersService],
|
||||
})
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PrismaModule } from '../prisma/prisma.module'
|
||||
import { PurchaseReceiptsController } from './purchase-receipts.controller'
|
||||
import { PurchaseReceiptsService } from './purchase-receipts.service'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [PurchaseReceiptsController],
|
||||
providers: [PurchaseReceiptsService],
|
||||
})
|
||||
export class PurchaseReceiptsModule {}
|
||||
Reference in New Issue
Block a user