import * as db from '../../db/numbers.js'; // #region Helpers function requireSelectedCompany(req) { const companyId = req.user.selectedCompanyId; if (companyId == null) { return { error: 'No company selected' }; } return { companyId }; } function numberErrorStatus(error) { if (error.message === 'No company selected') return 400; if (error.message === 'Not authorized') return 403; if (error.message === 'Company not found') return 404; if (error.message === 'Number not found') return 404; if (error.message === 'Invalid number') return 400; return 500; } // #endregion /** * Registers number-sequence routes for the authenticated user's selected company. * @param {import('express').Application} app * @param {string} [basePath=''] */ export function register(app, basePath = '') { /** * @openapi * /number: * get: * tags: [Number] * summary: List number sequences * description: Lists the number sequences of the authenticated user's selected company. * security: * - cookieAuth: [] * x-markdown: number/list.md * responses: * 200: * description: Number sequence list * content: * application/json: * schema: * type: object * properties: * numbers: * type: array * items: * $ref: '#/components/schemas/NumberSequence' * 400: * description: No company selected * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 401: * description: Unauthorized * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 403: * description: Not authorized * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 404: * description: Company not found * content: * application/json: * schema: * $ref: '#/components/schemas/Error' */ // #region GET /number app.get(`${basePath}/number`, async (req, res) => { const selected = requireSelectedCompany(req); if (selected.error) { return res.status(400).json({ error: selected.error }); } try { const numbers = await db.list(req.user.id); res.status(200).json({ numbers }); } catch (error) { const status = numberErrorStatus(error); if (status === 500) console.error('List number sequences failed:', error); res.status(status).json({ error: error.message }); } }); // #endregion /** * @openapi * /number/{id}: * patch: * tags: [Number] * summary: Update number sequence * description: | * Updates sequence settings for the selected company. Only provided fields * are changed (`prefix`, `padding`, `next`). `prefix` is trimmed and must * be at most 50 characters. `padding` must be an integer `>= 0`. `next` * must be an integer `>= 1`. If no field is provided, the row is returned * unchanged. * security: * - cookieAuth: [] * x-markdown: number/update.md * parameters: * - in: path * name: id * required: true * schema: * type: integer * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * prefix: * type: string * padding: * type: integer * minimum: 0 * next: * type: integer * minimum: 1 * example: * prefix: 'A-' * padding: 4 * next: 100 * responses: * 200: * description: Updated number sequence * content: * application/json: * schema: * type: object * properties: * number: * $ref: '#/components/schemas/NumberSequence' * 400: * description: Invalid number, invalid id, or no company selected * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 401: * description: Unauthorized * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 403: * description: Not authorized * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 404: * description: Number sequence or company not found * content: * application/json: * schema: * $ref: '#/components/schemas/Error' */ // #region PATCH /number/:id app.patch(`${basePath}/number/:id`, async (req, res) => { const selected = requireSelectedCompany(req); if (selected.error) { return res.status(400).json({ error: selected.error }); } const id = Number(req.params.id); if (!Number.isInteger(id) || id <= 0) { return res.status(400).json({ error: 'id is required' }); } const body = req.body ?? {}; const input = {}; if (Object.prototype.hasOwnProperty.call(body, 'prefix')) { input.prefix = body.prefix; } if (Object.prototype.hasOwnProperty.call(body, 'padding')) { input.padding = body.padding; } if (Object.prototype.hasOwnProperty.call(body, 'next')) { input.next = body.next; } try { const number = await db.update(req.user.id, id, input); res.status(200).json({ number }); } catch (error) { const status = numberErrorStatus(error); if (status === 500) console.error('Update number sequence failed:', error); res.status(status).json({ error: error.message }); } }); // #endregion }