feat: 迭代

This commit is contained in:
2026-05-19 16:23:01 +08:00
parent 848df4c873
commit 606895fdd5
47 changed files with 1758 additions and 377 deletions
@@ -21,11 +21,20 @@ export class MerchantAccount {
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计收入(订单结算)' })
total_income: number;
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计支出(提现)' })
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计支出(提现+退款扣回' })
total_expense: number;
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计服务费' })
total_service_fee: number;
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计结算金额' })
total_settlement: number;
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '累计提现金额' })
total_withdraw: number;
@Column({ type: 'datetime', nullable: true, comment: '最后结算时间' })
last_settlement_at: Date;
@Column({ type: 'decimal', precision: 12, scale: 2, default: 0, comment: '待结算金额' })
pending_settlement: number;
@VersionColumn({ comment: '乐观锁版本号' })
version: number;
@@ -30,7 +30,7 @@ export class CouponController {
@Post('receive')
@ApiOperation({ summary: '领取优惠券' })
async receive(@Body() dto: ReceiveCouponDto, @CurrentUser() user: any) {
return this.couponService.receive(user.id, dto.couponId);
return this.couponService.receive(user.sub, dto.couponId);
}
@Get('my')
@@ -78,9 +78,9 @@ export class QueryOrderDto {
}
export class PayOrderDto {
@IsNumber()
@Type(() => Number)
orderId: number;
@IsString()
@IsNotEmpty()
orderNo: string;
@IsEnum(['wechat', 'alipay', 'balance'])
paymentMethod: 'wechat' | 'alipay' | 'balance';
@@ -43,20 +43,20 @@ export class OrderController {
return this.orderService.findByUser(userId, query);
}
@Get(':id')
@Get(':orderNo')
@ApiOperation({ summary: '订单详情' })
async findById(@Param('id') id: number) {
return this.orderService.findById(id);
async findByOrderNo(@Param('orderNo') orderNo: string) {
return this.orderService.findByOrderNo(orderNo);
}
@Put(':id/cancel')
@Put(':orderNo/cancel')
@ApiOperation({ summary: '取消订单' })
async cancel(
@CurrentUser('sub') userId: number,
@Param('id') id: number,
@Param('orderNo') orderNo: string,
@Body('reason') reason: string,
) {
return this.orderService.cancel(userId, id, reason);
return this.orderService.cancelByOrderNo(userId, orderNo, reason);
}
@Post('pay')
@@ -65,16 +65,16 @@ export class OrderController {
@CurrentUser('sub') userId: number,
@Body() dto: PayOrderDto,
) {
return this.orderService.pay(userId, dto.orderId, dto.paymentMethod);
return this.orderService.payByOrderNo(userId, dto.orderNo, dto.paymentMethod);
}
@Put(':id/refund')
@Put(':orderNo/refund')
@ApiOperation({ summary: '申请退款' })
async refund(
@CurrentUser('sub') userId: number,
@Param('id') id: number,
@Param('orderNo') orderNo: string,
@Body('reason') reason: string,
) {
return this.orderService.refund(userId, id, reason);
return this.orderService.refundByOrderNo(userId, orderNo, reason);
}
}
@@ -80,13 +80,6 @@ export class OrderService {
const roomAmount = totalRoomPrice * roomCount;
// 计算平台服务费(基于房费)
const serviceFeeRate = await this.configService.getServiceFeeRate();
const serviceFee = Math.round(roomAmount * serviceFeeRate * 100) / 100;
// 订单总额 = 房费 + 服务费
const totalAmount = roomAmount + serviceFee;
// 处理优惠券
let couponDiscount = 0;
let userCouponId: number | null = null;
@@ -106,16 +99,22 @@ export class OrderService {
throw new BadRequestException('优惠券不可用');
}
// 计算优惠金额(优惠券只能抵扣房费部分,不能抵扣服务费)
// 计算优惠金额(基于房费)
couponDiscount = this.couponService.calculateDiscount(userCoupon.coupon, roomAmount);
userCouponId = userCoupon.id;
}
// 实付金额 = 订单总额 - 优惠券折扣
// 订单总额 = 房费
const totalAmount = roomAmount;
// 用户实付 = 房费 - 优惠券
const payAmount = totalAmount - couponDiscount;
// 商家收入 = 房费 - 优惠券折扣
const merchantIncome = Math.round((roomAmount - couponDiscount) * 100) / 100;
// 计算平台服务费(基于用户实付金额)
const serviceFeeRate = await this.configService.getServiceFeeRate();
const serviceFee = Math.round(payAmount * serviceFeeRate * 100) / 100;
// 商家收入 = 用户实付 - 服务费
const merchantIncome = Math.round((payAmount - serviceFee) * 100) / 100;
const now = new Date();
const orderNo = [
@@ -212,7 +211,19 @@ export class OrderService {
}
/**
* 用户查询订单详情
* 用户查询订单详情(通过订单号)
*/
async findByOrderNo(orderNo: string) {
const order = await this.orderRepo.findOne({
where: { orderNo },
relations: ['room', 'merchant', 'user'],
});
if (!order) throw new NotFoundException('订单不存在');
return order;
}
/**
* 用户查询订单详情(通过ID,保留用于内部调用)
*/
async findById(id: number) {
const order = await this.orderRepo.findOne({
@@ -224,7 +235,44 @@ export class OrderService {
}
/**
* 用户取消订单
* 用户取消订单(通过订单号)
*/
async cancelByOrderNo(userId: number, orderNo: string, reason: string) {
const order = await this.findByOrderNo(orderNo);
if (order.userId !== userId) throw new ForbiddenException('无权操作此订单');
if (!['pending_pay', 'pending_confirm', 'pending_checkin'].includes(order.status)) {
throw new BadRequestException('当前订单状态不可取消');
}
// 恢复房态库存(所有可取消的订单都需要恢复库存)
const checkIn = new Date(order.checkInDate);
const checkOut = new Date(order.checkOutDate);
for (let d = new Date(checkIn); d < checkOut; d.setDate(d.getDate() + 1)) {
const dateStr = d.toISOString().split('T')[0];
await this.calendarRepo.decrement(
{ roomId: order.roomId, date: dateStr },
'sold',
order.roomCount,
);
}
// 已支付的订单(pending_confirm、pending_checkin)取消时需退款
const needRefund = order.status !== 'pending_pay';
await this.orderRepo.update(order.id, {
status: 'cancelled',
cancelReason: reason,
cancelledAt: new Date(),
...(needRefund ? {
refundAmount: order.payAmount,
refundAt: new Date(),
} : {}),
});
return { message: needRefund ? '订单已取消,退款将原路返回' : '订单已取消' };
}
/**
* 用户取消订单(通过ID,保留用于内部调用)
*/
async cancel(userId: number, id: number, reason: string) {
const order = await this.findById(id);
@@ -261,7 +309,44 @@ export class OrderService {
}
/**
* 用户支付订单
* 用户支付订单(通过订单号)
*/
async payByOrderNo(userId: number, orderNo: string, paymentMethod: 'wechat' | 'alipay' | 'balance') {
const order = await this.findByOrderNo(orderNo);
if (order.userId !== userId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'pending_pay') {
throw new BadRequestException('当前订单状态不可支付');
}
// 模拟支付成功
const paymentNo = `PAY${Date.now()}${Math.floor(Math.random() * 10000)}`;
await this.orderRepo.update(order.id, {
status: 'pending_confirm',
paymentMethod,
paymentNo,
paidAt: new Date(),
});
// 扣减房态库存
const checkIn = new Date(order.checkInDate);
const checkOut = new Date(order.checkOutDate);
for (let d = new Date(checkIn); d < checkOut; d.setDate(d.getDate() + 1)) {
const dateStr = d.toISOString().split('T')[0];
const calendar = await this.calendarRepo.findOne({
where: { roomId: order.roomId, date: dateStr },
});
if (calendar) {
await this.calendarRepo.update(calendar.id, {
sold: calendar.sold + order.roomCount,
});
}
}
return { message: '支付成功', paymentNo };
}
/**
* 用户支付订单(通过ID,保留用于内部调用)
*/
async pay(userId: number, id: number, paymentMethod: 'wechat' | 'alipay' | 'balance') {
const order = await this.findById(id);
@@ -298,7 +383,42 @@ export class OrderService {
}
/**
* 用户申请退款(待确认、待入住状态)- 直接退款,无需审核
* 用户申请退款(通过订单号)
*/
async refundByOrderNo(userId: number, orderNo: string, reason: string) {
const order = await this.findByOrderNo(orderNo);
if (order.userId !== userId) throw new ForbiddenException('无权操作此订单');
if (!['pending_confirm', 'pending_checkin'].includes(order.status)) {
throw new BadRequestException('当前订单状态不可申请退款');
}
// 恢复房态库存
const checkIn = new Date(order.checkInDate);
const checkOut = new Date(order.checkOutDate);
for (let d = new Date(checkIn); d < checkOut; d.setDate(d.getDate() + 1)) {
const dateStr = d.toISOString().split('T')[0];
const calendar = await this.calendarRepo.findOne({
where: { roomId: order.roomId, date: dateStr },
});
if (calendar) {
await this.calendarRepo.update(calendar.id, {
sold: Math.max(0, calendar.sold - order.roomCount),
});
}
}
// 调用 RefundService 处理财务退款
try {
await this.refundService.processRefund(order, reason);
return { message: '退款成功,款项将原路返回' };
} catch (error) {
// 退款失败,恢复订单状态(库存已恢复,需要手动回滚)
throw new BadRequestException(`退款失败: ${error.message}`);
}
}
/**
* 用户申请退款(通过ID,保留用于内部调用)
*/
async refund(userId: number, id: number, reason: string) {
const order = await this.findById(id);
@@ -1,10 +1,10 @@
import { IsString, IsNumber, IsOptional, IsBoolean, IsArray, Min, Max } from 'class-validator';
import { IsString, IsNumber, IsOptional, IsBoolean, IsArray, Min, Max, IsNotEmpty } from 'class-validator';
import { Type } from 'class-transformer';
export class CreateReviewDto {
@IsNumber()
@Type(() => Number)
orderId: number;
@IsString()
@IsNotEmpty()
orderNo: string;
@IsNumber()
@Min(1)
@@ -25,7 +25,7 @@ export class ReviewController {
@Request() req,
@Body() dto: CreateReviewDto,
) {
return this.reviewService.create(req.user.sub, Number(dto.orderId), dto);
return this.reviewService.createByOrderNo(req.user.sub, dto.orderNo, dto);
}
// 查询评价列表(公开)
@@ -35,9 +35,9 @@ export class ReviewController {
}
// 检查订单是否已评价
@Get('check/:orderId')
async checkOrder(@Param('orderId') orderId: number) {
const review = await this.reviewService.findByOrder(Number(orderId));
@Get('check/:orderNo')
async checkOrder(@Param('orderNo') orderNo: string) {
const review = await this.reviewService.findByOrderNo(orderNo);
return { reviewed: !!review, review };
}
}
@@ -20,7 +20,38 @@ export class ReviewService {
) {}
/**
* 用户提交评价
* 用户提交评价(通过订单号)
*/
async createByOrderNo(userId: number, orderNo: string, dto: CreateReviewDto) {
const order = await this.orderRepo.findOne({ where: { orderNo } });
if (!order) throw new NotFoundException('订单不存在');
if (order.userId !== userId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'completed') throw new BadRequestException('只有已完成的订单才能评价');
// 检查是否已评价
const existing = await this.reviewRepo.findOne({ where: { orderId: order.id } });
if (existing) throw new BadRequestException('该订单已评价');
if (dto.rating < 1 || dto.rating > 5) throw new BadRequestException('评分范围为1-5');
const review = this.reviewRepo.create({
orderId: order.id,
userId,
merchantId: order.merchantId,
roomId: order.roomId,
rating: dto.rating,
content: dto.content,
images: dto.images,
isAnonymous: dto.isAnonymous || false,
status: 'pending',
});
await this.reviewRepo.save(review);
return { message: '评价已提交' };
}
/**
* 用户提交评价(通过订单ID,保留用于内部调用)
*/
async create(userId: number, orderId: number, dto: CreateReviewDto) {
const order = await this.orderRepo.findOne({ where: { id: orderId } });
@@ -77,7 +108,16 @@ export class ReviewService {
}
/**
* 检查订单是否已评价
* 检查订单是否已评价(通过订单号)
*/
async findByOrderNo(orderNo: string) {
const order = await this.orderRepo.findOne({ where: { orderNo } });
if (!order) return null;
return this.reviewRepo.findOne({ where: { orderId: order.id } });
}
/**
* 检查订单是否已评价(通过订单ID)
*/
async findByOrder(orderId: number) {
return this.reviewRepo.findOne({ where: { orderId } });
@@ -180,4 +180,12 @@ export class QueryMerchantDto {
@IsOptional()
@IsString()
city?: string;
@IsOptional()
@IsString()
checkInDate?: string;
@IsOptional()
@IsString()
checkOutDate?: string;
}
@@ -1,17 +1,29 @@
import { Module } from '@nestjs/common';
import { Module, forwardRef } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MerchantFinanceController } from './finance.controller';
import { MerchantFinanceService } from './finance.service';
import { SettlementMerchantController } from './settlement-merchant.controller';
import { WithdrawalMerchantController } from './withdrawal-merchant.controller';
import { TransactionSellerController } from './transaction-seller.controller';
import { MerchantAccount } from '@/entities/merchant-account.entity';
import { MerchantTransaction } from '@/entities/merchant-transaction.entity';
import { MerchantProfileModule } from '../profile/profile.module';
import { MerchantModule } from '../merchant.module';
import { FinanceModule } from '@/modules/shared/finance/finance.module';
@Module({
imports: [
TypeOrmModule.forFeature([MerchantAccount, MerchantTransaction]),
MerchantProfileModule,
forwardRef(() => MerchantModule),
forwardRef(() => FinanceModule),
],
controllers: [
MerchantFinanceController,
SettlementMerchantController,
WithdrawalMerchantController,
TransactionSellerController,
],
controllers: [MerchantFinanceController],
providers: [MerchantFinanceService],
exports: [MerchantFinanceService],
})
@@ -14,7 +14,26 @@ export class MerchantFinanceService {
) {}
async getMerchantAccount(merchantId: number) {
return this.merchantAccountRepo.findOne({ where: { merchant_id: merchantId } });
let account = await this.merchantAccountRepo.findOne({ where: { merchant_id: merchantId } });
// 如果账户不存在,自动创建
if (!account) {
account = this.merchantAccountRepo.create({
merchant_id: merchantId,
balance: 0,
frozen_balance: 0,
debt_amount: 0,
total_income: 0,
total_expense: 0,
total_settlement: 0,
total_withdraw: 0,
pending_settlement: 0,
status: 'active',
});
await this.merchantAccountRepo.save(account);
}
return account;
}
async getMerchantTransactions(params: {
@@ -43,11 +62,11 @@ export class MerchantFinanceService {
const queryBuilder = this.merchantTransactionRepo.createQueryBuilder('t');
if (merchantId !== undefined) {
queryBuilder.andWhere('t.merchantId = :merchantId', { merchantId });
queryBuilder.andWhere('t.merchant_id = :merchantId', { merchantId });
}
if (accountId) {
queryBuilder.andWhere('t.accountId = :accountId', { accountId });
queryBuilder.andWhere('t.account_id = :accountId', { accountId });
}
if (direction) {
@@ -55,21 +74,21 @@ export class MerchantFinanceService {
}
if (transactionType) {
queryBuilder.andWhere('t.transactionType = :transactionType', { transactionType });
queryBuilder.andWhere('t.transaction_type = :transactionType', { transactionType });
}
if (businessType) {
queryBuilder.andWhere('t.businessType = :businessType', { businessType });
queryBuilder.andWhere('t.business_type = :businessType', { businessType });
}
if (startDate && endDate) {
queryBuilder.andWhere('t.createdAt BETWEEN :startDate AND :endDate', {
queryBuilder.andWhere('t.created_at BETWEEN :startDate AND :endDate', {
startDate: `${startDate} 00:00:00`,
endDate: `${endDate} 23:59:59`
});
}
queryBuilder.orderBy('t.createdAt', 'DESC');
queryBuilder.orderBy('t.created_at', 'DESC');
const skip = (page - 1) * pageSize;
queryBuilder.skip(skip).take(pageSize);
@@ -111,11 +130,11 @@ export class MerchantFinanceService {
queryBuilder.select('SUM(t.amount)', 'total');
if (merchantId !== undefined) {
queryBuilder.andWhere('t.merchantId = :merchantId', { merchantId });
queryBuilder.andWhere('t.merchant_id = :merchantId', { merchantId });
}
if (accountId) {
queryBuilder.andWhere('t.accountId = :accountId', { accountId });
queryBuilder.andWhere('t.account_id = :accountId', { accountId });
}
if (direction) {
@@ -123,11 +142,11 @@ export class MerchantFinanceService {
}
if (transactionType) {
queryBuilder.andWhere('t.transactionType = :transactionType', { transactionType });
queryBuilder.andWhere('t.transaction_type = :transactionType', { transactionType });
}
if (startDate && endDate) {
queryBuilder.andWhere('t.createdAt BETWEEN :startDate AND :endDate', {
queryBuilder.andWhere('t.created_at BETWEEN :startDate AND :endDate', {
startDate: `${startDate} 00:00:00`,
endDate: `${endDate} 23:59:59`
});
@@ -9,7 +9,6 @@ import { MerchantService } from './merchant.service';
import { StatisticsService } from './statistics.service';
import { MerchantSellerController } from './merchant-seller.controller';
import { MerchantAdminController } from './merchant-admin.controller';
import { StatisticsSellerController } from './statistics-seller.controller';
import { MerchantAuthModule } from './auth/auth.module';
import { MerchantProfileModule } from './profile/profile.module';
import { MerchantRoomModule } from './room/room.module';
@@ -34,7 +33,6 @@ import { MerchantStatisticsModule } from './statistics/statistics.module';
controllers: [
MerchantSellerController,
MerchantAdminController,
StatisticsSellerController,
],
providers: [MerchantService, StatisticsService],
exports: [MerchantService, StatisticsService],
@@ -67,7 +67,7 @@ export class MerchantService {
}
async findPublic(query: QueryMerchantDto) {
const { page = 1, pageSize = 10, keyword, city } = query;
const { page = 1, pageSize = 10, keyword, city, checkInDate } = query;
const safePage = Number(page) || 1;
const safePageSize = Number(pageSize) || 10;
const qb = this.merchantRepo
@@ -86,10 +86,10 @@ export class MerchantService {
const [list, total] = await qb.getManyAndCount();
// 获取当天日期
const today = new Date().toISOString().split('T')[0];
// 使用传入的开始日期,如果没有则使用当天日期
const targetDate = checkInDate || new Date().toISOString().split('T')[0];
// 为每个商家获取第一个房源的当天房价
// 为每个商家获取第一个房源的指定日期房价
const listWithPrice = await Promise.all(
list.map(async (merchant) => {
// 获取商家的第一个已审核通过且在售的房源
@@ -104,11 +104,11 @@ export class MerchantService {
let minPrice = 0;
if (firstRoom) {
// 获取该房源当天的房价
// 获取该房源指定日期的房价
const calendar = await this.roomCalendarRepo.findOne({
where: {
roomId: firstRoom.id,
date: today,
date: targetDate,
status: 'available',
},
});
@@ -210,6 +210,9 @@ export class MerchantService {
debt_amount: 0,
total_income: 0,
total_expense: 0,
total_settlement: 0,
total_withdraw: 0,
pending_settlement: 0,
status: 'active',
});
await this.merchantAccountRepo.save(account);
@@ -37,63 +37,78 @@ export class MerchantOrderController {
return this.orderService.findByMerchant(merchant.id, query);
}
@Post('detail')
@Get(':orderNo')
@ApiOperation({ summary: '商家订单详情' })
async getDetail(
@CurrentSeller('sub') sellerId: number,
@Body('orderId') orderId: number,
@Param('orderNo') orderNo: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
const order = await this.orderService.findById(orderId);
const order = await this.orderService.findOne(orderNo);
if (order.merchantId !== merchant.id) {
throw new NotFoundException('订单不存在');
}
return order;
}
@Put(':id/confirm')
@ApiOperation({ summary: '确认订单' })
async confirm(
@Post('detail')
@ApiOperation({ summary: '商家订单详情(POST)' })
async getDetailPost(
@CurrentSeller('sub') sellerId: number,
@Param('id') id: number,
@Body('orderNo') orderNo: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
return this.orderService.confirm(merchant.id, id);
const order = await this.orderService.findOne(orderNo);
if (order.merchantId !== merchant.id) {
throw new NotFoundException('订单不存在');
}
return order;
}
@Put(':id/reject')
@Put(':orderNo/confirm')
@ApiOperation({ summary: '确认订单' })
async confirm(
@CurrentSeller('sub') sellerId: number,
@Param('orderNo') orderNo: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
return this.orderService.confirm(merchant.id, orderNo);
}
@Put(':orderNo/reject')
@ApiOperation({ summary: '拒绝订单' })
async reject(
@CurrentSeller('sub') sellerId: number,
@Param('id') id: number,
@Param('orderNo') orderNo: string,
@Body('reason') reason: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
return this.orderService.reject(merchant.id, id, reason);
return this.orderService.reject(merchant.id, orderNo, reason);
}
@Put(':id/checkin')
@Put(':orderNo/checkin')
@ApiOperation({ summary: '办理入住' })
async checkin(
@CurrentSeller('sub') sellerId: number,
@Param('id') id: number,
@Param('orderNo') orderNo: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
return this.orderService.checkin(merchant.id, id);
return this.orderService.checkin(merchant.id, orderNo);
}
@Put(':id/checkout')
@Put(':orderNo/checkout')
@ApiOperation({ summary: '确认离店' })
async checkout(
@CurrentSeller('sub') sellerId: number,
@Param('id') id: number,
@Param('orderNo') orderNo: string,
) {
const merchant = await this.profileService.findBySellerId(sellerId);
if (!merchant) throw new NotFoundException('店铺不存在');
return this.orderService.checkout(merchant.id, id);
return this.orderService.checkout(merchant.id, orderNo);
}
}
@@ -36,37 +36,42 @@ export class MerchantOrderService {
return { list, total, page, pageSize, totalPages: Math.ceil(total / pageSize) };
}
async findById(id: number) {
async findOne(identifier: string | number) {
const whereCondition = typeof identifier === 'number'
? { id: identifier }
: { orderNo: identifier };
const order = await this.orderRepo.findOne({
where: { id },
where: whereCondition,
relations: ['room', 'merchant', 'user'],
});
if (!order) throw new NotFoundException('订单不存在');
return order;
}
async confirm(merchantId: number, id: number) {
const order = await this.findById(id);
async confirm(merchantId: number, orderNo: string) {
const order = await this.findOne(orderNo);
if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'pending_confirm') {
throw new BadRequestException('当前订单状态不可确认');
}
await this.orderRepo.update(id, {
await this.orderRepo.update(order.id, {
status: 'pending_checkin',
confirmedAt: new Date(),
});
return { message: '订单已确认' };
}
async reject(merchantId: number, id: number, reason: string) {
const order = await this.findById(id);
async reject(merchantId: number, orderNo: string, reason: string) {
const order = await this.findOne(orderNo);
if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'pending_confirm') {
throw new BadRequestException('当前订单状态不可拒绝');
}
await this.orderRepo.update(id, {
await this.orderRepo.update(order.id, {
status: 'cancelled',
cancelReason: reason,
cancelledAt: new Date(),
@@ -74,22 +79,22 @@ export class MerchantOrderService {
return { message: '订单已拒绝' };
}
async checkin(merchantId: number, id: number) {
const order = await this.findById(id);
async checkin(merchantId: number, orderNo: string) {
const order = await this.findOne(orderNo);
if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'pending_checkin') {
throw new BadRequestException('当前订单状态不可办理入住');
}
await this.orderRepo.update(id, {
await this.orderRepo.update(order.id, {
status: 'checked_in',
checkinAt: new Date(),
});
return { message: '已办理入住' };
}
async checkout(merchantId: number, id: number) {
const order = await this.findById(id);
async checkout(merchantId: number, orderNo: string) {
const order = await this.findOne(orderNo);
if (order.merchantId !== merchantId) throw new ForbiddenException('无权操作此订单');
if (order.status !== 'checked_in') {
throw new BadRequestException('当前订单状态不可确认离店');
@@ -101,7 +106,7 @@ export class MerchantOrderService {
throw new BadRequestException('未到离店日期,不可确认离店');
}
await this.orderRepo.update(id, {
await this.orderRepo.update(order.id, {
status: 'completed',
checkoutAt: new Date(),
});
@@ -79,6 +79,9 @@ export class MerchantProfileService {
debt_amount: 0,
total_income: 0,
total_expense: 0,
total_settlement: 0,
total_withdraw: 0,
pending_settlement: 0,
status: 'active',
});
await this.merchantAccountRepo.save(account);
@@ -62,6 +62,9 @@ export class AccountService {
debt_amount: 0,
total_income: 0,
total_expense: 0,
total_settlement: 0,
total_withdraw: 0,
pending_settlement: 0,
status: 'active',
});
await this.merchantAccountRepo.save(account);