Files
greatbear/pb/migrations/1788500100_menu_items_v3.js
T
tanshu bea6710d38 Menu schema v3: variants as separate products, POS-ready fields
- variants split into their own menu_items whenever price differs
  (name + variant fields; 164 products, 24 variant groups)
- price back to number (whole rupees); no more '449/549' strings
- diet select (veg/nonveg/mixed) instead of nullable bool — PocketBase
  serializes empty bools as false, which misfiled mixed dishes
- new fields for POS: sku (unique GB-CAT-NNN), available (86 toggle),
  tax_category (default food-5-gst)
- migration 1788500100_menu_items_v3 replaces menu_items; resync via
  scripts/update-menu.mjs
- cards render 'Dish – Variant', badges from diet, hide unavailable
2026-09-03 18:39:00 +05:30

81 lines
2.7 KiB
JavaScript

/// <reference path="../pb_data/types.d.ts" />
migrate(
(app) => {
// v3 menu_items: POS-friendly schema. Variants are separate products with
// a numeric rupee price; is_veg replaces the text group; adds sku,
// available and tax_category. The old collection only held the previous
// menu sync, so it is replaced wholesale (records are re-synced by
// scripts/update-menu.mjs).
try {
const oldCollection = app.findCollectionByNameOrId('menu_items')
app.delete(oldCollection)
} catch (e) {
// collection may not exist on a fresh database — nothing to migrate
}
const collection = new Collection({
name: 'menu_items',
type: 'base',
listRule: '',
viewRule: '',
createRule: null,
updateRule: null,
deleteRule: null,
fields: [
{ name: 'uid', type: 'text', required: true },
{ name: 'category', type: 'text', required: true },
{ name: 'name', type: 'text', required: true },
{ name: 'variant', type: 'text' },
{ name: 'description', type: 'text' },
{ name: 'price', type: 'number', required: true },
{ name: 'diet', type: 'select', maxSelect: 1, values: ['veg', 'nonveg', 'mixed'] },
{ name: 'pairing', type: 'text' },
{ name: 'tag', type: 'text' },
{ name: 'image', type: 'text' },
{ name: 'sku', type: 'text' },
{ name: 'available', type: 'bool' },
{ name: 'tax_category', type: 'text' },
{ name: 'sort', type: 'number' },
],
indexes: [
'CREATE UNIQUE INDEX idx_menu_items_uid ON menu_items (uid)',
'CREATE UNIQUE INDEX idx_menu_items_sku ON menu_items (sku) WHERE sku != \'\'',
],
})
return app.save(collection)
},
(app) => {
// Revert to the v2 schema.
try {
const newCollection = app.findCollectionByNameOrId('menu_items')
app.delete(newCollection)
} catch (e) {
// nothing to revert
}
const collection = new Collection({
name: 'menu_items',
type: 'base',
listRule: '',
viewRule: '',
createRule: null,
updateRule: null,
deleteRule: null,
fields: [
{ name: 'uid', type: 'text', required: true },
{ name: 'category', type: 'text', required: true },
{ name: 'name', type: 'text', required: true },
{ name: 'description', type: 'text' },
{ name: 'price', type: 'text' },
{ name: 'pairing', type: 'text' },
{ name: 'tag', type: 'text' },
{ name: 'image', type: 'text' },
{ name: 'group', type: 'text' },
{ name: 'sort', type: 'number' },
],
indexes: ['CREATE UNIQUE INDEX idx_menu_items_uid ON menu_items (uid)'],
})
return app.save(collection)
}
)