001 - POS outlets/devices + Cashier role
- Tanggal: 2026-08-07
- DB:
mpcdb (shared Postgres — mpc-be / mpc-be-pos / mpc-admin)
- Ringkas: Rename enum
StaffRole.Receptionist → Cashier; buat tabel pos_outlets + pos_devices dan seed outlet MPC-MAIN.
ALTER (jalankan di DB server)
-- Idempotent; safe to re-run.
DO $$ BEGIN
IF EXISTS (
SELECT 1 FROM pg_enum e
JOIN pg_type t ON e.enumtypid = t.oid
WHERE t.typname = 'StaffRole' AND e.enumlabel = 'Receptionist'
) AND NOT EXISTS (
SELECT 1 FROM pg_enum e
JOIN pg_type t ON e.enumtypid = t.oid
WHERE t.typname = 'StaffRole' AND e.enumlabel = 'Cashier'
) THEN
ALTER TYPE "StaffRole" RENAME VALUE 'Receptionist' TO 'Cashier';
END IF;
END $$;
DO $$ BEGIN
CREATE TYPE "PosOutletStatus" AS ENUM ('Active', 'Inactive');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
CREATE TYPE "PosDeviceStatus" AS ENUM ('Active', 'Revoked');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
CREATE TABLE IF NOT EXISTS pos_outlets (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
code text NOT NULL UNIQUE,
name text NOT NULL,
court_enabled boolean NOT NULL DEFAULT true,
fnb_enabled boolean NOT NULL DEFAULT true,
status "PosOutletStatus" NOT NULL DEFAULT 'Active',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE TABLE IF NOT EXISTS pos_devices (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
outlet_id uuid NOT NULL REFERENCES pos_outlets(id),
name text NOT NULL,
api_key_hash text NOT NULL,
court_enabled boolean NOT NULL DEFAULT true,
fnb_enabled boolean NOT NULL DEFAULT false,
last_seen_at timestamptz,
status "PosDeviceStatus" NOT NULL DEFAULT 'Active',
registered_at timestamptz NOT NULL DEFAULT now(),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
CREATE INDEX IF NOT EXISTS pos_devices_api_key_hash_idx ON pos_devices (api_key_hash);
CREATE INDEX IF NOT EXISTS pos_devices_outlet_id_idx ON pos_devices (outlet_id);
INSERT INTO pos_outlets (code, name, court_enabled, fnb_enabled, status)
VALUES ('MPC-MAIN', 'Metropole Padel Main', true, true, 'Active')
ON CONFLICT (code) DO UPDATE SET
name = EXCLUDED.name,
court_enabled = EXCLUDED.court_enabled,
fnb_enabled = EXCLUDED.fnb_enabled,
status = EXCLUDED.status,
updated_at = now();
Rollback (opsional tapi disarankan)
-- Hati-hati: drop devices dulu (FK). Hanya jika belum ada data produksi penting.
DROP TABLE IF EXISTS pos_devices;
DROP TABLE IF EXISTS pos_outlets;
DROP TYPE IF EXISTS "PosDeviceStatus";
DROP TYPE IF EXISTS "PosOutletStatus";
-- Rename balik hanya jika label Cashier ada dan Receptionist belum ada,
-- dan tidak ada baris staff yang masih memakai Cashier (atau update dulu).
DO $$ BEGIN
IF EXISTS (
SELECT 1 FROM pg_enum e
JOIN pg_type t ON e.enumtypid = t.oid
WHERE t.typname = 'StaffRole' AND e.enumlabel = 'Cashier'
) AND NOT EXISTS (
SELECT 1 FROM pg_enum e
JOIN pg_type t ON e.enumtypid = t.oid
WHERE t.typname = 'StaffRole' AND e.enumlabel = 'Receptionist'
) THEN
ALTER TYPE "StaffRole" RENAME VALUE 'Cashier' TO 'Receptionist';
END IF;
END $$;
Catatan
- Prod: sudah dijalankan lewat
mpc-be-pos EnsureSchema (AUTO_MIGRATE) pada deploy 2026-08-07.
- Duplikat SQL di
mpc-be-pos/scripts/migrate_pos_devices.sql / internal/device/migrate.go — sumber kebenaran untuk ops tetap file ini.
- Dampak:
mpc-admin (Prisma PosOutlet/PosDevice, role Cashier), mpc-be-pos (device auth + JWT), mpc-pos (wizard/login).