40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
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 }));
|
|
}
|