refactor: extract numbering logic into numbering.service.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,46 +0,0 @@
|
||||
import prisma from '../config/database';
|
||||
|
||||
/**
|
||||
* Atomically get and increment the next sequence number for a document type and year.
|
||||
* Uses the `number_sequences` table with upsert to avoid race conditions.
|
||||
*/
|
||||
export async function nextSequenceNumber(type: string, year: number): Promise<number> {
|
||||
// Use a transaction with a raw query to atomically increment
|
||||
const result = await prisma.$queryRaw<Array<{ last_number: number }>>`
|
||||
INSERT INTO number_sequences (type, year, last_number)
|
||||
VALUES (${type}, ${year}, 1)
|
||||
ON DUPLICATE KEY UPDATE last_number = last_number + 1;
|
||||
SELECT last_number FROM number_sequences WHERE type = ${type} AND year = ${year};
|
||||
`;
|
||||
|
||||
// $queryRaw with multiple statements may not work on all drivers, use a transaction fallback
|
||||
return result[0]?.last_number ?? 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically get and increment the next sequence number using Prisma transaction.
|
||||
* Compatible with all Prisma drivers.
|
||||
*/
|
||||
export async function getNextNumber(type: string, year: number): Promise<number> {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
// Try to find existing sequence
|
||||
const existing = await tx.number_sequences.findFirst({
|
||||
where: { type, year },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
const nextNum = (existing.last_number ?? 0) + 1;
|
||||
await tx.number_sequences.update({
|
||||
where: { id: existing.id },
|
||||
data: { last_number: nextNum },
|
||||
});
|
||||
return nextNum;
|
||||
}
|
||||
|
||||
// Create new sequence
|
||||
await tx.number_sequences.create({
|
||||
data: { type, year, last_number: 1 },
|
||||
});
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user