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:
@@ -6,6 +6,7 @@ import { success, error, parseId } from '../../utils/response';
|
||||
import { parsePagination, buildPaginationMeta } from '../../utils/pagination';
|
||||
import { parseBody } from '../../schemas/common';
|
||||
import { CreateQuotationSchema, UpdateQuotationSchema } from '../../schemas/offers.schema';
|
||||
import { generateOfferNumber } from '../../services/numbering.service';
|
||||
|
||||
|
||||
interface QuotationItemInput { description?: string; item_description?: string; quantity?: number; unit?: string; unit_price?: number; is_included_in_total?: boolean; position?: number }
|
||||
@@ -68,19 +69,7 @@ export default async function quotationsRoutes(fastify: FastifyInstance): Promis
|
||||
|
||||
// GET /api/admin/offers/next-number
|
||||
fastify.get('/next-number', { preHandler: requirePermission('offers.create') }, async (_request, reply) => {
|
||||
const settings = await prisma.company_settings.findFirst({ select: { quotation_prefix: true } });
|
||||
const prefix = settings?.quotation_prefix || 'NA';
|
||||
const year = new Date().getFullYear();
|
||||
const likePattern = `${year}/${prefix}/%`;
|
||||
|
||||
// Match PHP logic: find MAX number from existing quotations
|
||||
const result = await prisma.$queryRaw<[{ max_num: bigint | null }]>`
|
||||
SELECT COALESCE(MAX(CAST(SUBSTRING_INDEX(quotation_number, '/', -1) AS UNSIGNED)), 0) as max_num
|
||||
FROM quotations
|
||||
WHERE quotation_number LIKE ${likePattern}
|
||||
`;
|
||||
const nextNum = Number(result[0]?.max_num ?? 0) + 1;
|
||||
const number = `${year}/${prefix}/${String(nextNum).padStart(3, '0')}`;
|
||||
const number = await generateOfferNumber();
|
||||
return success(reply, { number, next_number: number });
|
||||
});
|
||||
|
||||
@@ -94,21 +83,11 @@ export default async function quotationsRoutes(fastify: FastifyInstance): Promis
|
||||
});
|
||||
if (!original) return error(reply, 'Nabídka nenalezena', 404);
|
||||
|
||||
// Get next number by querying MAX from existing quotations (matches PHP logic)
|
||||
const settings = await prisma.company_settings.findFirst({ select: { quotation_prefix: true } });
|
||||
const qPrefix = settings?.quotation_prefix || 'NA';
|
||||
const year = new Date().getFullYear();
|
||||
const likePattern = `${year}/${qPrefix}/%`;
|
||||
const result = await prisma.$queryRaw<[{ max_num: bigint | null }]>`
|
||||
SELECT COALESCE(MAX(CAST(SUBSTRING_INDEX(quotation_number, '/', -1) AS UNSIGNED)), 0) as max_num
|
||||
FROM quotations
|
||||
WHERE quotation_number LIKE ${likePattern}
|
||||
`;
|
||||
const nextNum = Number(result[0]?.max_num ?? 0) + 1;
|
||||
const nextOfferNumber = await generateOfferNumber();
|
||||
|
||||
const copy = await prisma.quotations.create({
|
||||
data: {
|
||||
quotation_number: `${year}/${qPrefix}/${String(nextNum).padStart(3, '0')}`,
|
||||
quotation_number: nextOfferNumber,
|
||||
project_code: original.project_code,
|
||||
customer_id: original.customer_id,
|
||||
valid_until: null,
|
||||
|
||||
Reference in New Issue
Block a user