88 lines
3.3 KiB
TypeScript
88 lines
3.3 KiB
TypeScript
import { beforeEach, describe, expect, it } from 'vitest';
|
|
import type { Db } from '../db';
|
|
import { makeDb, seedFixture, seedOrder, type Fixture } from '../testing/helpers';
|
|
import { RuleError } from './accountRules';
|
|
import { cancelOrder, removeLine, setLineQty } from './orderEdit';
|
|
import { getUserById } from './users';
|
|
|
|
let db: Db;
|
|
let f: Fixture;
|
|
let orderId: number;
|
|
const shopUser = () => getUserById(db, f.shopUser.id)!;
|
|
const lines = () =>
|
|
db.prepare('SELECT ending, qty FROM order_lines WHERE order_id = ? ORDER BY ending').all(orderId) as Array<{ ending: string; qty: number }>;
|
|
const order = () =>
|
|
db.prepare('SELECT status, edited_at FROM orders WHERE id = ?').get(orderId) as { status: string; edited_at: string | null };
|
|
|
|
beforeEach(() => {
|
|
db = makeDb();
|
|
f = seedFixture(db);
|
|
orderId = seedOrder(db, { shopId: f.shops.a, userId: f.shopUser.id, date: '2026-11-02', lines: [['1234', 2], ['1234', 3], ['5678', 1]] });
|
|
});
|
|
|
|
describe('changing a quantity', () => {
|
|
it('replaces every line of that ending with one and marks the order edited', () => {
|
|
setLineQty(db, shopUser(), orderId, '1234', 7);
|
|
expect(lines()).toEqual([{ ending: '1234', qty: 7 }, { ending: '5678', qty: 1 }]);
|
|
expect(order().edited_at).not.toBeNull();
|
|
});
|
|
|
|
it('refuses a quantity outside 1 to 999', () => {
|
|
for (const qty of [0, -1, 1000, 1.5]) expect(() => setLineQty(db, shopUser(), orderId, '1234', qty)).toThrow(RuleError);
|
|
expect(order().edited_at).toBeNull();
|
|
});
|
|
|
|
it('refuses an ending that is not in the order', () => {
|
|
expect(() => setLineQty(db, shopUser(), orderId, '9999', 1)).toThrow(RuleError);
|
|
});
|
|
});
|
|
|
|
describe('removing an ending', () => {
|
|
it('removes every line of it', () => {
|
|
removeLine(db, shopUser(), orderId, '1234');
|
|
expect(lines()).toEqual([{ ending: '5678', qty: 1 }]);
|
|
expect(order()).toMatchObject({ status: 'confirmed' });
|
|
});
|
|
|
|
it('cancels the order when its last ending goes', () => {
|
|
removeLine(db, shopUser(), orderId, '1234');
|
|
removeLine(db, shopUser(), orderId, '5678');
|
|
expect(order().status).toBe('cancelled');
|
|
});
|
|
});
|
|
|
|
describe('cancelling an order', () => {
|
|
it('cancels it and keeps the record', () => {
|
|
cancelOrder(db, shopUser(), orderId);
|
|
expect(order().status).toBe('cancelled');
|
|
expect(lines()).toHaveLength(3);
|
|
});
|
|
|
|
it('cannot be done twice', () => {
|
|
cancelOrder(db, shopUser(), orderId);
|
|
expect(() => cancelOrder(db, shopUser(), orderId)).toThrow(RuleError);
|
|
});
|
|
});
|
|
|
|
describe('who may edit', () => {
|
|
it('lets an admin edit any order', () => {
|
|
cancelOrder(db, getUserById(db, f.admin.id)!, orderId);
|
|
expect(order().status).toBe('cancelled');
|
|
});
|
|
|
|
it('refuses a user of another shop, as if the order did not exist', () => {
|
|
const other = seedOrder(db, { shopId: f.shops.b, userId: f.multiUser.id, date: '2026-11-02', lines: [['0001', 1]] });
|
|
expect(() => cancelOrder(db, shopUser(), other)).toThrow(/order not found/);
|
|
});
|
|
|
|
it('refuses an inactive user', () => {
|
|
expect(() => cancelOrder(db, getUserById(db, f.disabledUser.id)!, orderId)).toThrow(RuleError);
|
|
});
|
|
|
|
it('still lets a user edit an order of a shop that was switched off', () => {
|
|
db.prepare('UPDATE shops SET active = 0 WHERE id = ?').run(f.shops.a);
|
|
setLineQty(db, shopUser(), orderId, '5678', 4);
|
|
expect(lines()).toContainEqual({ ending: '5678', qty: 4 });
|
|
});
|
|
});
|