Files
2026-09-28 23:15:47 +05:30

375 lines
13 KiB
SQL

-- 100kmph MariaDB schema (Drift tablet schema version 6, snake_case).
-- Apply as an admin user. The app user has no DDL and no DELETE.
-- Synced rows are soft-deleted via deleted_at. Do not hard-delete them.
-- No foreign keys: the tablet may push children before parents.
CREATE TABLE IF NOT EXISTS staff_members (
id CHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
pin_hash VARCHAR(255) NOT NULL,
role VARCHAR(64) NOT NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_staff_members_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS shop_settings (
id CHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
address VARCHAR(4000) NOT NULL DEFAULT '',
phone VARCHAR(64) NOT NULL DEFAULT '',
gstin VARCHAR(64) NOT NULL DEFAULT '',
tax_percent DOUBLE NOT NULL DEFAULT 18,
sms_bill_template VARCHAR(4000) NOT NULL,
sms_status_template VARCHAR(4000) NOT NULL,
-- Last-write-wins. v1 does not allocate invoice numbers on the server. Two tablets incrementing this will clash.
next_invoice_number INT NOT NULL DEFAULT 1 COMMENT 'Last-write-wins. v1 does not allocate invoice numbers on the server. Two tablets incrementing this will clash.',
expected_open VARCHAR(16) NOT NULL DEFAULT '09:00',
expected_close VARCHAR(16) NOT NULL DEFAULT '18:00',
late_grace_minutes INT NOT NULL DEFAULT 120,
public_base_url VARCHAR(512) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_shop_settings_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS work_days (
id CHAR(36) NOT NULL,
day_key VARCHAR(32) NOT NULL,
started_at DATETIME(3) NOT NULL,
ended_at DATETIME(3) NULL,
started_by_staff_id CHAR(36) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_work_days_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS attendance_records (
id CHAR(36) NOT NULL,
work_day_id CHAR(36) NOT NULL,
staff_id CHAR(36) NOT NULL,
check_in_at DATETIME(3) NULL,
check_out_at DATETIME(3) NULL,
notes VARCHAR(4000) NOT NULL DEFAULT '',
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_attendance_records_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS short_leaves (
id CHAR(36) NOT NULL,
work_day_id CHAR(36) NOT NULL,
staff_id CHAR(36) NOT NULL,
from_at DATETIME(3) NOT NULL,
to_at DATETIME(3) NOT NULL,
minutes INT NOT NULL,
reason VARCHAR(4000) NOT NULL DEFAULT '',
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_short_leaves_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS overtime_logs (
id CHAR(36) NOT NULL,
work_day_id CHAR(36) NOT NULL,
staff_id CHAR(36) NOT NULL,
from_at DATETIME(3) NULL,
to_at DATETIME(3) NULL,
minutes INT NOT NULL,
reason VARCHAR(4000) NOT NULL DEFAULT '',
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_overtime_logs_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS customers (
id CHAR(36) NOT NULL,
phone VARCHAR(64) NOT NULL,
name VARCHAR(255) NOT NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_customers_phone (phone),
KEY idx_customers_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS vehicles (
id CHAR(36) NOT NULL,
customer_id CHAR(36) NOT NULL,
registration VARCHAR(64) NOT NULL,
vin VARCHAR(64) NOT NULL DEFAULT '',
make VARCHAR(255) NOT NULL DEFAULT '',
model_name VARCHAR(255) NOT NULL DEFAULT '',
`year` INT NULL,
engine_capacity INT NULL,
bike_model_id CHAR(36) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_vehicles_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS job_cards (
id CHAR(36) NOT NULL,
vehicle_id CHAR(36) NOT NULL,
customer_id CHAR(36) NOT NULL,
brought_by_customer_id CHAR(36) NULL,
complaint VARCHAR(4000) NOT NULL,
stage VARCHAR(64) NOT NULL,
engineer_notes VARCHAR(4000) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_job_cards_customer (customer_id),
KEY idx_job_cards_vehicle (vehicle_id),
KEY idx_job_cards_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS odo_readings (
id CHAR(36) NOT NULL,
read_at DATETIME(3) NOT NULL,
vehicle_id CHAR(36) NOT NULL,
reading_km INT NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_odo_readings_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS job_card_events (
id CHAR(36) NOT NULL,
job_card_id CHAR(36) NOT NULL,
stage VARCHAR(64) NOT NULL,
note VARCHAR(4000) NOT NULL DEFAULT '',
`at` DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_job_card_events_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS part_types (
id CHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_part_types_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS bike_models (
id CHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
brand VARCHAR(255) NOT NULL DEFAULT '',
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_bike_models_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS bike_groups (
id CHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
part_type_id CHAR(36) NULL,
code VARCHAR(64) NOT NULL DEFAULT '',
notes VARCHAR(4000) NOT NULL DEFAULT '',
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_bike_groups_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS bike_group_members (
id CHAR(36) NOT NULL,
group_id CHAR(36) NOT NULL,
bike_model_id CHAR(36) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_bike_group_members_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS catalog_parts (
id CHAR(36) NOT NULL,
part_type_id CHAR(36) NOT NULL,
bike_model_id CHAR(36) NULL,
group_id CHAR(36) NULL,
is_universal TINYINT(1) NOT NULL DEFAULT 0,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_catalog_parts_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS catalog_part_models (
id CHAR(36) NOT NULL,
catalog_part_id CHAR(36) NOT NULL,
bike_model_id CHAR(36) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_catalog_part_models_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS part_variants (
id CHAR(36) NOT NULL,
catalog_part_id CHAR(36) NOT NULL,
grade VARCHAR(64) NOT NULL,
brand VARCHAR(255) NOT NULL DEFAULT '',
sku VARCHAR(128) NOT NULL DEFAULT '',
cost DOUBLE NOT NULL DEFAULT 0,
sale_price DOUBLE NOT NULL,
qty_on_hand DOUBLE NOT NULL DEFAULT 0,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_part_variants_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS job_line_items (
id CHAR(36) NOT NULL,
job_card_id CHAR(36) NOT NULL,
kind VARCHAR(64) NOT NULL,
variant_id CHAR(36) NULL,
description VARCHAR(4000) NOT NULL,
qty DOUBLE NOT NULL,
unit_price DOUBLE NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_job_line_items_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS invoices (
id CHAR(36) NOT NULL,
number VARCHAR(64) NOT NULL,
public_token CHAR(36) NOT NULL,
job_card_id CHAR(36) NULL,
customer_id CHAR(36) NULL,
kind VARCHAR(64) NOT NULL,
subtotal DOUBLE NOT NULL,
tax_percent DOUBLE NOT NULL,
tax_amount DOUBLE NOT NULL,
total DOUBLE NOT NULL,
snapshot_json LONGTEXT NOT NULL,
publish_status VARCHAR(64) NOT NULL,
created_at DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uq_invoices_public_token (public_token),
KEY idx_invoices_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS invoice_lines (
id CHAR(36) NOT NULL,
invoice_id CHAR(36) NOT NULL,
description VARCHAR(4000) NOT NULL,
qty DOUBLE NOT NULL,
unit_price DOUBLE NOT NULL,
line_total DOUBLE NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_invoice_lines_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS payments (
id CHAR(36) NOT NULL,
invoice_id CHAR(36) NOT NULL,
method VARCHAR(64) NOT NULL,
amount DOUBLE NOT NULL,
`at` DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_payments_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS demand_logs (
id CHAR(36) NOT NULL,
part_type_id CHAR(36) NOT NULL,
bike_model_id CHAR(36) NOT NULL,
variant_id CHAR(36) NULL,
qty DOUBLE NOT NULL,
reason VARCHAR(4000) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_demand_logs_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS sms_outbox (
id CHAR(36) NOT NULL,
to_phone VARCHAR(64) NOT NULL,
body VARCHAR(4000) NOT NULL,
status VARCHAR(64) NOT NULL,
error VARCHAR(4000) NOT NULL DEFAULT '',
invoice_id CHAR(36) NULL,
job_card_id CHAR(36) NULL,
created_at DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_sms_outbox_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS publish_outbox (
id CHAR(36) NOT NULL,
invoice_id CHAR(36) NOT NULL,
public_token CHAR(36) NOT NULL,
payload_json LONGTEXT NOT NULL,
status VARCHAR(64) NOT NULL,
error VARCHAR(4000) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL,
updated_at DATETIME(3) NOT NULL,
deleted_at DATETIME(3) NULL,
is_dirty TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
KEY idx_publish_outbox_sync (updated_at, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Legacy unauthenticated bill publish. Not a synced table.
-- The posted token is the public token, never invoices.id.
CREATE TABLE IF NOT EXISTS bill_snapshots (
token CHAR(36) NOT NULL,
payload_json LONGTEXT NOT NULL,
updated_at DATETIME(3) NOT NULL,
PRIMARY KEY (token)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;