feat(numbering): projects get their own dedicated number sequence (decoupled from orders)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-09 19:24:51 +02:00
parent 9e9aacdf0b
commit ed9ea52a44
5 changed files with 148 additions and 22 deletions

View File

@@ -6,6 +6,9 @@ import {
isSharedNumberTaken,
previewOfferNumber,
isOfferNumberTaken,
generateProjectNumber,
previewProjectNumber,
isProjectNumberTaken,
} from "../services/numbering.service";
import prisma from "../config/database";
@@ -77,6 +80,38 @@ describe("generateSharedNumber", () => {
});
});
describe("generateProjectNumber", () => {
beforeEach(async () => {
await prisma.number_sequences.deleteMany({ where: { type: "project" } });
});
afterEach(async () => {
await prisma.number_sequences.deleteMany({ where: { type: "project" } });
});
it("returns a non-empty string", async () => {
const num = await generateProjectNumber();
expect(typeof num).toBe("string");
expect(num.length).toBeGreaterThan(0);
});
it("increments the sequence by exactly 1 and preserves the year/format", async () => {
// Seed high so neither generated number collides with a real project →
// the skip-taken retry never fires and the increment is strictly +1.
await seedSequence("project", 900000);
const num1 = await generateProjectNumber();
const num2 = await generateProjectNumber();
assertStrictIncrement(num1, num2);
});
it("previewProjectNumber returns a number not yet taken by a project", async () => {
const preview = await previewProjectNumber();
expect(typeof preview).toBe("string");
expect(preview.length).toBeGreaterThan(0);
expect(await isProjectNumberTaken(preview)).toBe(false);
});
});
describe("generateOfferNumber", () => {
beforeEach(async () => {
await prisma.number_sequences.deleteMany({ where: { type: "offer" } });