feat: 重构各业务模块管理页面与服务
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DataSource, EntityManager, Repository } from 'typeorm';
|
||||
import { DataSource, EntityManager, Repository, In } from 'typeorm';
|
||||
import { Bill } from '../entities/bill.entity';
|
||||
import { Student } from '../entities/student.entity';
|
||||
import { StudentWallet } from '../entities/student-wallet.entity';
|
||||
import { WalletTransaction } from '../entities/wallet-transaction.entity';
|
||||
import { In } from 'typeorm';
|
||||
import { BatchChangeWalletBalanceDto, ChangeWalletBalanceDto } from './dto/wallet.dto';
|
||||
import { FinancialOperationsService } from '../financial-operations/financial-operations.service';
|
||||
import { Room } from '../entities/room.entity';
|
||||
@@ -58,7 +57,8 @@ export class WalletsService {
|
||||
|
||||
const ids = rows.map((row) => Number(row.studentId));
|
||||
const wallets = await this.walletRepo.find({ where: { studentId: In(ids) } });
|
||||
const bills = await this.dataSource.getRepository(Bill)
|
||||
const bills = await this.dataSource
|
||||
.getRepository(Bill)
|
||||
.createQueryBuilder('bill')
|
||||
.select('bill.studentId', 'studentId')
|
||||
.addSelect('SUM(bill.outstandingAmount)', 'outstandingAmount')
|
||||
@@ -67,7 +67,9 @@ export class WalletsService {
|
||||
.groupBy('bill.studentId')
|
||||
.getRawMany<{ studentId: number; outstandingAmount: string }>();
|
||||
const walletMap = new Map(wallets.map((wallet) => [wallet.studentId, wallet]));
|
||||
const debtMap = new Map(bills.map((bill) => [Number(bill.studentId), money(bill.outstandingAmount)]));
|
||||
const debtMap = new Map(
|
||||
bills.map((bill) => [Number(bill.studentId), money(bill.outstandingAmount)]),
|
||||
);
|
||||
return rows
|
||||
.map((row) => ({
|
||||
studentId: Number(row.studentId),
|
||||
@@ -103,7 +105,9 @@ export class WalletsService {
|
||||
async changeBalance(dto: ChangeWalletBalanceDto, recordedBy?: number) {
|
||||
const { operationId, ...change } = dto;
|
||||
return this.financialOperations
|
||||
? this.financialOperations.run(operationId, 'wallet.change_balance', () => this.changeBalanceOnce(change, recordedBy, operationId))
|
||||
? this.financialOperations.run(operationId, 'wallet.change_balance', () =>
|
||||
this.changeBalanceOnce(change, recordedBy, operationId),
|
||||
)
|
||||
: this.changeBalanceOnce(change, recordedBy, operationId);
|
||||
}
|
||||
|
||||
@@ -114,7 +118,10 @@ export class WalletsService {
|
||||
transactionManager?: EntityManager,
|
||||
) {
|
||||
const amount = money(dto.amount);
|
||||
if (!Number.isFinite(dto.amount) || Math.abs(dto.amount * 100 - Math.round(dto.amount * 100)) > 1e-8) {
|
||||
if (
|
||||
!Number.isFinite(dto.amount) ||
|
||||
Math.abs(dto.amount * 100 - Math.round(dto.amount * 100)) > 1e-8
|
||||
) {
|
||||
throw new BadRequestException('调账金额最多保留两位小数');
|
||||
}
|
||||
if (amount === 0) throw new BadRequestException('调账金额不能为 0');
|
||||
@@ -139,8 +146,11 @@ export class WalletsService {
|
||||
recordedBy: recordedBy || null,
|
||||
}),
|
||||
);
|
||||
const payments = amount > 0 ? await this.settleOutstandingBills(manager, dto.studentId, recordedBy) : [];
|
||||
const finalWallet = await manager.findOneByOrFail(StudentWallet, { studentId: dto.studentId });
|
||||
const payments =
|
||||
amount > 0 ? await this.settleOutstandingBills(manager, dto.studentId, recordedBy) : [];
|
||||
const finalWallet = await manager.findOneByOrFail(StudentWallet, {
|
||||
studentId: dto.studentId,
|
||||
});
|
||||
return { wallet: finalWallet, payments };
|
||||
};
|
||||
return transactionManager ? work(transactionManager) : this.dataSource.transaction(work);
|
||||
@@ -148,19 +158,27 @@ export class WalletsService {
|
||||
|
||||
async batchChangeBalance(dto: BatchChangeWalletBalanceDto, recordedBy?: number) {
|
||||
const { operationId, ...batch } = dto;
|
||||
const work = () => this.dataSource.transaction(async (manager) => {
|
||||
const uniqueStudentIds = Array.from(new Set(batch.studentIds));
|
||||
const results: Array<{ wallet: StudentWallet; payments: Bill[] }> = [];
|
||||
for (const studentId of uniqueStudentIds) {
|
||||
results.push(await this.changeBalanceOnce({
|
||||
studentId,
|
||||
amount: batch.amount,
|
||||
type: batch.type,
|
||||
description: batch.description,
|
||||
}, recordedBy, operationId ? `${operationId}:${studentId}` : undefined, manager));
|
||||
}
|
||||
return { count: uniqueStudentIds.length, results };
|
||||
});
|
||||
const work = () =>
|
||||
this.dataSource.transaction(async (manager) => {
|
||||
const uniqueStudentIds = Array.from(new Set(batch.studentIds));
|
||||
const results: Array<{ wallet: StudentWallet; payments: Bill[] }> = [];
|
||||
for (const studentId of uniqueStudentIds) {
|
||||
results.push(
|
||||
await this.changeBalanceOnce(
|
||||
{
|
||||
studentId,
|
||||
amount: batch.amount,
|
||||
type: batch.type,
|
||||
description: batch.description,
|
||||
},
|
||||
recordedBy,
|
||||
operationId ? `${operationId}:${studentId}` : undefined,
|
||||
manager,
|
||||
),
|
||||
);
|
||||
}
|
||||
return { count: uniqueStudentIds.length, results };
|
||||
});
|
||||
return this.financialOperations
|
||||
? this.financialOperations.run(operationId, 'wallet.batch_change_balance', work)
|
||||
: work();
|
||||
@@ -236,7 +254,11 @@ export class WalletsService {
|
||||
return manager.save(bill);
|
||||
}
|
||||
|
||||
private async settleOutstandingBills(manager: EntityManager, studentId: number, recordedBy?: number) {
|
||||
private async settleOutstandingBills(
|
||||
manager: EntityManager,
|
||||
studentId: number,
|
||||
recordedBy?: number,
|
||||
) {
|
||||
const bills = await manager
|
||||
.createQueryBuilder(Bill, 'bill')
|
||||
.where('bill.studentId = :studentId', { studentId })
|
||||
|
||||
Reference in New Issue
Block a user