import * as db from '../../db/unit.js'; // #region Helpers function requireSelectedCompany(req) { const companyId = req.user.selectedCompanyId; if (companyId == null) { return { error: 'No company selected' }; } return { companyId }; } function unitErrorStatus(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 === 'Unit not found') return 404; if (error.message === 'Invalid unit') return 400; if (error.message === 'Unit in use') return 409; return 500; } // #endregion /** * Registers unit routes for the authenticated user's selected company. * @param {import('express').Application} app * @param {string} [basePath=''] */ export function register(app, basePath = '') { /** * @openapi * /unit: * get: * tags: [Unit] * summary: List units * description: Lists units for the authenticated user's selected company (default-language symbol/name). * security: * - cookieAuth: [] * x-markdown: unit/list.md * responses: * 200: * description: Unit list * content: * application/json: * schema: * type: object * properties: * units: * type: array * items: * $ref: '#/components/schemas/Unit' * 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' * put: * tags: [Unit] * summary: Upsert unit * description: | * Insert or update unit by `si` for the selected company. Upserts `unittext` for the company language. * `basesifactor` must be finite and `> 0`. * security: * - cookieAuth: [] * x-markdown: unit/upsert.md * requestBody: * required: true * content: * application/json: * schema: * type: object * required: [si, basesi, basesifactor, symbol, name] * properties: * si: * type: string * basesi: * type: string * basesifactor: * type: number * symbol: * type: string * name: * type: string * example: * si: l * basesi: l * basesifactor: 1 * symbol: L * name: Liter * responses: * 200: * description: Upserted unit * content: * application/json: * schema: * type: object * properties: * unit: * $ref: '#/components/schemas/Unit' * 400: * description: Invalid unit 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: Company not found * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * delete: * tags: [Unit] * summary: Delete unit * description: Deletes `si` for the selected company. Fails with `Unit in use` if articles still reference it. * security: * - cookieAuth: [] * x-markdown: unit/delete.md * parameters: * - in: query * name: si * required: true * schema: * type: string * responses: * 204: * description: Deleted * 400: * description: Missing si 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: Company or unit not found * content: * application/json: * schema: * $ref: '#/components/schemas/Error' * 409: * description: Unit in use * content: * application/json: * schema: * $ref: '#/components/schemas/Error' */ // #region GET /unit app.get(`${basePath}/unit`, async (req, res) => { const selected = requireSelectedCompany(req); if (selected.error) { return res.status(400).json({ error: selected.error }); } try { const units = await db.list(req.user.id); res.status(200).json({ units }); } catch (error) { const status = unitErrorStatus(error); if (status === 500) console.error('List units failed:', error); res.status(status).json({ error: error.message }); } }); // #endregion // #region PUT /unit app.put(`${basePath}/unit`, async (req, res) => { const selected = requireSelectedCompany(req); if (selected.error) { return res.status(400).json({ error: selected.error }); } const { si, basesi, basesifactor, symbol, name } = req.body ?? {}; try { const unit = await db.upsert(req.user.id, { si, basesi, basesifactor, symbol, name, }); res.status(200).json({ unit }); } catch (error) { const status = unitErrorStatus(error); if (status === 500) console.error('Upsert unit failed:', error); res.status(status).json({ error: error.message }); } }); // #endregion // #region DELETE /unit app.delete(`${basePath}/unit`, async (req, res) => { const selected = requireSelectedCompany(req); if (selected.error) { return res.status(400).json({ error: selected.error }); } const si = typeof req.query.si === 'string' ? req.query.si.trim() : ''; if (!si) { return res.status(400).json({ error: 'si is required' }); } try { await db.remove(req.user.id, si); res.sendStatus(204); } catch (error) { const status = unitErrorStatus(error); if (status === 500) console.error('Delete unit failed:', error); res.status(status).json({ error: error.message }); } }); // #endregion }