feat(bank-accounts): add transaction retrieval and update service logic
- Implemented a new endpoint to fetch transactions for a specific bank account. - Refactored the bank account service to streamline transaction handling and balance calculations. - Removed the bank account balance table and adjusted related logic in workflows and services. - Enhanced transaction mapping to include references to sales and purchase records.
This commit is contained in:
@@ -31,4 +31,9 @@ export class BankAccountsController {
|
||||
remove(@Param('id') id: string) {
|
||||
return this.bankAccountsService.remove(Number(id))
|
||||
}
|
||||
|
||||
@Get(':id/transactions')
|
||||
getTransactions(@Param('id') id: string) {
|
||||
return this.bankAccountsService.getTransactions(Number(id))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,61 @@
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { withTransaction } from '../../common/database/transaction.helper'
|
||||
import { ResponseMapper } from '../../common/response/response-mapper'
|
||||
import { BankTransactionRefType } from '../../generated/prisma/enums'
|
||||
import { PrismaService } from '../../prisma/prisma.service'
|
||||
|
||||
@Injectable()
|
||||
export class BankAccountsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
async create(data: any) {
|
||||
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() {
|
||||
const items = await this.prisma.bankAccount.findMany({
|
||||
include: {
|
||||
branch: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
code: true,
|
||||
bank: {
|
||||
select: { id: true, name: true, shortName: true },
|
||||
},
|
||||
private readonly bankAccountQuery = {
|
||||
include: {
|
||||
branch: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
code: true,
|
||||
bank: {
|
||||
select: { id: true, name: true, shortName: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
omit: {
|
||||
branchId: true,
|
||||
bankAccountTransactions: {
|
||||
take: 1,
|
||||
select: { id: true, createdAt: true, balanceAfter: true },
|
||||
orderBy: { createdAt: 'desc' as const },
|
||||
},
|
||||
})
|
||||
return ResponseMapper.list(items)
|
||||
},
|
||||
omit: {
|
||||
branchId: true,
|
||||
},
|
||||
}
|
||||
|
||||
async create(data: any) {
|
||||
const item = await this.prisma.bankAccount.create({ data })
|
||||
return ResponseMapper.create(item)
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
const items = await this.prisma.bankAccount.findMany(this.bankAccountQuery)
|
||||
const mappedData = items.map(({ bankAccountTransactions, ...rest }) => ({
|
||||
...rest,
|
||||
currentBalance: Number(bankAccountTransactions[0]?.balanceAfter || 0),
|
||||
}))
|
||||
|
||||
return ResponseMapper.list(mappedData)
|
||||
}
|
||||
|
||||
async findOne(id: number) {
|
||||
const item = await this.prisma.bankAccount.findUnique({ where: { id } })
|
||||
if (!item) return null
|
||||
return ResponseMapper.single(item)
|
||||
const item = await this.prisma.bankAccount.findUniqueOrThrow({
|
||||
...this.bankAccountQuery,
|
||||
where: { id },
|
||||
})
|
||||
|
||||
const { bankAccountTransactions, ...rest } = item
|
||||
return ResponseMapper.single({
|
||||
...rest,
|
||||
currentBalance: Number(bankAccountTransactions[0]?.balanceAfter || 0),
|
||||
})
|
||||
}
|
||||
|
||||
async update(id: number, data: any) {
|
||||
@@ -55,4 +67,87 @@ export class BankAccountsService {
|
||||
const item = await this.prisma.bankAccount.delete({ where: { id } })
|
||||
return ResponseMapper.single(item)
|
||||
}
|
||||
|
||||
async getTransactions(bankAccountId: number, page = 1, pageSize = 50) {
|
||||
const query = {
|
||||
where: { bankAccountId },
|
||||
orderBy: { createdAt: 'desc' as const },
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
}
|
||||
|
||||
const [items, count] = await this.prisma.$transaction([
|
||||
this.prisma.bankAccountTransaction.findMany({
|
||||
...query,
|
||||
omit: { bankAccountId: true },
|
||||
}),
|
||||
this.prisma.bankAccountTransaction.count({ where: { bankAccountId } }),
|
||||
])
|
||||
|
||||
const PosReferenceIds = [] as number[]
|
||||
const purchaseReferenceIds = [] as number[]
|
||||
|
||||
items.forEach(({ referenceType, referenceId }) => {
|
||||
if (referenceId && referenceType) {
|
||||
if (
|
||||
referenceType === BankTransactionRefType.POS_SALE ||
|
||||
referenceType === BankTransactionRefType.POS_REFUND
|
||||
) {
|
||||
PosReferenceIds.push(referenceId)
|
||||
} else if (
|
||||
referenceType === BankTransactionRefType.PURCHASE_PAYMENT ||
|
||||
referenceType === BankTransactionRefType.PURCHASE_REFUND
|
||||
) {
|
||||
purchaseReferenceIds.push(referenceId)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const posRecords = await this.prisma.salesInvoice.findMany({
|
||||
where: { id: { in: PosReferenceIds } },
|
||||
select: {
|
||||
id: true,
|
||||
code: true,
|
||||
totalAmount: true,
|
||||
posAccount: {
|
||||
select: { id: true, name: true },
|
||||
},
|
||||
customer: {
|
||||
select: { id: true, firstName: true, lastName: true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const purchaseRecords = await this.prisma.purchaseReceipt.findMany({
|
||||
where: { id: { in: purchaseReferenceIds } },
|
||||
select: {
|
||||
id: true,
|
||||
code: true,
|
||||
totalAmount: true,
|
||||
supplier: {
|
||||
select: { id: true, firstName: true, lastName: true },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const mappedItems = items.map(tx => {
|
||||
let reference = null as any
|
||||
if (tx.referenceId && tx.referenceType) {
|
||||
if (
|
||||
tx.referenceType === BankTransactionRefType.POS_SALE ||
|
||||
tx.referenceType === BankTransactionRefType.POS_REFUND
|
||||
) {
|
||||
reference = posRecords.find(r => r.id === tx.referenceId) || null
|
||||
} else if (
|
||||
tx.referenceType === BankTransactionRefType.PURCHASE_PAYMENT ||
|
||||
tx.referenceType === BankTransactionRefType.PURCHASE_REFUND
|
||||
) {
|
||||
reference = purchaseRecords.find(r => r.id === tx.referenceId) || null
|
||||
}
|
||||
}
|
||||
return { ...tx, reference }
|
||||
})
|
||||
|
||||
return ResponseMapper.paginate(mappedItems, count, page, pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ export class BankAccountsWorkflow {
|
||||
tx: Prisma.TransactionClient,
|
||||
payload: AddTransactionToBankAccountDto,
|
||||
) {
|
||||
const item = await tx.bankAccountBalance.findUnique({
|
||||
const item = await tx.bankAccountTransaction.findFirst({
|
||||
where: {
|
||||
bankAccountId: payload.bankAccountId,
|
||||
},
|
||||
})
|
||||
|
||||
const balance = item ? Number(item.balance) : 0
|
||||
const balance = item ? Number(item?.balanceAfter) : 0
|
||||
|
||||
const newBalance = item
|
||||
? payload.type === 'DEPOSIT'
|
||||
@@ -35,31 +35,5 @@ export class BankAccountsWorkflow {
|
||||
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,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ export class InventoriesService {
|
||||
},
|
||||
})
|
||||
let info = null as any
|
||||
console.log(movements)
|
||||
|
||||
const mapped = movements.map(movement => {
|
||||
const { id, quantity, unitPrice, totalCost, avgCost, product } = movement
|
||||
|
||||
Reference in New Issue
Block a user