import type { Db } from '../db'; import { isUniqueViolation, RuleError } from './accountRules'; import type { Shop } from './shopScope'; export interface ShopListing extends Shop { active: boolean; } export const SHOP_NAME_MAX = 100; export const SHOP_CODE_MAX = 20; export function createShop(db: Db, input: { name: string; code: string }): Shop { const name = input.name.trim(); const code = input.code.trim(); if (name === '' || name.length > SHOP_NAME_MAX) { throw new RuleError('invalid', `the shop name must be 1 to ${SHOP_NAME_MAX} characters`); } if (code === '' || code.length > SHOP_CODE_MAX || /\s/.test(code)) { throw new RuleError('invalid', `the shop code must be 1 to ${SHOP_CODE_MAX} characters with no spaces`); } const sameName = db.prepare('SELECT 1 FROM shops WHERE active = 1 AND lower(name) = lower(?)').get(name); if (sameName) throw new RuleError('conflict', 'an active shop already has that name'); try { const id = Number(db.prepare('INSERT INTO shops (name, code) VALUES (?, ?)').run(name, code).lastInsertRowid); return { id, name, code }; } catch (e) { if (isUniqueViolation(e)) throw new RuleError('conflict', 'that shop code is already used'); throw e; } } export function listShops(db: Db): ShopListing[] { const rows = db.prepare('SELECT id, name, code, active FROM shops ORDER BY name, id').all() as Array< Shop & { active: number } >; return rows.map((r) => ({ id: r.id, name: r.name, code: r.code, active: r.active === 1 })); }