@@ -5,6 +5,7 @@ import {
|
||||
ConflictException,
|
||||
} from '@nestjs/common';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { AuditService } from '../audit/audit.service';
|
||||
import { RealtimeService } from '../realtime/realtime.service';
|
||||
@@ -35,7 +36,7 @@ export class CommandsService {
|
||||
});
|
||||
}
|
||||
|
||||
// Use transaction for consistency
|
||||
// Serializable so two simultaneous requests for the same tab can't both pass the pending check
|
||||
const result = await this.prisma.$transaction(async (tx) => {
|
||||
// Resolve tab ownership
|
||||
const ownership = await tx.tabOwnership.findUnique({
|
||||
@@ -93,6 +94,8 @@ export class CommandsService {
|
||||
venueId,
|
||||
deviceId: device.id,
|
||||
targetTabId: dto.tabId,
|
||||
customerName: snapshot?.customerName ?? null,
|
||||
amountInCents: snapshot?.totalInCents ?? null,
|
||||
type: dto.type || 'close_tab',
|
||||
expectedVersion: dto.expectedVersion,
|
||||
paymentMethod: dto.paymentMethod,
|
||||
@@ -130,6 +133,14 @@ export class CommandsService {
|
||||
status: command.status,
|
||||
...warning,
|
||||
};
|
||||
}, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }).catch((error) => {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2034') {
|
||||
throw new ConflictException({
|
||||
code: 'command_already_pending',
|
||||
message: 'A command for this tab is already pending',
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
|
||||
this.realtime.notify(venueId, 'commands');
|
||||
@@ -152,6 +163,8 @@ export class CommandsService {
|
||||
select: {
|
||||
id: true,
|
||||
targetTabId: true,
|
||||
customerName: true,
|
||||
amountInCents: true,
|
||||
type: true,
|
||||
status: true,
|
||||
paymentMethod: true,
|
||||
@@ -173,6 +186,8 @@ export class CommandsService {
|
||||
commands: commands.map((c) => ({
|
||||
id: c.id,
|
||||
tabId: c.targetTabId,
|
||||
customerName: c.customerName,
|
||||
amountInCents: c.amountInCents,
|
||||
type: c.type,
|
||||
status: c.status,
|
||||
paymentMethod: c.paymentMethod,
|
||||
|
||||
Reference in New Issue
Block a user